{"version":3,"file":"charts-main.js","names":[],"sources":["../../../../frontend/charts/ChartApi.ts","../../../../frontend/charts/Technicals.ts","../../../../frontend/charts/TechnicalsView.ts","../../../../frontend/charts/workspace/DrawingToolbox.ts","../../../../frontend/charts/workspace/FrameTask.ts","../../../../frontend/charts/workspace/ids.ts","../../../../frontend/zero/calendar.ts","../../../../frontend/zero/maps.ts","../../../../frontend/zero/matrices.ts","../../../../frontend/zero/arrays.ts","../../../../frontend/zero/builtins.ts","../../../../frontend/zero/pivots.ts","../../../../frontend/zero/technical.ts","../../../../frontend/zero/wasm.ts","../../../../frontend/zero/ScriptLibrary.ts","../../../../frontend/zero/main.ts","../../../../frontend/charts/ChartAppearancePanel.ts","../../../../frontend/charts/DenseChartOptions.ts","../../../../frontend/charts/WatchlistModel.ts","../../../../frontend/charts/Watchlist.ts","../../../../frontend/charts/ContextMenu.ts","../../../../frontend/charts/Replay.ts","../../../../frontend/charts/IndicatorPane.ts","../../../../frontend/charts/LabApi.ts","../../../../frontend/charts/IndicatorControls.ts","../../../../frontend/charts/IndicatorLineLegend.ts","../../../../frontend/charts/IndicatorFillPrimitive.ts","../../../../frontend/charts/VisiblePriceScaleRails.ts","../../../../frontend/charts/SeriesManager.ts","../../../../frontend/charts/BackgroundRunIndex.ts","../../../../frontend/charts/IndicatorBackgroundLayer.ts","../../../../frontend/charts/ChartApp.ts","../../../../frontend/charts/IndicatorSettingsPanel.ts","../../../../frontend/charts/IndicatorList.ts","../../../../frontend/charts/workspace/DrawingLayer.ts","../../../../frontend/charts/workspace/ChartWorkspace.ts","../../../../frontend/charts/main.ts"],"sourcesContent":["import type { CandlestickData, Time } from \"lightweight-charts\";\r\n\r\nexport type Candle = CandlestickData<Time> & { volume?: number };\r\n\r\nexport function chartTime(time: Time): number {\r\n    if (typeof time === \"number\") return time;\r\n    if (typeof time === \"string\") return Date.parse(time) / 1000;\r\n    return Date.UTC(time.year, time.month - 1, time.day) / 1000;\r\n}\r\n\r\nexport type DataUrlBuilder = (symbol: string, timeframe: string) => string;\r\n\r\nexport class ChartApi {\r\n    private readonly dataUrlBuilder: DataUrlBuilder;\r\n\r\n    constructor(dataUrlBuilder: DataUrlBuilder) {\r\n        this.dataUrlBuilder = dataUrlBuilder;\r\n    }\r\n\r\n    public async fetchCandles(\r\n        symbol: string,\r\n        timeframe: string,\r\n        limit = 20_000,\r\n        signal?: AbortSignal,\r\n    ): Promise<Candle[]> {\r\n        const cleanSymbol = symbol.trim().toUpperCase();\r\n\r\n        if (!cleanSymbol) {\r\n            throw new Error(\"Symbol is empty.\");\r\n        }\r\n\r\n        const rawUrl =\r\n            this.dataUrlBuilder(\r\n                cleanSymbol,\r\n                timeframe,\r\n            );\r\n\r\n        const url =\r\n            new URL(\r\n                rawUrl,\r\n                window.location.href,\r\n            );\r\n\r\n        url.searchParams.set(\r\n            \"limit\",\r\n            String(limit),\r\n        );\r\n\r\n        const response =\r\n            await fetch(\r\n                url.toString(),\r\n                {\r\n                    credentials: \"same-origin\",\r\n                    signal,\r\n                },\r\n            );\r\n\r\n        if (!response.ok) {\r\n            const detail = await response.json().catch(() => null);\r\n            throw new Error(typeof detail?.error === \"string\" ? detail.error : `Data request failed: ${response.status} ${response.statusText}`);\r\n        }\r\n\r\n        const data =\r\n            await response.json();\r\n\r\n        if (!Array.isArray(data)) {\r\n            throw new Error(\r\n                \"Invalid candle data response. \" +\r\n                \"Expected an array.\",\r\n            );\r\n        }\r\n\r\n        return data as Candle[];\r\n    }\r\n}","import type { Candle } from \"./ChartApi\";\n\nexport const TECHNICALS_BAR_LIMIT = 1000;\nexport type Vote = \"Sell\" | \"Neutral\" | \"Buy\";\nexport interface TechnicalReading {\n    name: string;\n    value: number | null;\n    vote: Vote | null;\n    digits: number;\n}\n\nexport function summarizeTechnicals(readings: readonly TechnicalReading[]) {\n    const counts = { Sell: 0, Neutral: 0, Buy: 0 };\n    for (const { vote } of readings) if (vote !== null) counts[vote]++;\n    const total = counts.Sell + counts.Neutral + counts.Buy;\n    const score = total ? (counts.Buy - counts.Sell) / total : 0;\n    const label = !total ? \"Not enough data\" : score > .6 ? \"Strong buy\" : score > .2 ? \"Buy\" : score < -.6 ? \"Strong sell\" : score < -.2 ? \"Sell\" : \"Neutral\";\n    return { counts, total, score, label };\n}\n\nconst mean = (values: readonly number[]): number => values.reduce((sum, value) => sum + value, 0) / values.length;\nconst direction = (delta: number, reference = 1): Vote => {\n    const tolerance = 1e-10 * Math.max(Math.abs(reference), 1);\n    return delta > tolerance ? \"Buy\" : delta < -tolerance ? \"Sell\" : \"Neutral\";\n};\nconst zones = (value: number, low: number, high: number): Vote => value < low ? \"Buy\" : value > high ? \"Sell\" : \"Neutral\";\n\nfunction ema(values: readonly number[], period: number): number[] {\n    if (values.length < period) return [];\n    const alpha = 2 / (period + 1);\n    const result = [mean(values.slice(0, period))];\n    for (let i = period; i < values.length; i++) {\n        const previous = result[result.length - 1];\n        result.push(previous + alpha * (values[i] - previous));\n    }\n    return result;\n}\n\nfunction alma(values: readonly number[], period: number): number {\n    const offset = .85 * (period - 1), spread = period / 6;\n    let weighted = 0, weights = 0;\n    for (let i = 0; i < period; i++) {\n        const weight = Math.exp(-((i - offset) ** 2) / (2 * spread ** 2));\n        weighted += values[values.length - period + i] * weight;\n        weights += weight;\n    }\n    return weighted / weights;\n}\n\nfunction rsi(values: readonly number[], period: number): number | null {\n    if (values.length <= period) return null;\n    let gain = 0, loss = 0;\n    for (let i = 1; i <= period; i++) {\n        const change = values[i] - values[i - 1];\n        gain += Math.max(change, 0) / period;\n        loss += Math.max(-change, 0) / period;\n    }\n    for (let i = period + 1; i < values.length; i++) {\n        const change = values[i] - values[i - 1];\n        gain = (gain * (period - 1) + Math.max(change, 0)) / period;\n        loss = (loss * (period - 1) + Math.max(-change, 0)) / period;\n    }\n    return loss === 0 ? (gain === 0 ? 50 : 100) : 100 - 100 / (1 + gain / loss);\n}\n\n/** Calculate the latest readings from an ascending candle window. Each available reading gets one vote. */\nexport function calculateTechnicals(candles: readonly Candle[]) {\n    const bars = candles.slice(-TECHNICALS_BAR_LIMIT);\n    const closes = bars.map(bar => bar.close);\n    const last = bars[bars.length - 1];\n    const close = last?.close ?? 0;\n    const priceDigits = Math.abs(close) < 10 ? 5 : Math.abs(close) < 1000 ? 3 : 2;\n    const reading = (name: string, value: number | null, vote: (value: number) => Vote, digits = 2): TechnicalReading => {\n        if (value === null || !Number.isFinite(value)) return { name, value: null, vote: null, digits };\n        return { name, value, vote: vote(value), digits };\n    };\n    const averages: TechnicalReading[] = [];\n    for (const period of [10, 20, 50, 200]) {\n        const exponential = ema(closes, period);\n        const simple = closes.length >= period ? mean(closes.slice(-period)) : null;\n        const priceVote = (value: number) => direction(close - value, close);\n        averages.push(reading(`EMA (${period})`, exponential[exponential.length - 1] ?? null, priceVote, priceDigits));\n        averages.push(reading(`SMA (${period})`, simple, priceVote, priceDigits));\n    }\n    for (const period of [9, 20]) {\n        averages.push(reading(`ALMA (${period})`, closes.length >= period ? alma(closes, period) : null,\n            value => direction(close - value, close), priceDigits));\n    }\n\n    const fast = ema(closes, 12), slow = ema(closes, 26);\n    const macd = slow.map((value, i) => fast[i + 14] - value);\n    const signal = ema(macd, 9);\n    const histogram = signal.length ? macd[macd.length - 1] - signal[signal.length - 1] : null;\n    const stochasticWindow = bars.slice(-14);\n    const high = Math.max(...stochasticWindow.map(bar => bar.high));\n    const low = Math.min(...stochasticWindow.map(bar => bar.low));\n    const stochastic = bars.length < 14 ? null : high === low ? 50 : 100 * (close - low) / (high - low);\n    const typical = bars.slice(-20).map(bar => (bar.high + bar.low + bar.close) / 3);\n    const center = mean(typical), deviation = mean(typical.map(value => Math.abs(value - center)));\n    const cci = bars.length < 20 ? null : deviation <= 1e-12 ? 0 : (typical[typical.length - 1] - center) / (.015 * deviation);\n    const momentum = closes.length > 10 ? close - closes[closes.length - 11] : null;\n    const oscillators = [\n        reading(\"RSI (14)\", rsi(closes, 14), value => zones(value, 30, 70)),\n        reading(\"Stochastic %K (14)\", stochastic, value => zones(value, 20, 80)),\n        reading(\"CCI (20)\", cci, value => zones(value, -100, 100)),\n        reading(\"Momentum (10)\", momentum, value => direction(value, close), priceDigits + 1),\n        reading(\"MACD histogram (12, 26, 9)\", histogram, value => direction(value, close), priceDigits + 1),\n    ];\n    return { averages, oscillators, last, previous: bars[bars.length - 2], bars: bars.length, priceDigits };\n}\n","import type { Time } from \"lightweight-charts\";\nimport type { Candle, ChartApi } from \"./ChartApi\";\nimport { calculateTechnicals, summarizeTechnicals, TECHNICALS_BAR_LIMIT, type TechnicalReading, type Vote } from \"./Technicals.ts\";\nimport { TIMEFRAMES } from \"./workspace/WorkspaceState\";\nimport { toolIcon } from \"./workspace/ToolIcons\";\n\nexport interface TechnicalsSource {\n    symbol: string;\n    timeframe: string;\n    candles: readonly Candle[];\n    replaying: boolean;\n}\n\nconst intervals = TIMEFRAMES.filter(timeframe => timeframe !== \"1mo\");\nconst votes: Vote[] = [\"Sell\", \"Neutral\", \"Buy\"];\nconst dateFormat = new Intl.DateTimeFormat(\"en-GB\", { dateStyle: \"medium\", timeStyle: \"short\", timeZone: \"UTC\" });\nconst formatTime = (time: Time): string => {\n    const date = typeof time === \"number\" ? new Date(time * 1000) : typeof time === \"string\" ? new Date(time) : new Date(Date.UTC(time.year, time.month - 1, time.day));\n    return Number.isNaN(date.getTime()) ? \"\" : `${dateFormat.format(date)} UTC`;\n};\nconst intervalName = (timeframe: string): string => timeframe.replace(/wk$/, \"w\");\n\nfunction gauge(title: string, readings: readonly TechnicalReading[], featured = false): HTMLElement {\n    const { counts, total, score, label } = summarizeTechnicals(readings);\n    const point = (angle: number, radius: number) => {\n        const radians = angle * Math.PI / 180;\n        return `${(110 + radius * Math.cos(radians)).toFixed(2)} ${(108 - radius * Math.sin(radians)).toFixed(2)}`;\n    };\n    const segments = [\"sell-strong\", \"sell\", \"neutral\", \"buy\", \"buy-strong\"].map((name, i) => {\n        const angle = 180 - i * 36;\n        return `<path class=\"gauge-${name}\" d=\"M ${point(angle - 2.8, 84)} A 84 84 0 0 1 ${point(angle - 33.2, 84)}\"/>`;\n    }).join(\"\");\n    const needle = total ? `<path class=\"gauge-needle\" d=\"M 110 108 L ${point(90 - score * 90, 65)}\"/><circle class=\"gauge-hub\" cx=\"110\" cy=\"108\" r=\"5\"/>` : \"\";\n    const card = document.createElement(\"section\");\n    card.className = `technicals-gauge${featured ? \" technicals-gauge-featured\" : \"\"}`;\n    card.dataset.vote = score < -.2 ? \"Sell\" : score > .2 ? \"Buy\" : \"Neutral\";\n    card.innerHTML = `<h2>${title}</h2>\n        <svg viewBox=\"0 0 220 124\" aria-hidden=\"true\" focusable=\"false\">${segments}${needle}</svg>\n        <div class=\"technicals-gauge-verdict\">${label}</div>\n        <dl class=\"technicals-votes\">${votes.map(vote => `<div data-vote=\"${vote}\"><dt>${vote}</dt><dd>${counts[vote]}</dd></div>`).join(\"\")}</dl>`;\n    return card;\n}\n\nfunction readingsTable(title: string, readings: readonly TechnicalReading[]): HTMLElement {\n    const card = document.createElement(\"section\");\n    card.className = \"technicals-table-card\";\n    card.innerHTML = `<h2>${title}</h2><table aria-label=\"${title}\"><thead><tr><th scope=\"col\">Indicator</th><th scope=\"col\">Value</th><th scope=\"col\">Signal</th></tr></thead><tbody></tbody></table>`;\n    const body = card.querySelector(\"tbody\")!;\n    for (const reading of readings) {\n        const row = body.insertRow();\n        const name = document.createElement(\"th\");\n        name.scope = \"row\";\n        name.textContent = reading.name;\n        row.append(name);\n        row.insertCell().textContent = reading.value === null ? \"—\" : reading.value.toFixed(reading.digits);\n        const signal = document.createElement(\"span\");\n        signal.className = \"technicals-signal\";\n        signal.dataset.vote = reading.vote ?? \"Neutral\";\n        signal.textContent = reading.vote ?? \"—\";\n        row.insertCell().append(signal);\n    }\n    return card;\n}\n\nexport class TechnicalsView {\n    private source?: TechnicalsSource;\n    private timeframe = \"1d\";\n    private request?: AbortController;\n    private readonly heading: HTMLElement;\n    private readonly quote: HTMLElement;\n    private readonly description: HTMLElement;\n    private readonly results: HTMLElement;\n    private readonly status: HTMLElement;\n    private readonly intervalButtons = new Map<string, HTMLButtonElement>();\n\n    constructor(private readonly root: HTMLElement, private readonly trigger: HTMLButtonElement, private readonly api: ChartApi,\n        private readonly activeSource: () => TechnicalsSource | undefined, private readonly onVisibilityChange: (open: boolean) => void) {\n        root.innerHTML = `<div class=\"technicals-content\">\n            <div class=\"technicals-intro\">\n                <div><span class=\"eyebrow\">MARKET SNAPSHOT</span><h1 id=\"technicals-heading\" tabindex=\"-1\">Technicals</h1><p class=\"technicals-description\"></p></div>\n                <div class=\"technicals-intro-actions\"><div class=\"technicals-quote\" hidden></div><button type=\"button\" class=\"workspace-button technicals-back\">${toolIcon(\"back\")} Back to charts</button></div>\n            </div>\n            <div class=\"technicals-timeframes\" role=\"group\" aria-label=\"Technicals interval\"></div>\n            <div class=\"technicals-status\" role=\"status\" hidden></div>\n            <div class=\"technicals-results\"></div>\n            <details class=\"technicals-method\" hidden><summary>How the signals are calculated</summary>\n                <p>Each available indicator gets one vote. The gauges use (Buy − Sell) ÷ total votes. A score beyond ±0.2 is Buy or Sell, and beyond ±0.6 is Strong buy or Strong sell.</p>\n                <p>Moving averages compare the last close with the average. RSI, Stochastic %K, and CCI vote Buy below 30, 20, and −100, or Sell above 70, 80, and 100. Momentum and the MACD histogram use the sign of their latest value. ALMA uses offset 0.85 and sigma 6.</p>\n            </details>\n        </div>`;\n        this.heading = root.querySelector(\"h1\")!;\n        this.quote = root.querySelector(\".technicals-quote\")!;\n        this.description = root.querySelector(\".technicals-description\")!;\n        this.results = root.querySelector(\".technicals-results\")!;\n        this.status = root.querySelector(\".technicals-status\")!;\n        const group = root.querySelector(\".technicals-timeframes\")!;\n        for (const timeframe of intervals) {\n            const button = document.createElement(\"button\");\n            button.type = \"button\";\n            button.className = \"workspace-button\";\n            button.textContent = intervalName(timeframe);\n            button.setAttribute(\"aria-pressed\", \"false\");\n            button.addEventListener(\"click\", () => { void this.load(timeframe); });\n            this.intervalButtons.set(timeframe, button);\n            group.append(button);\n        }\n        trigger.innerHTML = toolIcon(\"technicals\") + \"Technicals\";\n        trigger.addEventListener(\"click\", () => { if (this.isOpen) this.close(); else this.open(); });\n        root.querySelector(\".technicals-back\")!.addEventListener(\"click\", () => this.close());\n        root.addEventListener(\"keydown\", event => { if (event.key === \"Escape\") { event.preventDefault(); this.close(); } });\n    }\n\n    public get isOpen(): boolean { return !this.root.hidden; }\n\n    private open(): void {\n        this.source = this.activeSource();\n        if (!this.source) return;\n        this.root.hidden = false;\n        this.trigger.setAttribute(\"aria-pressed\", \"true\");\n        this.heading.textContent = `${this.source.symbol} Technicals`;\n        this.onVisibilityChange(true);\n        this.heading.focus({ preventScroll: true });\n        const timeframe = intervals.includes(this.source.timeframe) ? this.source.timeframe : \"1d\";\n        void this.load(timeframe);\n    }\n\n    private close(): void {\n        this.request?.abort();\n        this.request = undefined;\n        this.source = undefined;\n        this.root.hidden = true;\n        this.trigger.setAttribute(\"aria-pressed\", \"false\");\n        this.onVisibilityChange(false);\n        this.trigger.focus({ preventScroll: true });\n    }\n\n    private async load(timeframe: string): Promise<void> {\n        const source = this.source;\n        if (!source || (source.replaying && timeframe !== source.timeframe)) return;\n        this.request?.abort();\n        const request = new AbortController();\n        this.request = request;\n        this.timeframe = timeframe;\n        for (const [interval, button] of this.intervalButtons) {\n            button.setAttribute(\"aria-pressed\", String(interval === timeframe));\n            button.disabled = source.replaying && interval !== source.timeframe;\n        }\n        this.root.querySelector<HTMLElement>(\".technicals-method\")!.hidden = true;\n        this.results.replaceChildren();\n        this.quote.hidden = true;\n        this.status.hidden = false;\n        this.status.textContent = `Loading ${source.symbol} · ${intervalName(timeframe)}…`;\n        this.description.textContent = source.replaying ? \"Replay snapshot · intervals are locked to the replay chart.\" : \"Indicator readings from your chart data.\";\n        try {\n            const candles = timeframe === source.timeframe && (source.candles.length || source.replaying)\n                ? source.candles\n                : await this.api.fetchCandles(source.symbol, timeframe, TECHNICALS_BAR_LIMIT, request.signal);\n            if (request.signal.aborted || this.request !== request) return;\n            if (!candles.length) throw new Error(\"This interval has no candle data.\");\n            this.render(candles);\n        } catch {\n            if (request.signal.aborted || this.request !== request) return;\n            const message = document.createElement(\"p\");\n            message.textContent = `Could not load ${source.symbol} · ${intervalName(timeframe)}. Check that this interval has a candle dataset.`;\n            const retry = document.createElement(\"button\");\n            retry.type = \"button\";\n            retry.className = \"workspace-button\";\n            retry.textContent = \"Retry\";\n            retry.addEventListener(\"click\", () => { void this.load(timeframe); });\n            this.status.replaceChildren(message, retry);\n        }\n    }\n\n    private render(candles: readonly Candle[]): void {\n        const { averages, oscillators, last, previous, bars, priceDigits } = calculateTechnicals(candles);\n        if (!last) return;\n        this.status.hidden = true;\n        this.quote.hidden = false;\n        const price = document.createElement(\"strong\");\n        price.textContent = last.close.toFixed(priceDigits);\n        const caption = document.createElement(\"span\");\n        caption.textContent = `Last close · ${intervalName(this.timeframe)}`;\n        this.quote.replaceChildren(price, caption);\n        if (previous?.close) {\n            const change = 100 * (last.close / previous.close - 1);\n            const delta = document.createElement(\"span\");\n            delta.dataset.vote = change > 0 ? \"Buy\" : change < 0 ? \"Sell\" : \"Neutral\";\n            delta.textContent = `${change > 0 ? \"+\" : \"\"}${change.toFixed(2)}% vs previous bar`;\n            this.quote.append(delta);\n        }\n        this.description.textContent = `${this.source?.replaying ? \"Replay snapshot · \" : \"\"}${bars.toLocaleString()} bars · ${formatTime(last.time)}`;\n        const gauges = document.createElement(\"div\");\n        gauges.className = \"technicals-gauges\";\n        gauges.append(gauge(\"Oscillators\", oscillators), gauge(\"Summary\", [...oscillators, ...averages], true), gauge(\"Moving averages\", averages));\n        const tables = document.createElement(\"div\");\n        tables.className = \"technicals-tables\";\n        tables.append(readingsTable(\"Oscillators\", oscillators), readingsTable(\"Moving averages\", averages));\n        this.results.replaceChildren(gauges, tables);\n        this.root.querySelector<HTMLElement>(\".technicals-method\")!.hidden = false;\n    }\n}\n","import { DRAWING_TOOLS, drawingDefinition, type DrawingTool, type ObjectTool } from \"./DrawingCatalog.ts\";\nimport { toolIcon, type ToolIcon } from \"./ToolIcons\";\n\ninterface FavoritesPlacement { x: number; y: number; minimized: boolean; }\ninterface FavoritesOptions {\n    tools: unknown;\n    placement: unknown;\n    saveTools: (tools: ObjectTool[]) => void;\n    savePlacement: (placement: FavoritesPlacement) => void;\n}\n\nconst clampFraction = (value: number): number => Math.max(0, Math.min(1, value));\n\nexport class DrawingToolbox {\n    private active: DrawingTool = \"select\";\n    private openGroup: HTMLElement | null = null;\n    private returnFocus: HTMLButtonElement | null = null;\n    private readonly flyout = document.createElement(\"div\");\n    private readonly favorites = new Set<ObjectTool>();\n    private readonly favoritesLayer = document.createElement(\"div\");\n    private readonly favoritesBar = document.createElement(\"div\");\n    private readonly favoritesTools = document.createElement(\"div\");\n    private placement: FavoritesPlacement = { x: .5, y: .04, minimized: false };\n    private closeTimer = 0;\n    constructor(private readonly toolbar: HTMLElement, private readonly options: FavoritesOptions,\n        private readonly select: (tool: DrawingTool, hint: string) => void) {\n        if (Array.isArray(options.tools)) {\n            for (const value of options.tools) {\n                const definition = typeof value === \"string\" ? drawingDefinition(value) : undefined;\n                if (definition) this.favorites.add(definition.id);\n            }\n        }\n        if (options.placement && typeof options.placement === \"object\") {\n            const { x, y, minimized } = options.placement as Partial<FavoritesPlacement>;\n            if (typeof x === \"number\" && Number.isFinite(x)) this.placement.x = clampFraction(x);\n            if (typeof y === \"number\" && Number.isFinite(y)) this.placement.y = clampFraction(y);\n            if (typeof minimized === \"boolean\") this.placement.minimized = minimized;\n        }\n    }\n    public mount(chartArea: HTMLElement): void {\n        const select = this.toolButton(\"select\", \"select\", \"Select / move drawing (Esc)\"); this.toolbar.append(select);\n        this.flyout.className = \"drawing-flyout\"; this.flyout.hidden = true; this.flyout.id = \"drawing-more-tools\";\n        this.flyout.setAttribute(\"role\", \"region\");\n        this.flyout.tabIndex = -1;\n        document.body.append(this.flyout);\n        this.mountFavoritesBar(chartArea);\n        for (const [group, id] of [[\"Lines\", \"trend\"], [\"Shapes\", \"rectangle\"], [\"Fibonacci\", \"fib\"], [\"Annotations\", \"text\"], [\"Measure\", \"measure\"]] as const) {\n            const definition = DRAWING_TOOLS.find(t => t.id === id)!;\n            const row = document.createElement(\"div\"); row.className = \"tool-group\";\n            row.append(this.toolButton(id, definition.icon, definition.name));\n            const arrow = document.createElement(\"button\"); arrow.type = \"button\"; arrow.className = \"tool-more\";\n            arrow.innerHTML = toolIcon(\"chevron\"); arrow.title = `More ${group.toLowerCase()} tools`; arrow.setAttribute(\"aria-label\", arrow.title);\n            arrow.setAttribute(\"aria-expanded\", \"false\"); arrow.setAttribute(\"aria-controls\", this.flyout.id);\n            const open = () => this.open(group, row, arrow);\n            arrow.addEventListener(\"pointerenter\", open);\n            arrow.addEventListener(\"click\", () => { if (this.openGroup === row && !this.flyout.hidden) this.flyout.querySelector<HTMLButtonElement>(\"[data-tool]\")?.focus(); else open(); });\n            arrow.addEventListener(\"keydown\", e => { if ([\"ArrowRight\", \"ArrowDown\"].includes(e.key)) { e.preventDefault(); open(); this.flyout.querySelector<HTMLButtonElement>(\"[data-tool]\")?.focus(); } });\n            row.addEventListener(\"pointerenter\", () => window.clearTimeout(this.closeTimer));\n            row.addEventListener(\"pointerleave\", () => this.scheduleClose());\n            row.append(arrow); this.toolbar.append(row);\n        }\n        this.flyout.addEventListener(\"pointerenter\", () => window.clearTimeout(this.closeTimer));\n        this.flyout.addEventListener(\"pointerleave\", () => this.scheduleClose());\n        this.flyout.addEventListener(\"keydown\", e => {\n            if (e.key === \"Escape\" || e.key === \"ArrowLeft\") { e.preventDefault(); e.stopPropagation(); this.close(); this.returnFocus?.focus(); }\n            if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") {\n                e.preventDefault(); const buttons = [...this.flyout.querySelectorAll<HTMLButtonElement>(\"[data-tool]\")];\n                const row = (document.activeElement as Element)?.closest(\".drawing-flyout-row\");\n                const index = buttons.findIndex(b => row?.contains(b));\n                buttons[(index + (e.key === \"ArrowDown\" ? 1 : -1) + buttons.length) % buttons.length]?.focus();\n            }\n        });\n        document.addEventListener(\"pointerdown\", e => { if (!this.openGroup?.contains(e.target as Node) && !this.flyout.contains(e.target as Node)) this.close(); });\n        document.addEventListener(\"focusin\", e => { if (!this.openGroup?.contains(e.target as Node) && !this.flyout.contains(e.target as Node)) this.close(); });\n        window.addEventListener(\"resize\", () => this.close());\n        this.toolbar.addEventListener(\"scroll\", () => this.close(), { passive: true });\n        this.setActive(\"select\");\n    }\n    public setActive(tool: DrawingTool): void {\n        this.active = tool;\n        for (const root of [this.toolbar, this.flyout, this.favoritesTools]) {\n            for (const b of root.querySelectorAll<HTMLButtonElement>(\"[data-tool]\")) b.setAttribute(\"aria-pressed\", String(b.dataset.tool === tool));\n        }\n    }\n    private toolButton(tool: DrawingTool, icon: ToolIcon, name: string, label = false): HTMLButtonElement {\n        const b = document.createElement(\"button\"); b.type = \"button\"; b.className = \"tool-button\";\n        b.innerHTML = toolIcon(icon); b.title = name; b.setAttribute(\"aria-label\", name); b.dataset.tool = tool;\n        if (label) { const text = document.createElement(\"span\"); text.textContent = name; b.append(text); }\n        b.addEventListener(\"click\", () => {\n            const def = DRAWING_TOOLS.find(t => t.id === tool);\n            const hint = !def ? \"Select / move drawing\" : `${def.name} · ${def.id === \"text\" ? \"click and type\" : def.id === \"brush\" ? \"drag to draw\" : `click ${def.points === 1 ? \"a point\" : def.points + \" points\"}`}`;\n            this.select(tool, hint); this.close(); this.setActive(tool);\n            // Move focus to the active chart so Esc and drawing shortcuts work.\n            document.querySelector<HTMLElement>(\".chart-cell.is-active .chart-stack > .chart-container\")?.focus({ preventScroll: true });\n        });\n        return b;\n    }\n    private open(group: string, row: HTMLElement, arrow: HTMLButtonElement): void {\n        window.clearTimeout(this.closeTimer);\n        if (this.openGroup === row && !this.flyout.hidden) return;\n        this.close(); this.openGroup = row; this.returnFocus = arrow; arrow.setAttribute(\"aria-expanded\", \"true\");\n        this.flyout.setAttribute(\"aria-label\", `${group} drawing tools`);\n        this.renderFlyout(group);\n        this.flyout.hidden = false;\n        const bounds = row.getBoundingClientRect(), panel = this.flyout.getBoundingClientRect();\n        this.flyout.style.left = `${Math.max(8, Math.min(bounds.right + 6, window.innerWidth - panel.width - 8))}px`;\n        this.flyout.style.top = `${Math.max(8, Math.min(bounds.top, window.innerHeight - panel.height - 8))}px`;\n    }\n    private renderFlyout(group: string): void {\n        const title = document.createElement(\"div\");\n        title.className = \"drawing-flyout-title\";\n        title.textContent = group;\n        this.flyout.replaceChildren(title);\n        for (const tool of DRAWING_TOOLS.filter(tool => tool.group === group)) {\n            const item = document.createElement(\"div\");\n            item.className = \"drawing-flyout-row\";\n            const star = document.createElement(\"button\");\n            star.type = \"button\";\n            star.className = \"drawing-star\";\n            star.innerHTML = toolIcon(\"star\");\n            const updateStar = () => {\n                const selected = this.favorites.has(tool.id);\n                star.title = `${selected ? \"Unfavorite\" : \"Favorite\"} ${tool.name}`;\n                star.setAttribute(\"aria-label\", star.title);\n                star.setAttribute(\"aria-pressed\", String(selected));\n            };\n            updateStar();\n            star.addEventListener(\"click\", () => {\n                if (this.favorites.has(tool.id)) this.favorites.delete(tool.id);\n                else this.favorites.add(tool.id);\n                this.options.saveTools([...this.favorites]);\n                updateStar();\n                this.renderFavorites();\n            });\n            item.append(this.toolButton(tool.id, tool.icon, tool.name, true), star);\n            this.flyout.append(item);\n        }\n        this.setActive(this.active);\n    }\n    private mountFavoritesBar(chartArea: HTMLElement): void {\n        const trigger = document.createElement(\"button\");\n        const grip = document.createElement(\"button\");\n        const toggle = document.createElement(\"button\");\n        for (const button of [trigger, grip, toggle]) button.type = \"button\";\n        trigger.className = \"tool-button drawing-favorites-trigger\";\n        trigger.innerHTML = toolIcon(\"star\");\n        trigger.title = \"Favorite drawing tools\";\n        trigger.setAttribute(\"aria-label\", trigger.title);\n        grip.className = \"tool-button drawing-favorites-grip\";\n        grip.innerHTML = toolIcon(\"grip\");\n        grip.title = \"Move favorites toolbar · drag or use arrow keys\";\n        grip.setAttribute(\"aria-label\", grip.title);\n        toggle.className = \"tool-button drawing-favorites-toggle\";\n\n        this.favoritesLayer.className = \"drawing-favorites-layer\";\n        this.favoritesBar.className = \"drawing-favorites-bar\";\n        this.favoritesBar.setAttribute(\"role\", \"toolbar\");\n        this.favoritesBar.setAttribute(\"aria-label\", \"Favorite drawing tools\");\n        this.favoritesTools.className = \"drawing-favorites-tools\";\n        this.favoritesTools.id = \"drawing-favorites-tools\";\n        for (const button of [trigger, toggle]) button.setAttribute(\"aria-controls\", this.favoritesTools.id);\n        this.favoritesBar.append(grip, this.favoritesTools, toggle);\n        this.favoritesLayer.append(this.favoritesBar);\n        chartArea.append(this.favoritesLayer);\n        this.toolbar.append(trigger);\n\n        const update = () => {\n            const minimized = this.placement.minimized;\n            this.favoritesTools.hidden = minimized;\n            toggle.innerHTML = toolIcon(minimized ? \"star\" : \"minus\");\n            toggle.title = minimized ? \"Expand favorites toolbar\" : \"Minimize favorites toolbar\";\n            toggle.setAttribute(\"aria-label\", toggle.title);\n            for (const button of [trigger, toggle]) button.setAttribute(\"aria-expanded\", String(!minimized));\n        };\n        const toggleMinimized = () => {\n            this.placement.minimized = !this.placement.minimized;\n            update();\n            this.options.savePlacement({ ...this.placement });\n        };\n        trigger.addEventListener(\"click\", toggleMinimized);\n        toggle.addEventListener(\"click\", toggleMinimized);\n        this.bindFavoritesDrag(grip);\n        this.renderFavorites();\n        this.positionFavorites();\n        update();\n    }\n    private renderFavorites(): void {\n        this.favoritesTools.replaceChildren();\n        for (const id of this.favorites) {\n            const tool = drawingDefinition(id);\n            if (tool) this.favoritesTools.append(this.toolButton(id, tool.icon, tool.name));\n        }\n        if (!this.favorites.size) {\n            const hint = document.createElement(\"span\");\n            hint.className = \"drawing-favorites-empty\";\n            hint.textContent = \"Star a drawing tool to pin it here\";\n            this.favoritesTools.append(hint);\n        }\n        this.setActive(this.active);\n    }\n    private positionFavorites(): void {\n        const x = this.placement.x * 100;\n        const y = this.placement.y * 100;\n        this.favoritesBar.style.left = `${x}%`;\n        this.favoritesBar.style.top = `${y}%`;\n        this.favoritesBar.style.transform = `translate(${-x}%, ${-y}%)`;\n    }\n    private bindFavoritesDrag(grip: HTMLButtonElement): void {\n        const travel = () => ({\n            width: Math.max(1, this.favoritesLayer.clientWidth - this.favoritesBar.offsetWidth),\n            height: Math.max(1, this.favoritesLayer.clientHeight - this.favoritesBar.offsetHeight),\n        });\n        const move = (x: number, y: number) => {\n            this.placement.x = clampFraction(x);\n            this.placement.y = clampFraction(y);\n            this.positionFavorites();\n        };\n        let drag: { pointer: number; clientX: number; clientY: number; x: number; y: number; width: number; height: number } | null = null;\n        grip.addEventListener(\"pointerdown\", event => {\n            if (event.button !== 0 || drag) return;\n            drag = { pointer: event.pointerId, clientX: event.clientX, clientY: event.clientY,\n                x: this.placement.x, y: this.placement.y, ...travel() };\n            grip.setPointerCapture(event.pointerId);\n        });\n        grip.addEventListener(\"pointermove\", event => {\n            if (drag?.pointer !== event.pointerId) return;\n            move(drag.x + (event.clientX - drag.clientX) / drag.width,\n                drag.y + (event.clientY - drag.clientY) / drag.height);\n        });\n        const finish = (event: PointerEvent) => {\n            if (drag?.pointer !== event.pointerId) return;\n            drag = null;\n            this.options.savePlacement({ ...this.placement });\n        };\n        grip.addEventListener(\"pointerup\", finish);\n        grip.addEventListener(\"pointercancel\", finish);\n        grip.addEventListener(\"lostpointercapture\", finish);\n        grip.addEventListener(\"keydown\", event => {\n            const step = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[event.key];\n            if (!step) return;\n            event.preventDefault();\n            event.stopPropagation();\n            const { width, height } = travel();\n            move(this.placement.x + step[0] * 12 / width, this.placement.y + step[1] * 12 / height);\n            this.options.savePlacement({ ...this.placement });\n        });\n    }\n    private scheduleClose(): void { this.closeTimer = window.setTimeout(() => { if (!this.flyout.contains(document.activeElement)) this.close(); }, 160); }\n    private close(): void { window.clearTimeout(this.closeTimer); if (this.openGroup) this.returnFocus?.setAttribute(\"aria-expanded\", \"false\"); this.openGroup = null; this.flyout.hidden = true; }\n}\n","/** Keep only the latest interaction update for each animation frame. */\nexport class FrameTask {\n    private frame = 0;\n    private task: (() => void) | null = null;\n    public schedule(task: () => void): void {\n        this.task = task;\n        if (this.frame) return;\n        this.frame = requestAnimationFrame(() => {\n            this.frame = 0;\n            const next = this.task;\n            this.task = null;\n            next?.();\n        });\n    }\n    public cancel(): void {\n        if (this.frame) cancelAnimationFrame(this.frame);\n        this.frame = 0; this.task = null;\n    }\n}\n","/** IDs are local object identities, not authentication tokens. Works on HTTP LAN hosts too. */\nexport function createId(): string {\n    return globalThis.crypto?.randomUUID?.() ?? `chartix-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n","type Value = number | string | boolean | undefined;\ntype Fields = { year: number; month: number; day: number; hour: number; minute: number; second: number; ms: number; offset: number };\nconst DAY = 86_400_000;\nconst calendarNames = new Set([\"year\", \"month\", \"dayofmonth\", \"dayofweek\", \"weekofyear\", \"hour\", \"minute\", \"second\"]);\n\nfunction utc(year: number, month: number, day: number, hour = 0, minute = 0, second = 0): number {\n    const date = new Date(0);\n    date.setUTCFullYear(year, month - 1, day);\n    date.setUTCHours(hour, minute, second, 0);\n    return date.getTime();\n}\n\nfunction offsetMinutes(zone: string): number | undefined {\n    if (zone === \"UTC\" || zone === \"GMT\" || zone === \"Z\") return 0;\n    const offset = /^(?:UTC|GMT)?([+-])(\\d{1,2})(?::?(\\d{2}))?$/.exec(zone);\n    if (!offset) return undefined;\n    const hour = Number(offset[2]), minute = Number(offset[3] ?? 0);\n    return hour <= 23 && minute <= 59 ? (offset[1] === \"-\" ? -1 : 1) * (60 * hour + minute) : undefined;\n}\n\nexport function calendarRuntime() {\n    const formats = new Map<string, Intl.DateTimeFormat>();\n    const fail = (line: number, message: string): never => { throw new Error(`Line ${line}. ${message}`); };\n\n    function fields(time: number, zone: string, line: number): Fields | undefined {\n        if (!Number.isFinite(time)) return undefined;\n        const offset = offsetMinutes(zone);\n        if (offset !== undefined) {\n            const date = new Date(time + offset * 60_000);\n            if (!Number.isFinite(date.getTime())) return undefined;\n            return { year: date.getUTCFullYear(), month: date.getUTCMonth() + 1, day: date.getUTCDate(),\n                hour: date.getUTCHours(), minute: date.getUTCMinutes(), second: date.getUTCSeconds(),\n                ms: date.getUTCMilliseconds(), offset };\n        }\n        let format = formats.get(zone);\n        if (!format) {\n            try {\n                format = new Intl.DateTimeFormat(\"en-GB\", { timeZone: zone, year: \"numeric\", month: \"numeric\",\n                    day: \"numeric\", hour: \"numeric\", minute: \"numeric\", second: \"numeric\", hourCycle: \"h23\" });\n            } catch {\n                return fail(line, `Unknown timezone '${zone}'.`);\n            }\n            if (formats.size >= 32) formats.clear();\n            formats.set(zone, format);\n        }\n        if (!Number.isFinite(new Date(time).getTime())) return undefined;\n        const parts = Object.fromEntries(format.formatToParts(time).map(part => [part.type, Number(part.value)]));\n        const { year, month, day, hour, minute, second } = parts;\n        const offsetValue = (utc(year, month, day, hour, minute, second) - Math.floor(time / 1000) * 1000) / 60_000;\n        return { year, month, day, hour, minute, second, ms: ((time % 1000) + 1000) % 1000, offset: offsetValue };\n    }\n\n    function numberField(name: string, f: Fields): number {\n        switch (name) {\n            case \"dayofmonth\": return f.day;\n            case \"dayofweek\": return new Date(utc(f.year, f.month, f.day)).getUTCDay() + 1;\n            case \"weekofyear\": {\n                const date = new Date(utc(f.year, f.month, f.day));\n                const weekday = (date.getUTCDay() + 6) % 7;\n                date.setUTCDate(date.getUTCDate() + 3 - weekday);\n                return Math.floor((date.getTime() - utc(date.getUTCFullYear(), 1, 1)) / (7 * DAY)) + 1;\n            }\n            case \"year\": return f.year;\n            case \"month\": return f.month;\n            case \"hour\": return f.hour;\n            case \"minute\": return f.minute;\n            default: return f.second;\n        }\n    }\n\n    function formatTime(f: Fields, pattern: string, line: number): string {\n        const pad = (value: number, length = 2) => String(value).padStart(length, \"0\");\n        const signedOffset = (f.offset < 0 ? \"-\" : \"+\") + pad(Math.floor(Math.abs(f.offset) / 60)) + pad(Math.abs(f.offset) % 60);\n        const hour = f.hour % 12 || 12;\n        const values: Record<string, string> = {\n            yyyy: pad(f.year, 4), yy: pad(f.year % 100), M: String(f.month), MM: pad(f.month),\n            d: String(f.day), dd: pad(f.day), H: String(f.hour), HH: pad(f.hour),\n            h: String(hour), hh: pad(hour), m: String(f.minute), mm: pad(f.minute), s: String(f.second), ss: pad(f.second),\n            SSS: pad(f.ms, 3), a: f.hour < 12 ? \"AM\" : \"PM\", Z: signedOffset,\n        };\n        return pattern.replace(/''|'(?:[^']|'')*'|([A-Za-z])\\1*/g, token => {\n            if (token === \"''\") return \"'\";\n            if (token.startsWith(\"'\")) return token.slice(1, -1).replace(/''/g, \"'\");\n            return values[token] ?? fail(line, `Unsupported time format token '${token}'.`);\n        });\n    }\n\n    return (name: string, args: readonly Value[], line: number): Value => {\n        if (name === \"timestamp\") {\n            if (args.length === 1) {\n                const input = args[0];\n                if (typeof input !== \"string\") return undefined;\n                const match = /^\\s*(\\d{4})-(\\d{1,2})-(\\d{1,2})(?:[ T](\\d{1,2}):(\\d{2})(?::(\\d{2}))?)?(?:\\s*(Z|UTC|GMT|(?:UTC|GMT)?[+-]\\d{1,2}(?::?\\d{2})?))?\\s*$/.exec(input);\n                if (!match) return fail(line, \"timestamp() needs an ISO date with an optional time and UTC offset.\");\n                const [, y, m, d, h = \"0\", minute = \"0\", s = \"0\", zone = \"UTC\"] = match;\n                const offset = offsetMinutes(zone);\n                if (offset === undefined) return fail(line, `Invalid UTC offset '${zone}'.`);\n                return utc(Number(y), Number(m), Number(d), Number(h), Number(minute), Number(s)) - offset * 60_000;\n            }\n            const [zone, ...parts] = args;\n            if (typeof zone !== \"string\" || parts.some(value => typeof value !== \"number\")) return undefined;\n            const [y, m, d, h, minute, s] = parts as number[];\n            const local = utc(y, m, d, h, minute, s);\n            const fixed = offsetMinutes(zone);\n            if (fixed !== undefined) return local - fixed * 60_000;\n            const guess = fields(local, zone, line);\n            if (!guess) return undefined;\n            const candidate = local - guess.offset * 60_000;\n            const corrected = fields(candidate, zone, line);\n            return local - (corrected?.offset ?? guess.offset) * 60_000;\n        }\n        const time = typeof args[0] === \"number\" ? args[0] : NaN;\n        const zone = (name === \"str.format_time\" ? args[2] : args[1]) ?? \"UTC\";\n        const value = fields(time, String(zone), line);\n        if (!value) return undefined;\n        if (name === \"str.format_time\") return formatTime(value, String(args[1] ?? \"yyyy-MM-dd'T'HH:mm:ssZ\"), line);\n        if (calendarNames.has(name)) return numberField(name, value);\n        return fail(line, `Unknown calendar built-in '${name}'.`);\n    };\n}\n","type CreateArray = (values: number[], line: number) => number;\n\nexport function mapRuntime(createArray: CreateArray) {\n    const objects: Map<number, number>[] = [];\n    let entries = 0;\n    let work = 0;\n    const fail = (line: number, message: string): never => { throw new Error(`Line ${line}. ${message}`); };\n\n    function charge(count: number, line: number): void {\n        work += count;\n        if (work > 10_000_000) fail(line, \"The script exceeded its map calculation limit.\");\n    }\n    function reserve(size: number, growth: number, line: number): void {\n        if (size > 50_000 || entries + growth > 500_000) fail(line, \"The script exceeded its map storage limit.\");\n        entries += growth;\n    }\n    function get(id: number, line: number): Map<number, number> {\n        return objects[id] ?? fail(line, \"A map operation received an undefined reference.\");\n    }\n    function create(line: number, original?: Map<number, number>): number {\n        if (objects.length >= 50_000) fail(line, \"The script exceeded its map object limit.\");\n        if (original) {\n            charge(original.size, line);\n            reserve(original.size, original.size, line);\n        }\n        return objects.push(new Map(original)) - 1;\n    }\n    function put(map: Map<number, number>, key: number, value: number, line: number): number {\n        if (Number.isNaN(key)) fail(line, \"Map keys must be defined.\");\n        const previous = map.get(key);\n        if (!map.has(key)) reserve(map.size + 1, 1, line);\n        map.set(key, value);\n        return previous ?? NaN;\n    }\n\n    return (operation: string, args: readonly number[], line: number): number => {\n        if (operation === \"map.new\") return create(line);\n        const [id, key, value] = args;\n        const map = get(id, line);\n        switch (operation) {\n            case \"map.size\": return map.size;\n            case \"map.get\": return map.get(key) ?? NaN;\n            case \"map.contains\": return Number(map.has(key));\n            case \"map.put\": return put(map, key, value, line);\n            case \"map.remove\": {\n                const previous = map.get(key);\n                if (map.delete(key)) entries--;\n                return previous ?? NaN;\n            }\n            case \"map.clear\": entries -= map.size; map.clear(); return NaN;\n            case \"map.copy\": return create(line, map);\n            case \"map.keys\":\n            case \"map.values\":\n                charge(map.size, line);\n                return createArray(Array.from(operation === \"map.keys\" ? map.keys() : map.values()), line);\n            case \"map.put_all\": {\n                const other = get(key, line);\n                if (other === map) return NaN;\n                charge(other.size, line);\n                let extra = 0;\n                for (const otherKey of other.keys()) if (!map.has(otherKey)) extra++;\n                reserve(map.size + extra, extra, line);\n                for (const [otherKey, item] of other) map.set(otherKey, item);\n                return NaN;\n            }\n            default: return fail(line, `Unknown map built-in '${operation}'.`);\n        }\n    };\n}\n","type Matrix = { rows: number; columns: number; data: number[] };\ntype Arrays = {\n    create(values: number[], line: number): number;\n    get(id: number, line: number): number[];\n};\n\nconst at = (m: Matrix, row: number, col: number): number => m.data[row * m.columns + col];\nconst MAX_CELLS = 100_000;\nconst MAX_WORK = 30_000_000;\n\nexport function matrixRuntime(arrays: Arrays, strings: readonly string[]) {\n    const objects: Matrix[] = [];\n    let cells = 0, work = 0;\n    const fail = (line: number, message: string): never => { throw new Error(`Line ${line}. ${message}`); };\n    function charge(count: number, line: number): void {\n        work += count;\n        if (work > MAX_WORK) fail(line, \"The script exceeded its matrix calculation limit.\");\n    }\n    function shape(rows: number, cols: number, line: number, growth = 0): void {\n        if (!Number.isInteger(rows) || !Number.isInteger(cols) || rows < 0 || cols < 0 || rows > MAX_CELLS || cols > MAX_CELLS\n            || rows * cols > MAX_CELLS || cells + growth > 500_000) fail(line, \"The matrix exceeds the runtime storage limit.\");\n    }\n    function matrix(id: number, line: number): Matrix {\n        return objects[id] ?? fail(line, \"A matrix operation received an undefined reference.\");\n    }\n    function bounds(index: number, size: number, line: number, end = false): number {\n        if (!Number.isInteger(index) || index < 0 || index >= size + Number(end)) fail(line, `Matrix index ${index} is out of bounds for size ${size}.`);\n        return index;\n    }\n    function generate(rows: number, columns: number, fn: (row: number, col: number) => number, line: number): Matrix {\n        shape(rows, columns, line);\n        charge(rows * columns, line);\n        return { rows, columns, data: Array.from({ length: rows * columns }, (_, i) => fn(Math.floor(i / columns), i % columns)) };\n    }\n    function save(value: Matrix, line: number, integral = false): number {\n        if (objects.length >= 50_000) fail(line, \"The script exceeded its matrix object limit.\");\n        shape(value.rows, value.columns, line, value.data.length);\n        cells += value.data.length;\n        if (integral) value.data = value.data.map(item => Number.isSafeInteger(Math.trunc(item)) ? Math.trunc(item) : NaN);\n        return objects.push(value) - 1;\n    }\n    function replace(id: number, next: Matrix, line: number): number {\n        const growth = next.data.length - objects[id].data.length;\n        shape(next.rows, next.columns, line, growth);\n        cells += growth;\n        objects[id] = next;\n        return NaN;\n    }\n    function transpose(m: Matrix, line: number): Matrix {\n        return generate(m.columns, m.rows, (i, j) => at(m, j, i), line);\n    }\n    function multiply(a: Matrix, b: Matrix, line: number): Matrix {\n        if (a.columns !== b.rows) fail(line, \"The first matrix's columns must match the second operand's rows.\");\n        charge(a.rows * a.columns * b.columns, line);\n        return generate(a.rows, b.columns, (i, j) => {\n            let value = 0;\n            for (let k = 0; k < a.columns; k++) value += at(a, i, k) * at(b, k, j);\n            return value;\n        }, line);\n    }\n    function square(m: Matrix, line: number): number {\n        if (m.rows !== m.columns || !m.rows) fail(line, \"This operation requires a non-empty square matrix.\");\n        return m.rows;\n    }\n    function eliminate(m: Matrix, line: number, inverse = false) {\n        const { rows, columns } = m;\n        charge(rows + columns + rows * columns * Math.min(rows, columns) * (inverse ? 2 : 1), line);\n        const width = columns + (inverse ? rows : 0);\n        if (width * rows > 2 * MAX_CELLS) fail(line, \"The matrix is too large for elimination.\");\n        const values = Array.from({ length: rows }, (_, i) => Array.from({ length: width },\n            (_, j) => j < columns ? at(m, i, j) : Number(j - columns === i)));\n        let scale = 0;\n        for (const item of m.data) scale = Math.max(scale, Math.abs(item));\n        if (!Number.isFinite(scale)) return { rank: NaN, determinant: NaN, values };\n        const tolerance = Number.EPSILON * Math.max(rows, columns) * scale;\n        let rank = 0, determinant = 1;\n        for (let column = 0; column < columns && rank < rows; column++) {\n            let pivot = rank;\n            for (let row = rank + 1; row < rows; row++) {\n                if (Math.abs(values[row][column]) > Math.abs(values[pivot][column])) pivot = row;\n            }\n            if (Math.abs(values[pivot][column]) <= tolerance) continue;\n            if (pivot !== rank) {\n                [values[pivot], values[rank]] = [values[rank], values[pivot]];\n                determinant = -determinant;\n            }\n            const leading = values[rank][column];\n            determinant *= leading;\n            for (let j = column; j < width; j++) values[rank][j] /= leading;\n            for (let i = inverse ? 0 : rank + 1; i < rows; i++) {\n                if (i === rank) continue;\n                const factor = values[i][column];\n                for (let j = column; j < width; j++) values[i][j] -= factor * values[rank][j];\n            }\n            rank++;\n        }\n        return { rank, determinant: rank === rows ? determinant : 0, values };\n    }\n    function invert(m: Matrix, line: number): Matrix {\n        const size = square(m, line);\n        const { rank, values } = eliminate(m, line, true);\n        if (rank !== size) fail(line, \"A singular or undefined matrix cannot be inverted.\");\n        return generate(size, size, (i, j) => values[i][j + size], line);\n    }\n\n    function pseudoInverse(m: Matrix, line: number): Matrix {\n        if (!m.rows || !m.columns) return transpose(m, line);\n        if (m.rows < m.columns) return transpose(pseudoInverse(transpose(m, line), line), line);\n\n        // One-sided Jacobi SVD. Rotate columns directly to preserve accuracy\n        // for rank-deficient inputs without squaring their condition number.\n        const { rows, columns } = m;\n        let scale = 0;\n        for (const value of m.data) scale = Math.max(scale, Math.abs(value));\n        if (!Number.isFinite(scale)) fail(line, \"A pseudoinverse requires defined finite elements.\");\n        if (scale === 0) return generate(columns, rows, () => 0, line);\n        const orthogonal = m.data.map(value => value / scale);\n        const basis = generate(columns, columns, (i, j) => Number(i === j), line).data;\n        const rotate = (data: number[], count: number, p: number, q: number, cos: number, sin: number) => {\n            for (let i = 0; i < count; i++) {\n                const first = i * columns + p, second = i * columns + q;\n                const x = data[first], y = data[second];\n                data[first] = cos * x - sin * y;\n                data[second] = sin * x + cos * y;\n            }\n        };\n        let converged = false;\n        for (let sweep = 0; sweep < 40; sweep++) {\n            let changed = false;\n            charge(rows * columns * columns, line);\n            for (let p = 0; p < columns - 1; p++) {\n                for (let q = p + 1; q < columns; q++) {\n                    let xx = 0, yy = 0, xy = 0;\n                    for (let row = 0; row < rows; row++) {\n                        const x = orthogonal[row * columns + p], y = orthogonal[row * columns + q];\n                        xx += x * x;\n                        yy += y * y;\n                        xy += x * y;\n                    }\n                    if (Math.abs(xy) <= Number.EPSILON * Math.sqrt(xx * yy)) continue;\n                    const tau = (yy - xx) / (2 * xy);\n                    const tangent = (tau < 0 ? -1 : 1) / (Math.abs(tau) + Math.hypot(1, tau));\n                    const cosine = 1 / Math.hypot(1, tangent);\n                    rotate(orthogonal, rows, p, q, cosine, tangent * cosine);\n                    rotate(basis, columns, p, q, cosine, tangent * cosine);\n                    changed = true;\n                }\n            }\n            if (!changed) { converged = true; break; }\n        }\n        if (!converged) fail(line, \"The matrix pseudoinverse did not converge.\");\n        const squares = Array.from({ length: columns }, (_, j) => {\n            let norm = 0;\n            for (let i = 0; i < rows; i++) norm += orthogonal[i * columns + j] ** 2;\n            return norm;\n        });\n        const tolerance = (Number.EPSILON * Math.max(rows, columns)) ** 2 * Math.max(...squares);\n        charge(rows * columns * columns, line);\n        return generate(columns, rows, (i, j) => {\n            let value = 0;\n            for (let k = 0; k < columns; k++) {\n                if (squares[k] > tolerance) value += basis[i * columns + k] * orthogonal[j * columns + k] / squares[k];\n            }\n            return value / scale;\n        }, line);\n    }\n\n    function symmetricEigen(m: Matrix, line: number) {\n        const size = square(m, line);\n        const axes = generate(size, size, (i, j) => Number(i === j), line);\n        let scale = 0;\n        for (const value of m.data) scale = Math.max(scale, Math.abs(value));\n        if (!Number.isFinite(scale)) fail(line, \"Eigendecomposition requires finite elements.\");\n        if (!scale) return { values: Array<number>(size).fill(0), axes };\n        const values = m.data.map(value => value / scale);\n        const tolerance = Number.EPSILON * size * 4;\n        for (let p = 0; p < size; p++) {\n            for (let q = p + 1; q < size; q++) {\n                if (Math.abs(values[p * size + q] - values[q * size + p]) > tolerance) {\n                    fail(line, \"This runtime supports eigendecomposition of symmetric matrices.\");\n                }\n            }\n        }\n        let converged = false;\n        for (let sweep = 0; sweep < 40; sweep++) {\n            let changed = false;\n            charge(size ** 3, line);\n            for (let p = 0; p < size - 1; p++) {\n                for (let q = p + 1; q < size; q++) {\n                    const pq = values[p * size + q];\n                    if (Math.abs(pq) <= tolerance) continue;\n                    changed = true;\n                    const pp = values[p * size + p], qq = values[q * size + q];\n                    const tau = (qq - pp) / (2 * pq);\n                    const tangent = (tau < 0 ? -1 : 1) / (Math.abs(tau) + Math.hypot(1, tau));\n                    const cos = 1 / Math.hypot(1, tangent), sin = tangent * cos;\n                    for (let i = 0; i < size; i++) {\n                        const ip = i * size + p, iq = i * size + q;\n                        if (i !== p && i !== q) {\n                            const x = values[ip], y = values[iq];\n                            values[ip] = values[p * size + i] = cos * x - sin * y;\n                            values[iq] = values[q * size + i] = sin * x + cos * y;\n                        }\n                        const x = axes.data[ip], y = axes.data[iq];\n                        axes.data[ip] = cos * x - sin * y;\n                        axes.data[iq] = sin * x + cos * y;\n                    }\n                    values[p * size + p] = pp - tangent * pq;\n                    values[q * size + q] = qq + tangent * pq;\n                    values[p * size + q] = values[q * size + p] = 0;\n                }\n            }\n            if (!changed) { converged = true; break; }\n        }\n        if (!converged) fail(line, \"The matrix eigendecomposition did not converge.\");\n        const order = Array.from({ length: size }, (_, i) => i).sort((i, j) => values[i * (size + 1)] - values[j * (size + 1)]);\n        return {\n            values: order.map(i => scale * values[i * (size + 1)]),\n            axes: generate(size, size, (i, j) => at(axes, i, order[j]), line),\n        };\n    }\n\n    return (op: string, args: readonly number[], integral: boolean, line: number): number => {\n        const [id, a, b, c, d, e] = args;\n        const store = (value: Matrix): number => save(value, line, integral);\n        if (op === \"matrix.new\") return store(generate(id, a, () => b, line));\n        const m = matrix(id, line);\n        const { rows: r, columns: k, data } = m;\n        const row = (i: number, end = false) => bounds(i, r, line, end);\n        const col = (i: number, end = false) => bounds(i, k, line, end);\n        switch (op) {\n            case \"matrix.rows\": return r;\n            case \"matrix.columns\": return k;\n            case \"matrix.elements_count\": return data.length;\n            case \"matrix.get\": return at(m, row(a), col(b));\n            case \"matrix.set\": data[row(a) * k + col(b)] = c; return NaN;\n            case \"matrix.copy\": return store(generate(r, k, (i, j) => at(m, i, j), line));\n            case \"matrix.transpose\": return store(transpose(m, line));\n            case \"matrix.reverse\": charge(data.length, line); data.reverse(); return NaN;\n            case \"matrix.reshape\":\n                shape(a, b, line);\n                if (a * b !== data.length) fail(line, \"Reshape must preserve the number of elements.\");\n                m.rows = a; m.columns = b; return NaN;\n            case \"matrix.row\":\n            case \"matrix.remove_row\": {\n                const position = row(Number.isNaN(a) ? r - 1 : a);\n                const result = arrays.create(data.slice(position * k, (position + 1) * k), line);\n                if (op === \"matrix.remove_row\") {\n                    charge(data.length, line);\n                    data.splice(position * k, k); m.rows--; cells -= k;\n                }\n                return result;\n            }\n            case \"matrix.col\":\n            case \"matrix.remove_col\": {\n                const position = col(Number.isNaN(a) ? k - 1 : a);\n                const result = arrays.create(Array.from({ length: r }, (_, i) => at(m, i, position)), line);\n                if (op === \"matrix.remove_col\") replace(id, generate(r, k - 1, (i, j) => at(m, i, j + Number(j >= position)), line), line);\n                return result;\n            }\n            case \"matrix.add_row\":\n            case \"matrix.add_col\": {\n                const byRow = op === \"matrix.add_row\", added = arrays.get(b, line);\n                const position = byRow ? row(Number.isNaN(a) ? r : a, true) : col(Number.isNaN(a) ? k : a, true);\n                const expected = byRow ? k : r;\n                const empty = r === 0 && k === 0;\n                if (!empty && added.length !== expected) fail(line, \"The array size does not match the matrix dimension.\");\n                const result = byRow\n                    ? generate(r + 1, empty ? added.length : k, (i, j) => i === position ? added[j] : at(m, i - Number(i > position), j), line)\n                    : generate(empty ? added.length : r, k + 1, (i, j) => j === position ? added[i] : at(m, i, j - Number(j > position)), line);\n                return replace(id, result, line);\n            }\n            case \"matrix.concat\": {\n                const other = matrix(a, line);\n                if (k !== other.columns) fail(line, \"Concatenated matrices must have the same column count.\");\n                replace(id, generate(r + other.rows, k, (i, j) => i < r ? at(m, i, j) : at(other, i - r, j), line), line);\n                return id;\n            }\n            case \"matrix.swap_rows\":\n            case \"matrix.swap_columns\": {\n                const rows = op === \"matrix.swap_rows\";\n                const first = rows ? row(a) : col(a), second = rows ? row(b) : col(b);\n                charge(rows ? k : r, line);\n                for (let i = 0; i < (rows ? k : r); i++) {\n                    const x = rows ? first * k + i : i * k + first, y = rows ? second * k + i : i * k + second;\n                    [data[x], data[y]] = [data[y], data[x]];\n                }\n                return NaN;\n            }\n            case \"matrix.fill\":\n            case \"matrix.submatrix\": {\n                const fill = op === \"matrix.fill\";\n                const raw = fill ? [b, c, d, e] : [a, b, c, d];\n                const firstRow = row(raw[0], true), lastRow = row(Number.isNaN(raw[1]) ? r : raw[1], true);\n                const firstCol = col(raw[2], true), lastCol = col(Number.isNaN(raw[3]) ? k : raw[3], true);\n                if (firstRow > lastRow || firstCol > lastCol) fail(line, \"Matrix range starts must precede their ends.\");\n                if (!fill) return store(generate(lastRow - firstRow, lastCol - firstCol,\n                    (i, j) => at(m, firstRow + i, firstCol + j), line));\n                charge((lastRow - firstRow) * (lastCol - firstCol), line);\n                for (let i = firstRow; i < lastRow; i++) data.fill(a, i * k + firstCol, i * k + lastCol);\n                return NaN;\n            }\n            case \"matrix.sort\":\n            case \"matrix.sort.text\": {\n                const column = col(a);\n                charge(data.length + r * Math.ceil(Math.log2(Math.max(1, r))), line);\n                const order = Array.from({ length: r }, (_, i) => i).sort((i, j) => {\n                    const x = at(m, i, column), y = at(m, j, column);\n                    if (Number.isNaN(x)) return Number(!Number.isNaN(y));\n                    if (Number.isNaN(y)) return -1;\n                    return b * (op.endsWith(\".text\") ? (strings[x] < strings[y] ? -1 : strings[x] > strings[y] ? 1 : 0) : x - y);\n                });\n                m.data = order.flatMap(i => data.slice(i * k, (i + 1) * k));\n                return NaN;\n            }\n            case \"matrix.sum.scalar\":\n            case \"matrix.diff.scalar\":\n            case \"matrix.mult.scalar\": {\n                const apply = op.includes(\".sum\") ? (x: number) => x + a : op.includes(\".diff\") ? (x: number) => x - a : (x: number) => x * a;\n                return store(generate(r, k, (i, j) => apply(at(m, i, j)), line));\n            }\n            case \"matrix.sum\":\n            case \"matrix.diff\": {\n                const other = matrix(a, line);\n                if (r !== other.rows || k !== other.columns) fail(line, \"Matrix addition and subtraction require matching shapes.\");\n                const sign = op === \"matrix.sum\" ? 1 : -1;\n                return store(generate(r, k, (i, j) => at(m, i, j) + sign * at(other, i, j), line));\n            }\n            case \"matrix.mult\": return store(multiply(m, matrix(a, line), line));\n            case \"matrix.mult.vector\": {\n                const vector = arrays.get(a, line);\n                const values = multiply(m, { rows: vector.length, columns: 1, data: vector }, line).data;\n                return arrays.create(integral ? values.map(Math.trunc) : values, line);\n            }\n            case \"matrix.kron\": {\n                const other = matrix(a, line);\n                return store(generate(r * other.rows, k * other.columns, (i, j) =>\n                    at(m, Math.floor(i / other.rows), Math.floor(j / other.columns)) * at(other, i % other.rows, j % other.columns), line));\n            }\n            case \"matrix.rank\": return eliminate(m, line).rank;\n            case \"matrix.det\": {\n                square(m, line);\n                const determinant = eliminate(m, line).determinant;\n                return integral ? Math.round(determinant) : determinant;\n            }\n            case \"matrix.inv\": return store(invert(m, line));\n            case \"matrix.pinv\": return store(pseudoInverse(m, line));\n            case \"matrix.eigenvalues\": {\n                const values = symmetricEigen(m, line).values;\n                return arrays.create(integral ? values.map(Math.trunc) : values, line);\n            }\n            case \"matrix.eigenvectors\": return store(symmetricEigen(m, line).axes);\n            case \"matrix.trace\": {\n                square(m, line);\n                let total = 0;\n                for (let i = 0; i < r; i++) total += at(m, i, i);\n                return total;\n            }\n            case \"matrix.pow\": {\n                const size = square(m, line);\n                if (!Number.isSafeInteger(a)) fail(line, \"Matrix powers require an integer.\");\n                let value = generate(size, size, (i, j) => Number(i === j), line);\n                let factor = a < 0 ? invert(m, line) : m;\n                for (let power = Math.abs(a); power > 0; power = Math.floor(power / 2)) {\n                    if (power % 2) value = multiply(value, factor, line);\n                    if (power > 1) factor = multiply(factor, factor, line);\n                }\n                return store(value);\n            }\n        }\n        if (op.startsWith(\"matrix.is_\")) {\n            if (op === \"matrix.is_square\") return Number(r === k);\n            if ([\"matrix.is_diagonal\", \"matrix.is_antidiagonal\", \"matrix.is_identity\", \"matrix.is_symmetric\",\n                \"matrix.is_antisymmetric\", \"matrix.is_triangular\"].includes(op) && r !== k) return 0;\n            charge(data.length + r, line);\n            let upper = true, lower = true;\n            for (let i = 0; i < r; i++) {\n                let total = 0;\n                for (let j = 0; j < k; j++) {\n                    const v = at(m, i, j);\n                    if (!Number.isFinite(v)) return 0;\n                    if (op === \"matrix.is_zero\" && v !== 0) return 0;\n                    if (op === \"matrix.is_binary\" && v !== 0 && v !== 1) return 0;\n                    if (op === \"matrix.is_diagonal\" && i !== j && v !== 0) return 0;\n                    if (op === \"matrix.is_antidiagonal\" && i + j !== k - 1 && v !== 0) return 0;\n                    if (op === \"matrix.is_identity\" && v !== Number(i === j)) return 0;\n                    if (op === \"matrix.is_symmetric\" && v !== at(m, j, i)) return 0;\n                    if (op === \"matrix.is_antisymmetric\" && v !== -at(m, j, i)) return 0;\n                    if (i > j && v !== 0) upper = false;\n                    if (i < j && v !== 0) lower = false;\n                    if (op === \"matrix.is_stochastic\" && v < 0) return 0;\n                    total += v;\n                }\n                if (op === \"matrix.is_stochastic\" && Math.abs(total - 1) > 1e-9) return 0;\n            }\n            return Number(op !== \"matrix.is_triangular\" || upper || lower);\n        }\n        charge(data.length, line);\n        const sample = data.filter(Number.isFinite);\n        if (!sample.length) return NaN;\n        if (op === \"matrix.avg\") return sample.reduce((sum, x) => sum + x, 0) / sample.length;\n        charge(sample.length * Math.ceil(Math.log2(sample.length)), line);\n        sample.sort((x, y) => x - y);\n        if (op === \"matrix.min\") return sample[0];\n        if (op === \"matrix.max\") return sample[sample.length - 1];\n        if (op === \"matrix.median\") return (sample[Math.floor((sample.length - 1) / 2)] + sample[Math.floor(sample.length / 2)]) / 2;\n        if (op === \"matrix.mode\") {\n            let best = sample[0], max = 1, count = 1;\n            for (let i = 1; i < sample.length; i++) {\n                count = sample[i] === sample[i - 1] ? count + 1 : 1;\n                if (count > max) { best = sample[i]; max = count; }\n            }\n            return best;\n        }\n        return fail(line, `Unknown matrix built-in '${op}'.`);\n    };\n}\n","const MAX_LENGTH = 100_000;\nconst MAX_OBJECTS = 50_000;\nconst MAX_ELEMENTS = 500_000;\nconst MAX_WORK = 30_000_000;\n\nexport function arrayRuntime(strings: readonly string[], intern: (value: string) => number) {\n    const objects: number[][] = [];\n    let elements = 0, work = 0;\n    const fail = (line: number, message: string): never => { throw new Error(`Line ${line}. ${message}`); };\n    function reserve(length: number, growth: number, line: number): void {\n        if (length > MAX_LENGTH || elements + growth > MAX_ELEMENTS) {\n            fail(line, \"The script exceeded its array storage limit.\");\n        }\n        elements += growth;\n    }\n    function create(values: number[], line: number): number {\n        if (objects.length >= MAX_OBJECTS) fail(line, \"The script exceeded its array object limit.\");\n        reserve(values.length, values.length, line);\n        return objects.push(values) - 1;\n    }\n    function get(id: number, line: number): number[] {\n        return objects[id] ?? fail(line, \"An array operation received an undefined reference.\");\n    }\n    function index(raw: number, length: number, line: number, insert = false): number {\n        const i = raw < 0 ? raw + length : raw;\n        if (!Number.isInteger(i) || i < 0 || i > length - (insert ? 0 : 1)) {\n            fail(line, `Array index ${raw} is out of bounds for size ${length}.`);\n        }\n        return i;\n    }\n    function charge(amount: number, line: number): void {\n        work += amount;\n        if (work > MAX_WORK) fail(line, \"The script exceeded its array calculation limit.\");\n    }\n    function execute(operation: string, args: readonly number[], stringsInArray: boolean, line: number): number {\n        const [id, first, second, third] = args;\n        if (operation === \"array.new\") {\n            if (!Number.isSafeInteger(id) || id < 0 || id > MAX_LENGTH) fail(line, \"Array size must be between 0 and 100,000.\");\n            return create(Array<number>(id).fill(first), line);\n        }\n        if (operation === \"array.from\") return create([...args], line);\n        if (operation === \"str.split\") {\n            if (Number.isNaN(id) || Number.isNaN(first)) return NaN;\n            return create(strings[id].split(strings[first]).map(intern), line);\n        }\n        const data = get(id, line);\n        const length = data.length;\n        if (operation.startsWith(\"array.binary_search\")) {\n            if (Number.isNaN(first) || length === 0) return -1;\n            let lo = 0, hi = length - 1;\n            if (operation === \"array.binary_search\") {\n                while (lo <= hi) {\n                    const middle = (lo + hi) >>> 1;\n                    if (data[middle] === first) return middle;\n                    if (data[middle] < first) lo = middle + 1;\n                    else hi = middle - 1;\n                }\n                return -1;\n            }\n            const rightmost = operation.endsWith(\"rightmost\");\n            hi = length;\n            while (lo < hi) {\n                const middle = (lo + hi) >>> 1;\n                if (data[middle] < first || (rightmost && data[middle] === first)) lo = middle + 1;\n                else hi = middle;\n            }\n            if (rightmost) return lo && data[lo - 1] === first ? lo - 1 : lo;\n            return data[lo] === first ? lo : Math.max(0, lo - 1);\n        }\n        if (operation === \"array.covariance\") {\n            const other = get(first, line);\n            if (other.length !== length) fail(line, \"Covariance arrays must have the same size.\");\n            charge(length, line);\n            let count = 0, xMean = 0, yMean = 0, covariance = 0;\n            for (let i = 0; i < length; i++) {\n                const x = data[i], y = other[i];\n                if (Number.isNaN(x) || Number.isNaN(y)) continue;\n                count++;\n                const delta = x - xMean;\n                xMean += delta / count;\n                yMean += (y - yMean) / count;\n                covariance += delta * (y - yMean);\n            }\n            const divisor = count - Number(!second);\n            return divisor > 0 ? covariance / divisor : NaN;\n        }\n        switch (operation) {\n            case \"array.fill\": {\n                const start = index(second, length, line, true);\n                const end = Number.isNaN(third) ? length : index(third, length, line, true);\n                if (start > end) fail(line, \"The array fill start must precede the end.\");\n                charge(end - start, line);\n                data.fill(first, start, end);\n                return NaN;\n            }\n            case \"array.every\":\n            case \"array.some\": {\n                charge(length, line);\n                const truth = (value: number) => Boolean(value);\n                return Number(operation === \"array.every\" ? data.every(truth) : data.some(truth));\n            }\n            case \"array.abs\": charge(length, line); return create(data.map(Math.abs), line);\n            case \"array.sort_indices\": {\n                charge(length * Math.max(1, Math.ceil(Math.log2(length))), line);\n                return create(data.map((_, i) => i).sort((a, b) => {\n                    const x = data[a], y = data[b];\n                    return Number.isNaN(x) ? Number(!Number.isNaN(y)) : Number.isNaN(y) ? -1 : first * (x - y);\n                }), line);\n            }\n            case \"array.get\": return data[index(first, length, line)];\n            case \"array.set\": data[index(first, length, line)] = second; return NaN;\n            case \"array.insert\": {\n                const position = index(first, length, line, true);\n                if (position < length) charge(length, line);\n                reserve(length + 1, 1, line);\n                data.splice(position, 0, second);\n                return NaN;\n            }\n            case \"array.remove\": {\n                const position = index(first, length, line);\n                if (position < length - 1) charge(length, line);\n                elements--;\n                return data.splice(position, 1)[0];\n            }\n            case \"array.size\": return length;\n            case \"array.first\": return data[index(0, length, line)];\n            case \"array.last\": return data[index(-1, length, line)];\n            case \"array.push\": reserve(length + 1, 1, line); data.push(first); return NaN;\n            case \"array.unshift\":\n                if (length) charge(length, line); reserve(length + 1, 1, line); data.unshift(first); return NaN;\n            case \"array.pop\":\n                index(-1, length, line); elements--; return data.pop()!;\n            case \"array.shift\":\n                index(0, length, line); if (length > 1) charge(length, line); elements--; return data.shift()!;\n            case \"array.clear\": elements -= length; data.length = 0; return NaN;\n            case \"array.reverse\": charge(length, line); data.reverse(); return NaN;\n            case \"array.copy\": charge(length, line); return create([...data], line);\n            case \"array.concat\": {\n                const other = get(first, line);\n                charge(other.length, line);\n                reserve(length + other.length, other.length, line);\n                const count = other.length;\n                for (let i = 0; i < count; i++) data.push(other[i]);\n                return id;\n            }\n            case \"array.includes\":\n            case \"array.indexof\":\n            case \"array.lastindexof\": {\n                charge(length, line);\n                const equals = (value: number) => value === first || (Number.isNaN(value) && Number.isNaN(first));\n                let position = -1;\n                if (operation === \"array.lastindexof\") {\n                    for (let i = length - 1; i >= 0; i--) if (equals(data[i])) { position = i; break; }\n                } else {\n                    position = data.findIndex(equals);\n                }\n                return operation === \"array.includes\" ? Number(position !== -1) : position;\n            }\n            case \"array.join\": {\n                if (Number.isNaN(first)) return NaN;\n                charge(length, line);\n                let value = \"\";\n                for (const [i, item] of data.entries()) {\n                    const text = Number.isNaN(item) ? \"NaN\" : stringsInArray ? strings[item] : String(item);\n                    value += (i ? strings[first] : \"\") + text;\n                    if (value.length > 1024) fail(line, \"A joined string exceeds 1,024 characters.\");\n                }\n                return intern(value);\n            }\n            case \"array.sort\":\n                charge(length * Math.max(1, Math.ceil(Math.log2(length))), line);\n                if (Number.isNaN(first)) return NaN;\n                data.sort((a, b) => Number.isNaN(a) ? Number(!Number.isNaN(b)) : Number.isNaN(b) ? -1 : first * (a - b));\n                return NaN;\n        }\n        charge(length, line);\n        const sample = data.filter(value => !Number.isNaN(value));\n        if (!sample.length) return operation === \"array.standardize\" ? create([], line) : NaN;\n        const total = sample.reduce((a, b) => a + b, 0);\n        const mean = total / sample.length;\n        switch (operation) {\n            case \"array.standardize\": {\n                const deviation = Math.sqrt(sample.reduce((sum, value) => sum + (value - mean) ** 2, 0) / sample.length);\n                return create(data.map(value => deviation ? (value - mean) / deviation : NaN), line);\n            }\n            case \"array.percentrank\": {\n                const target = data[index(first, length, line)];\n                return Number.isNaN(target) ? NaN : 100 * sample.filter(value => value <= target).length / sample.length;\n            }\n            case \"array.mode\":\n            case \"array.percentile_linear_interpolation\":\n            case \"array.percentile_nearest_rank\": {\n                charge(sample.length * Math.ceil(Math.log2(sample.length)), line);\n                sample.sort((a, b) => a - b);\n                if (operation === \"array.mode\") {\n                    let best = sample[0], high = 1, count = 1;\n                    for (let i = 1; i < sample.length; i++) {\n                        count = sample[i] === sample[i - 1] ? count + 1 : 1;\n                        if (count > high) { best = sample[i]; high = count; }\n                    }\n                    return high > 1 ? best : NaN;\n                }\n                if (!Number.isFinite(first) || first < 0 || first > 100) return NaN;\n                if (operation.endsWith(\"nearest_rank\")) return sample[Math.max(0, Math.ceil(sample.length * first / 100) - 1)];\n                const rank = (sample.length - 1) * first / 100;\n                const low = Math.floor(rank);\n                return sample[low] + (rank - low) * (sample[Math.ceil(rank)] - sample[low]);\n            }\n            case \"array.sum\": return total;\n            case \"array.avg\": return mean;\n            case \"array.range\": {\n                let low = Infinity, high = -Infinity;\n                for (const value of sample) { low = Math.min(low, value); high = Math.max(high, value); }\n                return high - low;\n            }\n            case \"array.min\":\n            case \"array.max\":\n            case \"array.median\": {\n                charge(sample.length * Math.ceil(Math.log2(sample.length)), line);\n                const sign = operation === \"array.max\" ? -1 : 1;\n                sample.sort((a, b) => sign * (a - b));\n                if (operation !== \"array.median\") return sample[first] ?? NaN;\n                return (sample[Math.floor((sample.length - 1) / 2)] + sample[Math.floor(sample.length / 2)]) / 2;\n            }\n            case \"array.variance\":\n            case \"array.stdev\": {\n                const divisor = sample.length - (first ? 0 : 1);\n                if (divisor <= 0) return NaN;\n                const variance = sample.reduce((sum, value) => sum + (value - mean) ** 2, 0) / divisor;\n                return operation === \"array.stdev\" ? Math.sqrt(variance) : variance;\n            }\n            default: return fail(line, `Unknown array built-in '${operation}'.`);\n        }\n    }\n    return { execute, create, get };\n}\n","type Value = number | string | boolean | undefined;\n\nconst number = (value: Value): number => typeof value === \"number\" ? value : NaN;\nconst text = (value: Value): string => typeof value === \"string\" ? value : \"\";\nconst clamp = (value: number, low: number, high: number): number => Math.max(low, Math.min(high, value));\nconst hex = (value: number): string => value.toString(16).padStart(2, \"0\").toUpperCase();\n\nconst numeric: Record<string, (value: number, extra: number) => number> = {\n    \"math.abs\": Math.abs, \"math.acos\": Math.acos, \"math.asin\": Math.asin, \"math.atan\": Math.atan,\n    \"math.cos\": Math.cos, \"math.sin\": Math.sin, \"math.tan\": Math.tan,\n    \"math.ceil\": Math.ceil, \"math.floor\": Math.floor, \"math.exp\": Math.exp,\n    \"math.log\": Math.log, \"math.log10\": Math.log10, \"math.pow\": Math.pow,\n    \"math.sign\": Math.sign, \"math.sqrt\": Math.sqrt,\n    \"math.todegrees\": x => x * (180 / Math.PI),\n    \"math.toradians\": x => x * (Math.PI / 180),\n};\n\nfunction components(value: Value): number[] | undefined {\n    if (typeof value !== \"string\") return undefined;\n    return [1, 3, 5, 7].map(index => index >= value.length ? 255 : parseInt(value.slice(index, index + 2), 16));\n}\n\nfunction replaceNth(source: string, target: string, replacement: string, occurrence: number): string {\n    if (!target || !Number.isSafeInteger(occurrence) || occurrence < 0) return source;\n    let index = 0;\n    for (let count = 0; count <= occurrence; count++) {\n        index = source.indexOf(target, index);\n        if (index < 0) return source;\n        if (count < occurrence) index += target.length;\n    }\n    return source.slice(0, index) + replacement + source.slice(index + target.length);\n}\n\nfunction numberText(value: number, format: string, line: number): string {\n    if (!Number.isFinite(value)) return \"NaN\";\n    if (format === \"\") return String(Number(value.toFixed(10)));\n    if (format === \"format.percent\") return `${Number(value.toFixed(2))}%`;\n    if (!/^[#0]+(?:\\.[#0]+)?%?$/.test(format)) {\n        throw new Error(`Line ${line}. Unsupported numeric format '${format}'.`);\n    }\n    const percent = format.endsWith(\"%\");\n    const [whole, fraction = \"\"] = format.replace(/%$/, \"\").split(\".\");\n    if (fraction.length > 20 || whole.length > 20) throw new Error(`Line ${line}. Numeric format is too long.`);\n    const scaled = percent ? value * 100 : value;\n    const [digits, decimals = \"\"] = Math.abs(scaled).toFixed(fraction.length).split(\".\");\n    const mandatory = fraction.lastIndexOf(\"0\") + 1;\n    const fixed = decimals.slice(0, mandatory) + decimals.slice(mandatory).replace(/0+$/, \"\");\n    return (scaled < 0 ? \"-\" : \"\") + digits.padStart((whole.match(/0/g) ?? []).length, \"0\")\n        + (fixed ? \".\" + fixed : \"\") + (percent ? \"%\" : \"\");\n}\n\nexport function scalarBuiltin(name: string, args: readonly Value[], line: number): Value {\n    const [a, b, c, d, e] = args;\n    if (name === \"timeframe.from_seconds\") return timeframeFromSeconds(number(a));\n    if (name === \"timeframe.change\") {\n        const interval = parseTimeframe(text(a) || text(b), line);\n        if (!interval || interval.unit === \"T\") return false;\n        const current = timeframeBucket(number(c), interval);\n        return Number.isFinite(current) && (d === undefined || current !== timeframeBucket(number(d), interval));\n    }\n    if (name.startsWith(\"timeframe.\")) return timeframeValue(name, text(a), text(b), line);\n    if (name === \"str.format\") return formatValues(text(a), args.slice(1), line);\n    if (name in numeric) return args.some(value => value === undefined) ? undefined : numeric[name](number(a), number(b));\n    if (name === \"math.min\" || name === \"math.max\") {\n        return (name === \"math.min\" ? Math.min : Math.max)(...args.map(number));\n    }\n    if (name === \"math.avg\") return args.reduce<number>((sum, value) => sum + number(value), 0) / args.length;\n    if (name === \"math.round\") {\n        if (args.length === 1) return Math.round(number(a));\n        const scale = 10 ** number(b);\n        return Math.round(number(a) * scale) / scale;\n    }\n    if (name === \"color.rgb\" || name === \"color.new\") {\n        if (args.some(value => value === undefined)) return undefined;\n        const transparency = number(name === \"color.rgb\" ? d : b);\n        const rgb = name === \"color.rgb\"\n            ? [a, b, c].map(value => hex(Math.trunc(clamp(number(value), 0, 255)))).join(\"\")\n            : text(a).slice(1, 7);\n        return \"#\" + rgb + hex(Math.round(255 * (100 - clamp(transparency, 0, 100)) / 100));\n    }\n    if (name === \"color.from_gradient\") {\n        const bottom = components(d), top = components(e);\n        const value = number(a), low = number(b), high = number(c);\n        if (!Number.isFinite(value) || !Number.isFinite(low) || !Number.isFinite(high) || (!bottom && !top)) return undefined;\n        const ratio = high === low ? Number(value >= high) : clamp((value - low) / (high - low), 0, 1);\n        const start = bottom ?? [...top!.slice(0, 3), 0];\n        const end = top ?? [...bottom!.slice(0, 3), 0];\n        return \"#\" + start.map((channel, i) => hex(Math.round(channel + ratio * (end[i] - channel)))).join(\"\");\n    }\n    if (name.startsWith(\"color.\")) {\n        const rgba = components(a);\n        if (!rgba) return undefined;\n        if (name === \"color.t\") return (255 - rgba[3]) * 100 / 255;\n        return rgba[\"rgb\".indexOf(name[6])];\n    }\n    if (name === \"str.tostring\") {\n        if (a === undefined) return \"NaN\";\n        return typeof a === \"number\" ? numberText(a, text(b), line) : String(a);\n    }\n    if (a === undefined || (args[1] === undefined && args.length > 1)) return undefined;\n    const source = text(a);\n    const other = text(b);\n    switch (name) {\n        case \"str.contains\": return source.includes(other);\n        case \"str.endswith\": return source.endsWith(other);\n        case \"str.startswith\": return source.startsWith(other);\n        case \"str.pos\": {\n            const position = source.indexOf(other);\n            return position < 0 ? undefined : position;\n        }\n        case \"str.length\": return source.length;\n        case \"str.lower\": return source.toLowerCase();\n        case \"str.upper\": return source.toUpperCase();\n        case \"str.trim\": return source.trim();\n        case \"str.tonumber\": {\n            const raw = source.trim();\n            return /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/.test(raw) ? Number(raw) : undefined;\n        }\n        case \"str.substring\": {\n            const start = number(b), end = c === undefined ? source.length : number(c);\n            if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start || end > source.length) {\n                throw new Error(`Line ${line}. Substring bounds are outside the string.`);\n            }\n            return source.slice(start, end);\n        }\n        case \"str.repeat\": {\n            const repeat = number(b), separator = text(c);\n            if (!Number.isSafeInteger(repeat) || repeat < 0 || repeat > 1024\n                || repeat * source.length + Math.max(0, repeat - 1) * separator.length > 1024) {\n                throw new Error(`Line ${line}. A repeated string exceeds the runtime limit.`);\n            }\n            return Array.from({ length: repeat }, () => source).join(separator);\n        }\n        case \"str.replace\": return replaceNth(source, other, text(c), number(d));\n        case \"str.replace_all\": return other ? source.split(other).join(text(c)) : source;\n        default: throw new Error(`Line ${line}. Unknown scalar built-in '${name}'.`);\n    }\n}\n\nconst TIMEFRAME_SECONDS: Record<string, number> = { \"\": 60, S: 1, D: 86400, W: 604800, M: 2628003 };\nconst TIMEFRAME_FLAGS: Record<string, string[]> = {\n    \"timeframe.isdaily\": [\"D\"], \"timeframe.isweekly\": [\"W\"], \"timeframe.ismonthly\": [\"M\"],\n    \"timeframe.isdwm\": [\"D\", \"W\", \"M\"], \"timeframe.isintraday\": [\"\", \"S\"],\n    \"timeframe.isminutes\": [\"\"], \"timeframe.isseconds\": [\"S\"], \"timeframe.isticks\": [\"T\"],\n};\n\nexport function pineInterval(interval?: string): string | undefined {\n    const match = /^(\\d+)([smhdw])$/.exec(interval ?? \"\");\n    if (!match) return undefined;\n    const [, value, unit] = match;\n    if (unit === \"h\") return String(Number(value) * 60);\n    return value + (unit === \"m\" ? \"\" : unit.toUpperCase());\n}\n\ntype Timeframe = { multiplier: number; unit: string };\nconst validSeconds = [1, 5, 10, 15, 30, 45];\nconst unitLimits: Record<string, number> = { \"\": 1440, D: 365, W: 52, M: 12 };\n\nexport function parseTimeframe(value: string, line: number): Timeframe | undefined {\n    if (!value) return undefined;\n    const match = /^(\\d*)([TSDWM]?)$/.exec(value);\n    if (!match) throw new Error(`Line ${line}. Invalid Pine timeframe '${value}'.`);\n    const [, digits, unit] = match;\n    const multiplier = digits ? Number(digits) : 1;\n    const valid = unit === \"S\" ? validSeconds.includes(multiplier)\n        : unit === \"T\" ? [1, 10, 100, 1000].includes(multiplier)\n        : multiplier >= 1 && multiplier <= unitLimits[unit];\n    if (!valid) throw new Error(`Line ${line}. Invalid Pine timeframe '${value}'.`);\n    return { multiplier, unit };\n}\n\nfunction timeframeValue(name: string, interval: string, fallback: string, line: number): Value {\n    const result = parseTimeframe(interval || fallback, line);\n    if (!result) return undefined;\n    const { multiplier, unit } = result;\n    if (name === \"timeframe.multiplier\") return multiplier;\n    if (name === \"timeframe.in_seconds\") return multiplier * (TIMEFRAME_SECONDS[unit] ?? NaN);\n    return TIMEFRAME_FLAGS[name].includes(unit);\n}\n\nfunction timeframeFromSeconds(seconds: number): string | undefined {\n    if (!Number.isFinite(seconds)) return undefined;\n    const subMinute = validSeconds.find(candidate => candidate >= seconds);\n    if (subMinute !== undefined) return `${subMinute}S`;\n    let best = \"12M\", duration = Infinity;\n    // Later, larger units win ties such as 1440 minutes and one day.\n    for (const unit of [\"\", \"D\", \"W\", \"M\"]) {\n        const base = TIMEFRAME_SECONDS[unit];\n        const multiplier = Math.max(1, Math.ceil(seconds / base));\n        const candidate = base * multiplier;\n        if (multiplier <= unitLimits[unit] && candidate <= duration) {\n            best = `${multiplier}${unit}`;\n            duration = candidate;\n        }\n    }\n    return best;\n}\n\nfunction timeframeBucket(time: number, interval: Timeframe): number {\n    const { multiplier, unit } = interval;\n    if (unit === \"M\") {\n        const date = new Date(time);\n        return Math.floor((date.getUTCFullYear() * 12 + date.getUTCMonth()) / multiplier);\n    }\n    const monday = unit === \"W\" ? 4 * 86400 : 0;\n    return Math.floor((time / 1000 - monday) / (TIMEFRAME_SECONDS[unit] * multiplier));\n}\n\nfunction formatValues(template: string, values: readonly Value[], line: number): string {\n    let result = \"\", quoted = false;\n    const tokens = /''|'|\\{[^{}]*\\}|[^'{}]+|[{}]/g;\n    for (const match of template.matchAll(tokens)) {\n        const token = match[0];\n        if (token === \"''\") { result += \"'\"; continue; }\n        if (token === \"'\") { quoted = !quoted; continue; }\n        if (quoted || !token.startsWith(\"{\")) {\n            if (!quoted && token === \"}\") throw new Error(`Line ${line}. Unbalanced str.format() braces.`);\n            result += token;\n            continue;\n        }\n        const placeholder = /^\\{(\\d+)(?:\\s*,\\s*number(?:\\s*,\\s*([^}]+))?)?\\}$/.exec(token);\n        if (!placeholder) throw new Error(`Line ${line}. Unsupported str.format() placeholder '${token}'.`);\n        const index = Number(placeholder[1]);\n        if (index >= values.length) { result += token; continue; }\n        const value = values[index];\n        const style = placeholder[2]?.trim() ?? \"\";\n        if (typeof value === \"number\") result += numberText(value, style === \"integer\" ? \"0\" : style === \"percent\" ? \"0.##%\" : style, line);\n        else if (style) throw new Error(`Line ${line}. Numeric str.format() needs a number.`);\n        else result += value === undefined ? \"NaN\" : String(value);\n        if (result.length > 1024) throw new Error(`Line ${line}. A string exceeds the 1,024 character limit.`);\n    }\n    return result;\n}\n","type Ohlc = { open: number; high: number; low: number; close: number };\ntype Period = { current?: Ohlc; previous?: Ohlc };\nconst TYPES = new Set([\"Traditional\", \"Fibonacci\", \"Woodie\", \"Classic\", \"DM\", \"Camarilla\"]);\n\nfunction levels(kind: string, prior: Ohlc, currentOpen: number): number[] {\n    const { open, high, low, close } = prior;\n    const span = high - low;\n    const pivot = kind === \"Woodie\" ? (high + low + 2 * currentOpen) / 4 : (high + low + close) / 3;\n    const pair = (center: number, distance: number): number[] => [center + distance, center - distance];\n    if (kind === \"Fibonacci\") return [pivot, ...[0.382, 0.618, 1].flatMap(weight => pair(pivot, weight * span))];\n    if (kind === \"Camarilla\") {\n        const top = close * (high / low);\n        return [pivot, ...[12, 6, 4, 2].flatMap(divisor => pair(close, 1.1 * span / divisor)), top, 2 * close - top];\n    }\n    if (kind === \"DM\") {\n        const total = high + low + close + (close === open ? close : close > open ? high : low);\n        return [total / 4, total / 2 - low, total / 2 - high];\n    }\n    const result = [pivot, 2 * pivot - low, 2 * pivot - high, ...pair(pivot, span)];\n    if (kind === \"Classic\") return [...result, ...pair(pivot, 2 * span), ...pair(pivot, 3 * span)];\n    if (kind === \"Woodie\") {\n        const top = high + 2 * (pivot - low), bottom = low - 2 * (high - pivot);\n        return [...result, top, bottom, top + span, bottom - span];\n    }\n    for (let order = 2; order <= 4; order++) {\n        result.push(order * (pivot - low) + high, order * (pivot - high) + low);\n    }\n    return result;\n}\n\nexport function pivotRuntime() {\n    const periods = new Map<number, Period>();\n    return (site: number, type: string, anchor: boolean, developing: boolean, candle: Ohlc, line: number): number[] => {\n        if (!TYPES.has(type)) throw new Error(`Line ${line}. Unknown pivot type '${type}'.`);\n        if (type === \"Woodie\" && developing) throw new Error(`Line ${line}. Woodie pivots require a fixed anchor period.`);\n        let period = periods.get(site);\n        if (!period) periods.set(site, period = {});\n        if (anchor) {\n            period.previous = period.current;\n            period.current = { ...candle };\n        } else if (period.current) {\n            period.current.high = Math.max(period.current.high, candle.high);\n            period.current.low = Math.min(period.current.low, candle.low);\n            period.current.close = candle.close;\n        }\n        const source = developing ? period.current : period.previous;\n        const points = source ? levels(type, source, period.current!.open) : [];\n        return Array.from({ length: 11 }, (_, i) => Number.isFinite(points[i]) ? points[i] : NaN);\n    };\n}\n","export const MAX_HISTORY = 5_000;\nconst MAX_WINDOW_WORK = 30_000_000;\n\ntype WindowState = { values: number[]; count: number };\nconst push = (window: WindowState, value: number): void => {\n    window.values[window.count % MAX_HISTORY] = value;\n    window.count++;\n};\nconst back = (window: WindowState, offset: number): number =>\n    offset <= window.count ? window.values[(window.count - offset) % MAX_HISTORY] : NaN;\n\nexport function technicalRuntime() {\n    const states = new Map<number, WindowState>();\n    const scalars = new Map<number, number>();\n    const paired = new Map<number, WindowState>();\n    const volumeIndices = new Map<number, { close: number; volume: number; index: number }>();\n    const sars = new Map<number, { bull: boolean; sar: number; extreme: number; factor: number;\n        lastHigh: number; lastLow: number; secondHigh: number; secondLow: number }>();\n    const weighted = new Map<number, { volume: number; mean: number; squares: number }>();\n    const trends = new Map<number, { close: number; upper: number; lower: number; direction: number }>();\n    const randomStates = new Map<number, { seed: number; value: number }>();\n    const cumulativeSums = new Map<number, number[]>();\n    const extrema = new Map<number, { bar: number; source: number; length: number; result: number; wrote: boolean }>();\n    let work = 0;\n\n    function windowFor(site: number): WindowState {\n        let state = states.get(site);\n        if (!state) states.set(site, state = { values: [], count: 0 });\n        return state;\n    }\n\n    function charge(length: number, line: number): void {\n        work += length;\n        if (work > MAX_WINDOW_WORK) throw new Error(`Line ${line}. The script exceeded its rolling-window calculation limit.`);\n    }\n\n    return (name: string, site: number, line: number, source: number, length: number,\n        first: number, second: number, third: number, high: number, low: number, barIndex: number): number | number[] => {\n        if (name === \"ta.nvi\" || name === \"ta.pvi\") {\n            const previous = volumeIndices.get(site);\n            const previousIndex = previous?.index || 1;\n            const compare = name === \"ta.nvi\" ? length < (previous?.volume || 0) : length > (previous?.volume || 0);\n            const index = previous?.close && source && compare ? previousIndex + (source - previous.close) / previous.close * previousIndex : previousIndex;\n            volumeIndices.set(site, { close: source, volume: length, index });\n            return index;\n        }\n        if (name === \"ta.sar\") {\n            const start = length, step = first, limit = second;\n            if ([start, step, limit].some(Number.isNaN)) return NaN;\n            const previous = sars.get(site);\n            if (!previous) {\n                sars.set(site, { bull: false, sar: NaN, extreme: NaN, factor: start,\n                    lastHigh: high, lastLow: low, secondHigh: NaN, secondLow: NaN });\n                return NaN;\n            }\n            let { bull, sar, extreme, factor } = previous;\n            let firstTrendBar = Number.isNaN(sar);\n            if (firstTrendBar) {\n                bull = Boolean(source);\n                sar = bull ? previous.lastLow : previous.lastHigh;\n                extreme = bull ? high : low;\n                factor = start;\n            }\n            sar += factor * (extreme - sar);\n            if ((bull && sar > low) || (!bull && sar < high)) {\n                sar = bull ? Math.max(high, extreme) : Math.min(low, extreme);\n                bull = !bull;\n                extreme = bull ? high : low;\n                factor = start;\n                firstTrendBar = true;\n            }\n            if (!firstTrendBar && (bull ? high > extreme : low < extreme)) {\n                extreme = bull ? high : low;\n                factor = Math.min(factor + step, limit);\n            }\n            sar = bull ? Math.min(sar, previous.lastLow, Number.isNaN(previous.secondLow) ? previous.lastLow : previous.secondLow)\n                : Math.max(sar, previous.lastHigh, Number.isNaN(previous.secondHigh) ? previous.lastHigh : previous.secondHigh);\n            sars.set(site, { bull, sar, extreme, factor, lastHigh: high, lastLow: low,\n                secondHigh: previous.lastHigh, secondLow: previous.lastLow });\n            return sar;\n        }\n        if (name === \"fixnan\") {\n            if (!Number.isNaN(source)) scalars.set(site, source);\n            return scalars.get(site) ?? NaN;\n        }\n        if (name === \"ta.vwap\") {\n            if (first) weighted.set(site, { volume: 0, mean: 0, squares: 0 });\n            const state = weighted.get(site);\n            if (state && !Number.isNaN(source) && Number.isFinite(length) && length > 0) {\n                state.volume += length;\n                const delta = source - state.mean;\n                state.mean += delta * (length / state.volume);\n                state.squares += length * delta * (source - state.mean);\n            }\n            const mean = state?.volume ? state.mean : NaN;\n            if (!third) return mean;\n            const width = state?.volume ? Math.sqrt(Math.max(0, state.squares / state.volume)) * second : NaN;\n            return [mean, mean + width, mean - width];\n        }\n        if (name === \"math.random\") {\n            if (!Number.isFinite(source) || !Number.isFinite(length) || source >= length) return NaN;\n            let state = randomStates.get(site);\n            if (!state || !Object.is(first, state.seed)) {\n                state = { seed: first, value: Number.isNaN(first) ? Math.floor(Math.random() * 2 ** 32) : first >>> 0 };\n                randomStates.set(site, state);\n            }\n            state.value = (Math.imul(1664525, state.value) + 1013904223) >>> 0;\n            return source + (length - source) * ((state.value + 0.5) / 2 ** 32);\n        }\n        if (name === \"ta.max\" || name === \"ta.min\") {\n            let result = scalars.get(site);\n            if (!Number.isNaN(source)) {\n                result = result === undefined ? source : (name === \"ta.max\" ? Math.max : Math.min)(result, source);\n                scalars.set(site, result);\n            }\n            return result ?? NaN;\n        }\n        if (name === \"ta.supertrend\") {\n            const close = source, atr = length, middle = first, factor = second;\n            const previous = trends.get(site);\n            const rawUpper = middle + factor * atr, rawLower = middle - factor * atr;\n            const prevUpper = previous?.upper ?? NaN, prevLower = previous?.lower ?? NaN;\n            const upper = Number.isNaN(prevUpper) || rawUpper < prevUpper || previous!.close > prevUpper ? rawUpper : prevUpper;\n            const lower = Number.isNaN(prevLower) || rawLower > prevLower || previous!.close < prevLower ? rawLower : prevLower;\n            const direction = !previous || Number.isNaN(prevUpper) ? 1\n                : previous.direction === 1 ? (close > upper ? -1 : 1) : (close < lower ? 1 : -1);\n            trends.set(site, { close, upper, lower, direction });\n            return [Number.isNaN(atr) ? NaN : direction === 1 ? upper : lower, direction];\n        }\n        if (name === \"ta.pivothigh\" || name === \"ta.pivotlow\") {\n            const window = windowFor(site);\n            push(window, source);\n            const left = Math.trunc(length), right = Math.trunc(first);\n            if (!Number.isFinite(left + right)) return NaN;\n            if (left < 0 || right < 0 || left + right >= MAX_HISTORY) {\n                throw new Error(`Line ${line}. Pivot history must be below ${MAX_HISTORY} bars.`);\n            }\n            if (window.count <= left + right) return NaN;\n            const candidate = back(window, right + 1);\n            if (Number.isNaN(candidate)) return NaN;\n            charge(left + right + 1, line);\n            const sign = name === \"ta.pivothigh\" ? 1 : -1;\n            for (let offset = 1; offset <= left + right + 1; offset++) {\n                if (offset === right + 1) continue;\n                const delta = sign * (candidate - back(window, offset));\n                if (Number.isNaN(delta) || delta < 0 || (delta === 0 && offset <= right)) return NaN;\n            }\n            return candidate;\n        }\n        if (name === \"ta.rsi_delta\") {\n            if (Number.isNaN(source)) return NaN;\n            const previous = scalars.get(site) ?? NaN;\n            scalars.set(site, source);\n            return source - previous;\n        }\n        if (name === \"ta.cum\") {\n            if (Number.isNaN(source)) return NaN;\n            const next = (scalars.get(site) ?? 0) + source;\n            scalars.set(site, next);\n            return next;\n        }\n        if (name === \"ta.barssince\") {\n            const next = source ? 0 : (scalars.get(site) ?? NaN) + 1;\n            scalars.set(site, next);\n            return next;\n        }\n        if (name === \"ta.valuewhen\") {\n            const occurrence = first;\n            if (occurrence < 0 || occurrence >= MAX_HISTORY) {\n                throw new Error(`Line ${line}. Occurrence must be between 0 and ${MAX_HISTORY - 1}.`);\n            }\n            const window = windowFor(site);\n            if (source) push(window, length);\n            return Number.isNaN(occurrence) ? NaN : back(window, occurrence + 1);\n        }\n        if (length < 1 || length > MAX_HISTORY) {\n            const label = name === \"ta.sma\" || name === \"ta.ema\" ? \"Moving average length\" : \"Length\";\n            throw new Error(`Line ${line}. ${label} must be between 1 and ${MAX_HISTORY}.`);\n        }\n        if (name === \"ta.ema\") {\n            const previous = scalars.get(site) ?? NaN;\n            if (Number.isNaN(source) || Number.isNaN(length)) return previous;\n            const next = Number.isNaN(previous) ? source : previous + (source - previous) * (2 / (length + 1));\n            const result = Number.isFinite(next) ? next : NaN;\n            scalars.set(site, result);\n            return result;\n        }\n        if (name === \"ta.sma\" || name === \"math.sum\") {\n            let totals = cumulativeSums.get(site);\n            if (!totals) cumulativeSums.set(site, totals = [0]);\n            if (!Number.isNaN(source)) {\n                const total = totals[totals.length - 1] + source;\n                if (!Number.isFinite(total)) throw new Error(`Line ${line}. Moving average accumulated a non-finite value.`);\n                totals.push(total);\n            }\n            if (Number.isNaN(length) || totals.length <= length) return NaN;\n            const end = totals.length - 1;\n            const total = totals[end] - totals[end - length];\n            return name === \"math.sum\" ? total : total / length;\n        }\n        if (name === \"ta.change\" || name === \"ta.roc\" || name === \"ta.mom\") {\n            const window = windowFor(site);\n            const previous = Number.isNaN(length) ? NaN : back(window, length);\n            push(window, source);\n            return name === \"ta.roc\" ? (previous === 0 ? NaN : 100 * (source - previous) / previous)\n                : source - previous;\n        }\n\n        if (name === \"ta.correlation\") {\n            const window = windowFor(site);\n            let other = paired.get(site);\n            if (!other) paired.set(site, other = { values: [], count: 0 });\n            if (!Number.isNaN(source) && !Number.isNaN(first)) {\n                push(window, source);\n                push(other, first);\n            }\n            if (Number.isNaN(length) || window.count < length) return NaN;\n            charge(length, line);\n            let xMean = 0, yMean = 0, xx = 0, yy = 0, xy = 0;\n            for (let i = 1; i <= length; i++) {\n                const x = back(window, i), y = back(other, i);\n                const dx = x - xMean, dy = y - yMean;\n                xMean += dx / i;\n                yMean += dy / i;\n                xx += dx * (x - xMean);\n                yy += dy * (y - yMean);\n                xy += dx * (y - yMean);\n            }\n            return xy / Math.sqrt(xx * yy);\n        }\n        if (name === \"ta.rising\" || name === \"ta.falling\") {\n            const window = windowFor(site);\n            if (Number.isNaN(source)) return 0;\n            let result = !Number.isNaN(length) && window.count >= length;\n            if (result) {\n                charge(length, line);\n                for (let i = 1; i <= length && result; i++) {\n                    result = name === \"ta.rising\" ? source > back(window, i) : source < back(window, i);\n                }\n            }\n            push(window, source);\n            return Number(result);\n        }\n        if (name === \"ta.highestbars\" || name === \"ta.lowestbars\") {\n            const window = windowFor(site);\n            push(window, source);\n            if (Number.isNaN(length)) return NaN;\n            const sign = name === \"ta.highestbars\" ? 1 : -1;\n            let best = -Infinity, offset = NaN;\n            const count = Math.min(window.count, length);\n            charge(count, line);\n            for (let i = 1; i <= count; i++) {\n                const current = sign * back(window, i);\n                if (current > best) { best = current; offset = 1 - i; }\n            }\n            return offset;\n        }\n\n        const smoothed = scalars.get(site);\n        if (name === \"ta.rma\" && smoothed !== undefined) {\n            const next = Number.isNaN(source) || Number.isNaN(length) ? smoothed\n                : smoothed + (source - smoothed) / length;\n            scalars.set(site, next);\n            return next;\n        }\n        const window = windowFor(site);\n        if (name === \"ta.highest\" || name === \"ta.lowest\") {\n            const previous = extrema.get(site);\n            const sameBar = previous?.bar === barIndex;\n            if (sameBar && Object.is(previous.source, source) && Object.is(previous.length, length)) return previous.result;\n            // A call site inside a loop still contributes one sample to bar history.\n            const wrote = (sameBar && previous.wrote) || !Number.isNaN(source);\n            if (!Number.isNaN(source)) {\n                if (sameBar && previous.wrote) window.values[(window.count - 1) % MAX_HISTORY] = source;\n                else push(window, source);\n            }\n            const count = Math.min(length, window.count);\n            let result = NaN;\n            if (count > 0) {\n                charge(count, line);\n                const extreme = name === \"ta.highest\" ? Math.max : Math.min;\n                result = back(window, 1);\n                for (let offset = 2; offset <= count; offset++) result = extreme(result, back(window, offset));\n            }\n            extrema.set(site, { bar: barIndex, source, length, result, wrote });\n            return result;\n        }\n        const includesMissing = name === \"ta.alma\" || name === \"ta.linreg\" || name === \"ta.swma\"\n            || name === \"ta.percentrank\" || name === \"ta.percentile_linear_interpolation\" || name === \"ta.rci\";\n        if (!Number.isNaN(source) || includesMissing) push(window, source);\n        if (Number.isNaN(length)) return NaN;\n        if (length === 0 || window.count < length) return NaN;\n        charge(length, line);\n\n        let total = 0;\n        if (name === \"ta.swma\") {\n            return (back(window, 1) + 2 * back(window, 2) + 2 * back(window, 3) + back(window, 4)) / 6;\n        }\n        if (name === \"ta.rci\") {\n            const points = Array.from({ length }, (_, i) => ({ price: back(window, length - i), bar: i }));\n            if (points.some(point => Number.isNaN(point.price))) return NaN;\n            charge(length * Math.ceil(Math.log2(length)), line);\n            points.sort((a, b) => a.price - b.price);\n            const mean = (length - 1) / 2;\n            let xy = 0, yy = 0;\n            for (let start = 0; start < length;) {\n                let end = start + 1;\n                while (end < length && points[end].price === points[start].price) end++;\n                const rank = (start + end - 1) / 2 - mean;\n                for (let i = start; i < end; i++) xy += (points[i].bar - mean) * rank;\n                yy += (end - start) * rank * rank;\n                start = end;\n            }\n            return 100 * xy / Math.sqrt(yy * length * (length ** 2 - 1) / 12);\n        }\n        if (name === \"ta.percentrank\") {\n            if (Number.isNaN(source)) return NaN;\n            let count = 0;\n            for (let i = 1; i <= length; i++) {\n                const value = back(window, i);\n                if (Number.isNaN(value)) return NaN;\n                if (value <= source) count++;\n            }\n            return 100 * count / length;\n        }\n        if (name === \"ta.range\" || name === \"ta.median\" || name === \"ta.mode\"\n            || name === \"ta.percentile_linear_interpolation\" || name === \"ta.percentile_nearest_rank\") {\n            const sample = Array.from({ length }, (_, i) => back(window, i + 1));\n            if (sample.some(Number.isNaN)) return NaN;\n            if (name === \"ta.range\") {\n                let low = Infinity, high = -Infinity;\n                for (const value of sample) { low = Math.min(low, value); high = Math.max(high, value); }\n                return high - low;\n            }\n            charge(length * Math.ceil(Math.log2(length)), line);\n            sample.sort((a, b) => a - b);\n            if (name === \"ta.median\") return (sample[Math.floor((length - 1) / 2)] + sample[Math.floor(length / 2)]) / 2;\n            if (name === \"ta.mode\") {\n                let best = sample[0], bestCount = 1, count = 1;\n                for (let i = 1; i < sample.length; i++) {\n                    count = sample[i] === sample[i - 1] ? count + 1 : 1;\n                    if (count > bestCount) { best = sample[i]; bestCount = count; }\n                }\n                return best;\n            }\n            if (!Number.isFinite(first) || first < 0 || first > 100) return NaN;\n            if (name === \"ta.percentile_nearest_rank\") return sample[Math.max(0, Math.ceil(length * first / 100) - 1)];\n            const position = (length - 1) * first / 100;\n            const index = Math.floor(position);\n            return sample[index] + (position - index) * (sample[Math.ceil(position)] - sample[index]);\n        }\n        if (name === \"ta.linreg\") {\n            const xMean = (length - 1) / 2;\n            let covariance = 0;\n            for (let i = 0; i < length; i++) {\n                const y = back(window, length - i);\n                total += y;\n                covariance += (i - xMean) * y;\n            }\n            const slope = length === 1 ? 0 : covariance / (length * (length ** 2 - 1) / 12);\n            return total / length + slope * (length - 1 - xMean - first);\n        }\n        if (name === \"ta.cog\") {\n            let weighted = 0;\n            for (let i = 1; i <= length; i++) {\n                const value = back(window, i);\n                total += value;\n                weighted += i * value;\n            }\n            return -weighted / total;\n        }\n        if (name === \"ta.wma\") {\n            for (let offset = 1; offset <= length; offset++) total += back(window, offset) * (length + 1 - offset);\n            return total / (length * (length + 1) / 2);\n        }\n        if (name === \"ta.alma\") {\n            if (!Number.isFinite(first) || !Number.isFinite(second) || second <= 0) return NaN;\n            let center = first * (length - 1);\n            if (third) center = Math.floor(center);\n            const distances: number[] = [];\n            let minimum = Infinity;\n            for (let offset = 1; offset <= length; offset++) {\n                const scaled = (length - offset - center) * second / length;\n                const distance = scaled * scaled;\n                distances.push(distance);\n                minimum = Math.min(minimum, distance);\n            }\n            if (!Number.isFinite(minimum)) return NaN;\n            let weights = 0;\n            for (let offset = 1; offset <= length; offset++) {\n                const weight = Math.exp(-0.5 * (distances[offset - 1] - minimum));\n                weights += weight;\n                total += weight * back(window, offset);\n            }\n            return total / weights;\n        }\n        for (let offset = 1; offset <= length; offset++) total += back(window, offset);\n        const mean = total / length;\n        if (name === \"ta.rma\") {\n            scalars.set(site, mean);\n            return mean;\n        }\n        if (name === \"ta.dev\" || name === \"ta.cci\") {\n            let deviation = 0;\n            for (let i = 1; i <= length; i++) deviation += Math.abs(back(window, i) - mean);\n            deviation /= length;\n            return name === \"ta.dev\" ? deviation : (source - mean) / (0.015 * deviation);\n        }\n        const divisor = first ? length : length - 1;\n        if (!divisor) return NaN;\n        let sumSquares = 0;\n        for (let offset = 1; offset <= length; offset++) {\n            const delta = back(window, offset) - mean;\n            sumSquares += delta * delta;\n        }\n        const variance = sumSquares / divisor;\n        return name === \"ta.variance\" ? variance : Math.sqrt(variance);\n    };\n}\n","import { calendarRuntime } from \"./calendar.ts\";\nimport { mapRuntime } from \"./maps.ts\";\nimport { matrixRuntime } from \"./matrices.ts\";\nimport { arrayRuntime } from \"./arrays.ts\";\nimport { parseTimeframe, pineInterval, scalarBuiltin } from \"./builtins.ts\";\nimport { pivotRuntime } from \"./pivots.ts\";\nimport { MAX_HISTORY, technicalRuntime } from \"./technical.ts\";\nimport { chartTime, type Candle } from \"../charts/ChartApi.ts\";\nimport type {\n    IndicatorFillPoint, IndicatorLineSpec, IndicatorLineWidth, IndicatorParameterSpec, IndicatorParameterValue, IndicatorResponse,\n} from \"../charts/IndicatorContracts\";\n\nexport type Dialect = \"pine\" | \"zero\";\nexport type ScriptSource = { source: string; dialect: Dialect };\n\ntype ScriptInput = {\n    id: string;\n    title: string;\n    type: \"int\" | \"float\" | \"bool\" | \"string\" | \"color\" | \"source\";\n    default: IndicatorParameterValue;\n    min?: number;\n    max?: number;\n    step?: number;\n    options?: IndicatorParameterValue[];\n    description?: string;\n    display: number;\n};\ntype Bytecode = {\n    abi: number; title: string; overlay: boolean; inputs: ScriptInput[];\n    variables: number; strings: string[]; wasm: string;\n    priceFormat: IndicatorLineSpec[\"priceFormat\"] | \"inherit\" | null;\n    precision: number | null;\n    plots: {\n        title: string; linewidth: IndicatorLineWidth; color?: string; base: number;\n        style: \"line\" | \"histogram\" | \"columns\"; lineStyle: IndicatorLineSpec[\"lineStyle\"]; display: number;\n    }[];\n    fills: { first: number; second: number; title: string; fillGaps: boolean; display: number }[];\n    alerts: { title: string; message: string }[];\n};\nexport type CompiledScript = Omit<Bytecode, \"wasm\"> & { module: WebAssembly.Module };\n\nexport async function compileScript(url: string, csrf: string, script: ScriptSource): Promise<CompiledScript> {\n    const response = await fetch(url, {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\", \"X-CSRFToken\": csrf },\n        body: JSON.stringify(script),\n    });\n    if (!response.ok) {\n        const failure = await response.json().catch(() => null);\n        const location = failure?.line ? `Line ${failure.line}${failure.column ? `, column ${failure.column}` : \"\"}. ` : \"\";\n        throw new Error(location + (failure?.error ?? `Compile failed (HTTP ${response.status}).`));\n    }\n    const { wasm, ...scriptData }: Bytecode = await response.json();\n    if (scriptData.abi !== 7) throw new Error(\"Unsupported script runtime version. Reload the chart workspace.\");\n    const module = await WebAssembly.compile(Uint8Array.from(atob(wasm), byte => byte.charCodeAt(0)));\n    return { ...scriptData, module };\n}\n\nconst MAX_BARS = 20_000;\nconst inputTypes = { int: \"integer\", float: \"number\", bool: \"boolean\", string: \"text\", color: \"text\", source: \"select\" } as const;\nconst COLOR = /^#(?:[a-f0-9]{6}|[a-f0-9]{8})$/i;\nconst DEFAULT_COLOR = \"#2196F3\";\nconst DISPLAY_PANE = 1;\nconst DISPLAY_PRICE_SCALE = 2;\nconst INTERVAL_SECONDS = { m: 60, h: 3_600, d: 86_400, w: 604_800 };\n\nfunction barSpacing(timeframe: string | undefined, bars: readonly Candle[]): number {\n    const interval = /^(\\d+)([mhdw])$/.exec(timeframe ?? \"\");\n    if (interval) return Number(interval[1]) * INTERVAL_SECONDS[interval[2] as keyof typeof INTERVAL_SECONDS];\n    return bars.length >= 2 ? Math.max(1, chartTime(bars[bars.length - 1].time) - chartTime(bars[bars.length - 2].time)) : 60;\n}\n\nconst FEED = [\"open\", \"high\", \"low\", \"close\", \"hl2\", \"hlc3\", \"ohlc4\", \"volume\", \"bar_index\", \"time\", \"hlcc4\"];\n\nfunction parametersFor(inputs: ScriptInput[], overrides?: Record<string, IndicatorParameterValue>): IndicatorParameterSpec[] {\n    return inputs.map(spec => {\n        const value = overrides && Object.prototype.hasOwnProperty.call(overrides, spec.id) ? overrides[spec.id] : spec.default;\n        const valid = spec.type === \"int\" ? typeof value === \"number\" && Number.isSafeInteger(value)\n            : spec.type === \"float\" ? typeof value === \"number\" && Number.isFinite(value)\n            : spec.type === \"bool\" ? typeof value === \"boolean\"\n            : typeof value === \"string\" && (spec.type === \"color\" ? COLOR.test(value) : value.length <= 1024);\n        if (!valid) throw new Error(`${spec.title} needs a valid ${spec.type} value.`);\n        if (typeof value === \"number\" && (value < (spec.min ?? -Infinity) || value > (spec.max ?? Infinity))) {\n            throw new Error(`${spec.title} is outside its allowed range.`);\n        }\n        if (spec.options && !spec.options.includes(value)) throw new Error(`${spec.title} must be one of the listed options.`);\n        const { id, title: label, min, max, step, description } = spec;\n        const options = spec.options?.map(item => ({ value: item, label: String(item) }));\n        return { id, label, value, min, max, step, description, options, type: options ? \"select\" : inputTypes[spec.type] };\n    });\n}\n\nfunction normalized(value: number, integer: number): number {\n    return (integer ? Number.isSafeInteger(value) : Number.isFinite(value)) ? value : NaN;\n}\n\nfunction compare(op: number, a: number, b: number): number {\n    if (op === 6) return Number(Number.isNaN(a));\n    if (Number.isNaN(a) || Number.isNaN(b)) return 0;\n    if (!Number.isInteger(a)) a = Number(a.toFixed(9));\n    if (!Number.isInteger(b)) b = Number(b.toFixed(9));\n    switch (op) {\n        case 0: return Number(a === b);\n        case 1: return Number(a !== b);\n        case 2: return Number(a > b);\n        case 3: return Number(a >= b);\n        case 4: return Number(a < b);\n        case 5: return Number(a <= b);\n        default: throw new Error(\"Unknown WebAssembly comparison.\");\n    }\n}\n\n/** Each invocation owns a fresh instance, including all historical and call-site state. */\nexport function runScript(\n    program: CompiledScript,\n    id: string,\n    candles: readonly Candle[],\n    overrides?: Record<string, IndicatorParameterValue>,\n    timeframe?: string,\n    symbol?: string,\n): IndicatorResponse {\n    const bars = candles.length > MAX_BARS ? candles.slice(-MAX_BARS) : candles;\n    const strings = [...program.strings];\n    const interned = new Map(strings.map((text, index) => [text, index]));\n    const intern = (text: string): number => {\n        const existing = interned.get(text);\n        if (existing !== undefined) return existing;\n        const index = strings.length;\n        interned.set(text, index);\n        strings.push(text);\n        return index;\n    };\n    const interval = pineInterval(timeframe);\n    const intervalHandle = interval === undefined ? NaN : intern(interval);\n    const chartInterval = parseTimeframe(interval ?? \"\", 0);\n    const separator = symbol?.lastIndexOf(\":\") ?? -1;\n    const symbolFields = symbol ? [symbol, symbol, symbol.slice(separator + 1), symbol.slice(0, Math.max(0, separator))].map(intern) : [];\n    const checkedIntervals = new Map<number, boolean>();\n    const alerts: NonNullable<IndicatorResponse[\"alerts\"]> = (program.alerts ?? []).map(alert => ({ ...alert, times: [] }));\n    const barColors = new Map<number, string>();\n    const parameters = parametersFor(program.inputs, overrides);\n    const inputs = parameters.map(({ value }) => typeof value === \"string\" ? intern(value) : Number(value));\n    const plots: IndicatorResponse[\"plots\"] = [{\n        id: \"script\", title: program.title,\n        lines: program.plots.map((plot, index) => ({\n            id: `line-${index + 1}`, title: plot.title, data: [], lineWidth: plot.linewidth,\n            color: plot.color ?? DEFAULT_COLOR, respectReplay: true, onPriceScale: program.overlay,\n            plotStyle: plot.style === \"line\" ? \"line\" : \"histogram\",\n            histogramBase: plot.base,\n            drawInPane: Boolean(plot.display & DISPLAY_PANE),\n            showPriceLabel: Boolean(plot.display & DISPLAY_PRICE_SCALE),\n            lineStyle: plot.lineStyle,\n            priceFormat: program.priceFormat === \"inherit\" ? undefined : program.priceFormat ?? undefined,\n            precision: program.precision ?? undefined,\n        })),\n    }];\n    const lines = plots[0].lines;\n    const plotIndices = lines.map(() => [] as number[]);\n    const plotOffsets = lines.map(() => 0);\n    const fillColors = program.fills.map(() => [] as (string | undefined)[]);\n    const spacing = barSpacing(timeframe, bars);\n    const lastTime = bars.length ? chartTime(bars[bars.length - 1].time) : 0;\n    const values = new Float64Array(program.variables).fill(NaN);\n    const histories = Array.from({ length: program.variables }, () => new Float64Array(Math.min(bars.length, MAX_HISTORY)));\n    const counts = new Uint32Array(program.variables);\n    const written = new Set<number>();\n    const tuples: number[][] = [];\n    const technical = technicalRuntime();\n    const calendar = calendarRuntime();\n    const arrays = arrayRuntime(strings, intern);\n    const maps = mapRuntime(arrays.create);\n    const matrices = matrixRuntime(arrays, strings);\n    const pivots = pivotRuntime();\n    const crosses = new Map<number, [number, number]>();\n    let barIndex = 0;\n    let barSteps = 0;\n    let loopSteps = 0;\n    let time: Candle[\"time\"];\n\n    const wasm = new WebAssembly.Instance(program.module, { series: {\n        read: (slot: number) => values[slot],\n        prior: (slot: number, offset: number, boolean: number, line: number) => {\n            if (offset === 0) return values[slot];\n            if (!Number.isNaN(offset) && (offset < 0 || offset > MAX_HISTORY)) {\n                throw new Error(`Line ${line}. History offsets must be between 0 and ${MAX_HISTORY}.`);\n            }\n            if (Number.isNaN(offset) || offset > counts[slot]) return boolean ? 0 : NaN;\n            return histories[slot][(counts[slot] - offset) % histories[slot].length];\n        },\n        input: (slot: number) => inputs[slot],\n        source: (slot: number) => values[FEED.indexOf(strings[inputs[slot]])],\n        chartInterval: () => intervalHandle,\n        symbol: (field: number, line: number) => {\n            if (!symbol) throw new Error(`Line ${line}. Symbol metadata requires a chart symbol.`);\n            return symbolFields[field];\n        },\n        lastBar: () => Number(barIndex === bars.length - 1),\n        requestContext: (symbolHandle: number, timeframeHandle: number, ignore: number, line: number) => {\n            const requestedSymbol = strings[symbolHandle];\n            if (requestedSymbol && requestedSymbol !== symbol) {\n                if (ignore) return 0;\n                throw new Error(`Line ${line}. request.security() only supports the chart symbol. Requested '${requestedSymbol}'.`);\n            }\n            const requestedTimeframe = strings[timeframeHandle];\n            if (requestedTimeframe && !checkedIntervals.has(timeframeHandle)) {\n                const requested = parseTimeframe(requestedTimeframe, line);\n                if (requested?.unit !== chartInterval?.unit || requested?.multiplier !== chartInterval?.multiplier) {\n                    throw new Error(`Line ${line}. request.security() only supports the chart timeframe. Requested '${requestedTimeframe}'.`);\n                }\n                checkedIntervals.set(timeframeHandle, true);\n            }\n            return 1;\n        },\n        alertCondition: (slot: number, condition: number) => {\n            if (condition) alerts[slot].times.push(time);\n        },\n        barColor: (handle: number, offset: number, count: number, display: number, line: number) => {\n            if (Math.abs(offset) > MAX_HISTORY) throw new Error(`Line ${line}. Bar color offsets are limited to ${MAX_HISTORY} bars.`);\n            const target = barIndex + offset;\n            if (display & DISPLAY_PANE && strings[handle] !== undefined && target >= 0 && target < bars.length\n                && (count === -1 || barIndex >= bars.length - count)) barColors.set(target, strings[handle]);\n        },\n        pivotLevels: (site: number, kind: number, anchor: number, developing: number, line: number) => {\n            const [open, high, low, close] = values;\n            const points = pivots(site, strings[kind], Boolean(anchor), Boolean(developing), { open, high, low, close }, line);\n            return arrays.create(points, line);\n        },\n        arrayBuiltin: (kind: number, packed: number, text: number, line: number) =>\n            normalized(arrays.execute(strings[kind], tuples[packed], Boolean(text), line), 0),\n        runtimeError: (message: number, line: number) => {\n            throw new Error(`Line ${line}. ${strings[message] || \"Pine runtime error.\"}`);\n        },\n        collectionBuiltin: (kind: number, packed: number, integral: number, line: number) => {\n            const name = strings[kind];\n            const args = tuples[packed];\n            return normalized(name.startsWith(\"map.\") ? maps(name, args, line) : matrices(name, args, Boolean(integral), line), 0);\n        },\n        scalar: (kind: number, packed: number, stringMask: number, boolMask: number, line: number) => {\n            const args = tuples[packed].map((value, i) => {\n                if (Number.isNaN(value)) return undefined;\n                if (stringMask & (1 << i)) return strings[value];\n                return boolMask & (1 << i) ? Boolean(value) : value;\n            });\n            const name = strings[kind];\n            const result = name.startsWith(\"calendar:\") ? calendar(name.slice(9), args, line) : scalarBuiltin(name, args, line);\n            if (typeof result === \"string\") {\n                if (result.length > 1024) throw new Error(`Line ${line}. A string exceeds the 1,024 character limit.`);\n                return intern(result);\n            }\n            return result === undefined ? NaN : normalized(Number(result), 0);\n        },\n        appendArgs: (first: number, second: number) => tuples.push([...tuples[first], ...tuples[second]]) - 1,\n        range: (high: number, low: number, previous: number, handle: number) =>\n            Number.isNaN(previous) ? (handle ? high - low : NaN)\n                : Math.max(high - low, Math.abs(high - previous), Math.abs(low - previous)),\n        technical: (kind: number, site: number, line: number, source: number, length: number,\n            a: number, b: number, c: number) => {\n            const result = technical(strings[kind], site, line, source, length, a, b, c, values[1], values[2], barIndex);\n            return typeof result === \"number\" ? normalized(result, 0) : tuples.push(result.map(value => normalized(value, 0))) - 1;\n        },\n        initialized: (slot: number) => Number(counts[slot] > 0 || written.has(slot)),\n        loopStep: (stride: number, ascending: number, line: number) => {\n            if (stride <= 0) throw new Error(`Line ${line}. For loop step must be positive.`);\n            return ascending ? stride : -stride;\n        },\n        loopTick: (line: number) => {\n            barSteps++;\n            loopSteps++;\n            if (barSteps > 1_000 || loopSteps > 4_000_000) {\n                throw new Error(`Line ${line}. The script exceeded its loop iteration limit.`);\n            }\n        },\n        write: (slot: number, value: number) => {\n            values[slot] = value;\n            written.add(slot);\n        },\n        tuple: (size: number, ...items: number[]) => tuples.push(items.slice(0, size)) - 1,\n        item: (tuple: number, index: number) => tuples[tuple][index],\n        plot: (slot: number, value: number, color: number, offset: number) => {\n            if (offset > MAX_HISTORY) throw new Error(`Forward plot offsets are limited to ${MAX_HISTORY} bars.`);\n            const index = barIndex + offset;\n            if (!Number.isFinite(value) || !Number.isSafeInteger(index) || index < 0) return;\n            const target = bars[index]?.time ?? (lastTime + (index - bars.length + 1) * spacing) as Candle[\"time\"];\n            const line = lines[slot];\n            const css = line.drawInPane ? strings[color] : \"transparent\";\n            line.data.push({ time: target, value, color: css ?? \"transparent\" });\n            plotIndices[slot].push(index);\n            plotOffsets[slot] = offset;\n            if (offset) (line.replaySourceTimes ??= []).push(chartTime(time));\n        },\n        fill: (slot: number, color: number) => {\n            fillColors[slot][barIndex] = strings[color];\n        },\n        number: normalized,\n        concat: (a: number, b: number, line: number) => {\n            if (Number.isNaN(a) || Number.isNaN(b)) return NaN;\n            const value = strings[a] + strings[b];\n            if (value.length > 1024) throw new Error(`Line ${line}. A string exceeds the 1,024 character limit.`);\n            return intern(value);\n        },\n        compare,\n        mod: (a: number, b: number) => {\n            const rem = a % b;\n            return rem && (rem > 0) !== (b > 0) ? rem + b : rem;\n        },\n        nz: (value: number, replacement: number) => Number.isNaN(value) ? replacement : value,\n        cross: (site: number, kind: number, a: number, b: number) => {\n            const prior = crosses.get(site);\n            crosses.set(site, [a, b]);\n            if (!prior) return 0;\n            const up = a > b && prior[0] <= prior[1];\n            const down = a < b && prior[0] >= prior[1];\n            return Number(kind === 0 ? up : kind === 1 ? down : up || down);\n        },\n    } });\n    const { step } = wasm.exports as { step: () => void };\n    for (const bar of bars) {\n        time = bar.time;\n        const { open, high, low, close } = bar;\n        values[0] = open;\n        values[1] = high;\n        values[2] = low;\n        values[3] = close;\n        values[4] = (high + low) / 2;\n        values[5] = (high + low + close) / 3;\n        values[6] = (open + high + low + close) / 4;\n        values[7] = bar.volume ?? NaN;\n        values[8] = barIndex;\n        values[9] = chartTime(time) * 1000;\n        values[10] = (high + low + 2 * close) / 4;\n        tuples.length = 0;\n        barSteps = 0;\n        written.clear();\n        for (let slot = 0; slot < FEED.length; slot++) written.add(slot);\n        step();\n        for (const slot of written) {\n            const history = histories[slot];\n            history[counts[slot] % history.length] = values[slot];\n            counts[slot]++;\n        }\n        barIndex++;\n    }\n    for (const [fillIndex, fill] of program.fills.entries()) {\n        if (!(fill.display & DISPLAY_PANE)) continue;\n        const first = lines[fill.first], second = lines[fill.second];\n        const firstIndices = plotIndices[fill.first], secondIndices = plotIndices[fill.second];\n        const sharedOffset = plotOffsets[fill.first] === plotOffsets[fill.second] ? plotOffsets[fill.first] : 0;\n        const points: IndicatorFillPoint[] = [];\n        let i = 0, j = 0, previous = -1;\n        while (i < firstIndices.length && j < secondIndices.length) {\n            const index = firstIndices[i];\n            if (index < secondIndices[j]) { i++; continue; }\n            if (index > secondIndices[j]) { j++; continue; }\n            const a = first.data[i], b = second.data[j];\n            const colorIndex = Math.min(index - sharedOffset, bars.length - 1);\n            const color = fillColors[fillIndex][colorIndex];\n            points.push({\n                time: a.time, first: a.value, second: b.value, color,\n                availableAt: Math.max(chartTime(a.time), first.replaySourceTimes?.[i] ?? -Infinity,\n                    second.replaySourceTimes?.[j] ?? -Infinity),\n                startsGap: !fill.fillGaps && index !== previous + 1,\n            });\n            previous = index;\n            i++;\n            j++;\n        }\n        if (points.length) (first.fills ??= []).push({ otherLineId: second.id, points });\n    }\n    return {\n        indicator: { id, title: program.title.trim() || \"Untitled script\", pane: !program.overlay },\n        parameters, plots, metrics: { runtime: \"wasm\", candles: bars.length },\n        alerts, barColors: [...barColors].sort(([a], [b]) => a - b).map(([index, color]) => ({ time: bars[index].time, color })),\n    };\n}\n","import type { IndicatorCatalogItem } from \"../charts/IndicatorList\";\nimport type { WorkspaceStore } from \"../charts/workspace/WorkspaceState\";\nimport { createId } from \"../charts/workspace/ids\";\nimport { compileScript, type CompiledScript, type ScriptSource } from \"./wasm\";\n\nconst KEY = \"scripts\";\nconst MAX_SCRIPTS = 40;\nexport const isScriptIndicator = (id: string): boolean => id.startsWith(\"script:\");\nexport const isScriptPreview = (id: string): boolean => id.startsWith(\"script:preview:\");\nexport type SavedScript = ScriptSource & IndicatorCatalogItem;\n\nfunction isSavedScript(value: unknown): value is SavedScript {\n    const script = value as Partial<SavedScript> | null;\n    return !!script && typeof script.id === \"string\" && isScriptIndicator(script.id) && !isScriptPreview(script.id)\n        && typeof script.title === \"string\" && script.title.length > 0 && script.title.length <= 120\n        && (script.dialect === \"pine\" || script.dialect === \"zero\") && typeof script.source === \"string\"\n        && script.source.length <= 16_000 && Number.isInteger(script.parameterCount) && script.parameterCount! >= 0;\n}\n\nexport class ScriptLibrary {\n    private scripts: SavedScript[] = [];\n    private readonly compiled = new Map<string, Promise<CompiledScript>>();\n\n    constructor(\n        private readonly store: WorkspaceStore,\n        private readonly compileUrl: string,\n        private readonly csrf: string,\n    ) { this.refresh(); }\n\n    public catalog(): readonly SavedScript[] { return this.scripts; }\n\n    public refresh(): void {\n        const raw = this.store.read<unknown>(KEY, []);\n        const stored = Array.isArray(raw) ? raw.filter(isSavedScript).slice(0, MAX_SCRIPTS) : [];\n        const next = new Map(stored.map(script => [script.id, script]));\n        for (const script of this.scripts) {\n            const current = next.get(script.id);\n            if (!current || current.source !== script.source || current.dialect !== script.dialect) this.compiled.delete(script.id);\n        }\n        this.scripts = [...next.values()];\n    }\n\n    public compile(script: ScriptSource): Promise<CompiledScript> {\n        const { source, dialect } = script;\n        return compileScript(this.compileUrl, this.csrf, { source, dialect });\n    }\n\n    public add(script: ScriptSource, program: CompiledScript): SavedScript {\n        this.refresh();\n        const existing = this.scripts.find(saved => saved.dialect === script.dialect && saved.source === script.source);\n        if (existing) {\n            this.compiled.set(existing.id, Promise.resolve(program));\n            return existing;\n        }\n        if (this.scripts.length >= MAX_SCRIPTS) throw new Error(`The script picker holds up to ${MAX_SCRIPTS} saved scripts.`);\n        const saved = {\n            ...script, id: `script:${createId()}`,\n            title: program.title.trim().slice(0, 120) || \"Untitled script\", parameterCount: program.inputs.length,\n        };\n        const next = [...this.scripts, saved];\n        if (!this.store.write(KEY, next)) throw new Error(\"Could not save this indicator in browser storage.\");\n        this.scripts = next;\n        this.compiled.set(saved.id, Promise.resolve(program));\n        return saved;\n    }\n\n    public setPreview(id: string, program: CompiledScript): void {\n        this.compiled.set(id, Promise.resolve(program));\n    }\n\n    public async load(id: string): Promise<CompiledScript> {\n        const cached = this.compiled.get(id);\n        if (cached) return cached;\n        const saved = this.scripts.find(item => item.id === id);\n        if (!saved) throw new Error(\"This script is missing from My scripts in this browser.\");\n        const pending = this.compile(saved);\n        this.compiled.set(id, pending);\n        try { return await pending; }\n        catch (error) {\n            if (this.compiled.get(id) === pending) this.compiled.delete(id);\n            throw error;\n        }\n    }\n}\n","import { toolIcon } from \"../charts/workspace/ToolIcons\";\nimport type { CompiledScript, Dialect, ScriptSource } from \"./wasm\";\nimport type { ScriptLibrary } from \"./ScriptLibrary\";\nimport \"./zero.css\";\n\nconst examples: Record<Dialect, string> = {\n    pine: `//@version=6\nindicator(\"Moving averages\", overlay=true)\n\nlength = input.int(20, \"EMA length\", minval=1, maxval=200)\nplot(ta.ema(close, length), \"EMA\", color=color.orange, linewidth=2)\nplot(ta.sma(close, 50), \"SMA 50\", color=color.blue, linewidth=2)`,\n    zero: `indicator(\"Moving averages\", overlay=true);\n\nlet length: int = input.int(20, \"EMA length\", minval=1, maxval=200);\nplot(ta.ema(close, length), \"EMA\", color=color.orange, linewidth=2);\nplot(ta.sma(close, 50), \"SMA 50\", color=color.blue, linewidth=2);`,\n};\n\nexport class ScriptDock {\n    private readonly form = document.querySelector<HTMLFormElement>(\"#zero-form\")!;\n    private readonly editor = document.querySelector<HTMLTextAreaElement>(\"#zero-source\")!;\n    private readonly language = document.querySelector<HTMLSelectElement>(\"#zero-dialect\")!;\n    private readonly saved = document.querySelector<HTMLSelectElement>(\"#zero-saved\")!;\n    private readonly status = document.querySelector<HTMLElement>(\"#zero-status\")!;\n    private readonly target = document.querySelector<HTMLElement>(\"#zero-target\")!;\n    private readonly dock = document.querySelector<HTMLElement>(\"#zero-dock\")!;\n    private readonly toggle = document.querySelector<HTMLButtonElement>(\"#zero-toggle\")!;\n    private readonly closeButton = document.querySelector<HTMLButtonElement>(\"#zero-close\")!;\n    private readonly runButton = document.querySelector<HTMLButtonElement>(\"#zero-run\")!;\n    private readonly addButton = document.querySelector<HTMLButtonElement>(\"#zero-add\")!;\n    private readonly drafts = { ...examples };\n    private dialect: Dialect = \"pine\";\n    private lastCompiled?: { script: ScriptSource; program: CompiledScript };\n\n    constructor(\n        private readonly library: ScriptLibrary,\n        private readonly previewTarget: () => (program: CompiledScript) => Promise<void>,\n        private readonly refreshPickers: () => void,\n        private readonly resize: () => void,\n    ) {\n        this.editor.value = this.drafts.pine;\n        this.toggle.innerHTML = toolIcon(\"code\") + \"Zero Lab\";\n        this.closeButton.innerHTML = toolIcon(\"minus\");\n        this.toggle.addEventListener(\"click\", () => this.setOpen(this.dock.hidden === true));\n        this.closeButton.addEventListener(\"click\", () => {\n            this.setOpen(false);\n            this.toggle.focus();\n        });\n        this.language.addEventListener(\"change\", () => this.setLanguage(this.language.value as Dialect));\n        this.saved.addEventListener(\"change\", () => {\n            const script = this.library.catalog().find(item => item.id === this.saved.value);\n            this.saved.value = \"\";\n            if (!script) return;\n            this.setLanguage(script.dialect);\n            this.editor.value = script.source;\n            this.editor.focus();\n            this.message(`Opened ${script.title}.`);\n        });\n        this.editor.addEventListener(\"keydown\", event => {\n            if (event.key === \"Enter\" && (event.metaKey || event.ctrlKey) && !this.runButton.disabled) {\n                event.preventDefault();\n                this.form.requestSubmit(this.runButton);\n            }\n        });\n        this.form.addEventListener(\"submit\", event => {\n            event.preventDefault();\n            if (!this.runButton.disabled) void this.submit(event.submitter === this.addButton);\n        });\n        this.refreshCatalog();\n        this.mountResizeHandle();\n    }\n\n    public setOpen(open: boolean): void {\n        if (this.dock.hidden === !open) return;\n        this.dock.hidden = !open;\n        this.toggle.setAttribute(\"aria-expanded\", String(open));\n        this.resize();\n    }\n\n    public setTarget(target: string): void { this.target.textContent = target; }\n\n    public refreshCatalog(): void {\n        this.saved.replaceChildren(new Option(\"Open saved script…\", \"\"));\n        for (const script of this.library.catalog()) {\n            this.saved.add(new Option(`${script.title} · ${script.dialect === \"pine\" ? \"Pine\" : \"Zero\"}`, script.id));\n        }\n        this.saved.hidden = this.saved.options.length <= 1;\n    }\n\n    private setLanguage(dialect: Dialect): void {\n        this.drafts[this.dialect] = this.editor.value;\n        this.dialect = dialect;\n        this.language.value = dialect;\n        this.editor.value = this.drafts[dialect];\n    }\n\n    private message(message: string, error = false): void {\n        this.status.textContent = message;\n        this.status.classList.toggle(\"is-error\", error);\n    }\n\n    private async submit(add: boolean): Promise<void> {\n        const script = { dialect: this.dialect, source: this.editor.value };\n        this.runButton.disabled = this.addButton.disabled = this.saved.disabled = this.language.disabled = this.editor.readOnly = true;\n        this.message(\"Compiling WebAssembly…\");\n        try {\n            const run = add ? undefined : this.previewTarget();\n            const last = this.lastCompiled;\n            const program = last?.script.source === script.source && last.script.dialect === script.dialect\n                ? last.program : await this.library.compile(script);\n            this.lastCompiled = { script, program };\n            if (run) {\n                await run(program);\n                this.message(\"Preview plotted on the active chart.\");\n            } else {\n                const saved = this.library.add(script, program);\n                this.refreshCatalog();\n                this.refreshPickers();\n                this.message(`“${saved.title}” is in Indicators → My scripts.`);\n            }\n        } catch (error) {\n            this.message(error instanceof Error ? error.message : \"Could not compile the script.\", true);\n        } finally {\n            this.runButton.disabled = this.addButton.disabled = this.saved.disabled = this.language.disabled = this.editor.readOnly = false;\n        }\n    }\n\n    private mountResizeHandle(): void {\n        const handle = document.querySelector<HTMLElement>(\"#zero-resize\")!;\n        const resize = (height: number) => {\n            const max = Math.floor(window.innerHeight * 0.55);\n            this.dock.style.setProperty(\"--zero-height\", `${Math.min(max, Math.max(125, height))}px`);\n            this.resize();\n        };\n        handle.addEventListener(\"keydown\", event => {\n            if (event.key !== \"ArrowUp\" && event.key !== \"ArrowDown\") return;\n            event.preventDefault();\n            resize(this.dock.offsetHeight + (event.key === \"ArrowUp\" ? 30 : -30));\n        });\n        let drag: { pointer: number; y: number; height: number } | undefined;\n        handle.addEventListener(\"pointerdown\", event => {\n            if (!event.isPrimary || event.button !== 0) return;\n            handle.setPointerCapture(event.pointerId);\n            drag = { pointer: event.pointerId, y: event.clientY, height: this.dock.offsetHeight };\n        });\n        handle.addEventListener(\"pointermove\", event => {\n            if (drag?.pointer === event.pointerId) resize(drag.height + drag.y - event.clientY);\n        });\n        handle.addEventListener(\"lostpointercapture\", () => { drag = undefined; });\n    }\n}\n","import { CHART_PALETTES, type ChartPalette, type ChartAppearance, type AppearanceOverrides } from \"./ChartAppearance.ts\";\nimport { toolIcon } from \"./workspace/ToolIcons\";\n\n/** Lazily opened, live preview. Native dialog gives focus trapping and Escape, without browser prompts. */\nexport class ChartAppearancePanel {\n    private dialog: HTMLDialogElement | null = null;\n    constructor(private readonly getDefaults: () => ChartAppearance, private readonly getOverrides: () => AppearanceOverrides,\n        private readonly onChange: (value: AppearanceOverrides) => void,\n        private readonly getPalette: () => ChartPalette | undefined,\n        private readonly onSelectPalette: (palette: ChartPalette) => void) {}\n    public open(symbol: string): void {\n        if (this.dialog?.open) return;\n        this.dialog?.remove();\n        const dialog = document.createElement(\"dialog\"); this.dialog = dialog;\n        dialog.className = \"workspace-dialog appearance-dialog\";\n        dialog.setAttribute(\"aria-label\", `Chart appearance · ${symbol}`);\n        const header = document.createElement(\"header\"); header.className = \"template-header\";\n        const copy = document.createElement(\"div\");\n        const eyebrow = document.createElement(\"span\"); eyebrow.className = \"eyebrow\"; eyebrow.textContent = \"CHART SETTINGS\";\n        const title = document.createElement(\"h2\"); title.textContent = symbol;\n        const subtitle = document.createElement(\"p\"); subtitle.textContent = \"Choose a theme for the entire workspace. The controls below adjust this chart.\";\n        copy.append(eyebrow, title); header.append(copy);\n        const close = document.createElement(\"button\"); close.type = \"button\"; close.className = \"workspace-button\";\n        close.textContent = \"Done\"; close.addEventListener(\"click\", () => dialog.close()); header.append(close);\n        dialog.append(header, subtitle);\n        let overrides = { ...this.getOverrides() };\n        const fields = new Map<keyof ChartAppearance, HTMLInputElement | HTMLSelectElement>();\n        const paletteButtons: HTMLButtonElement[] = [];\n        const resolved = () => ({ ...this.getDefaults(), ...overrides });\n        const syncControls = () => {\n            const appearance = resolved();\n            for (const [key, input] of fields) {\n                if (input instanceof HTMLInputElement && input.type === \"checkbox\") input.checked = Boolean(appearance[key]);\n                else input.value = String(appearance[key]);\n            }\n            CHART_PALETTES.forEach(({ id }, i) => {\n                const selected = this.getPalette()?.id === id;\n                paletteButtons[i]?.setAttribute(\"aria-pressed\", String(selected));\n            });\n        };\n        const apply = (next: AppearanceOverrides) => {\n            overrides = next;\n            this.onChange(overrides);\n            syncControls();\n        };\n        const section = (title: string) => { const group = document.createElement(\"fieldset\"); const legend = document.createElement(\"legend\"); legend.textContent = title; group.append(legend); dialog.append(group); return group; };\n        const field = (parent: HTMLElement, key: keyof ChartAppearance, name: string, choices?: string[]) => {\n            const label = document.createElement(\"label\"); label.className = \"appearance-field\";\n            const span = document.createElement(\"span\"); span.textContent = name;\n            const input = choices ? document.createElement(\"select\") : document.createElement(\"input\");\n            input.setAttribute(\"aria-label\", name); input.dataset.appearance = key;\n            if (input instanceof HTMLSelectElement) {\n                for (const value of choices!) input.add(new Option(value[0].toUpperCase() + value.slice(1), value));\n            } else input.type = typeof this.getDefaults()[key] === \"boolean\" ? \"checkbox\" : \"color\";\n            fields.set(key, input);\n            input.addEventListener(\"input\", () => {\n                const value = input instanceof HTMLInputElement && input.type === \"checkbox\" ? input.checked : input.value;\n                apply({ ...overrides, [key]: value });\n            });\n            label.append(span, input); parent.append(label);\n        };\n        const palettes = section(\"Workspace themes\");\n        palettes.classList.add(\"appearance-palettes\");\n        for (const palette of CHART_PALETTES) {\n            const { name, colors, shell: [, surface, , border, accent] } = palette;\n            const button = document.createElement(\"button\");\n            button.type = \"button\";\n            button.className = \"appearance-palette\";\n            const preview = document.createElement(\"span\");\n            preview.className = \"appearance-palette-preview\";\n            preview.setAttribute(\"aria-hidden\", \"true\");\n            preview.style.background = `linear-gradient(90deg, ${surface} 0 16%, transparent 16% 84%, ${surface} 84%), linear-gradient(${colors.background}, ${colors.backgroundBottom})`;\n            preview.style.borderColor = border;\n            preview.style.boxShadow = `inset 0 3px 0 ${accent}`;\n            preview.style.setProperty(\"--candle-up\", colors.upColor);\n            preview.style.setProperty(\"--candle-down\", colors.downColor);\n            const caption = document.createElement(\"span\");\n            caption.textContent = name;\n            button.append(preview, caption);\n            button.addEventListener(\"click\", () => {\n                this.onSelectPalette(palette);\n                overrides = { ...this.getOverrides() };\n                syncControls();\n            });\n            paletteButtons.push(button);\n            palettes.append(button);\n        }\n        const canvas = section(\"Canvas\");\n        field(canvas, \"background\", \"Background color\"); field(canvas, \"gradient\", \"Gradient background\");\n        field(canvas, \"backgroundBottom\", \"Gradient bottom color\"); field(canvas, \"textColor\", \"Axis text color\");\n        const grid = section(\"Grid & crosshair\");\n        field(grid, \"verticalGrid\", \"Vertical grid lines\"); field(grid, \"horizontalGrid\", \"Horizontal grid lines\");\n        field(grid, \"gridColor\", \"Grid color\"); field(grid, \"gridStyle\", \"Grid style\", [\"solid\", \"dotted\", \"dashed\"]);\n        field(grid, \"crosshair\", \"Show crosshair\"); field(grid, \"crosshairColor\", \"Crosshair color\");\n        field(grid, \"crosshairMode\", \"Crosshair mode\", [\"normal\", \"magnet\"]);\n        const candles = section(\"Candles\");\n        field(candles, \"upColor\", \"Bullish candle color\"); field(candles, \"downColor\", \"Bearish candle color\");\n        field(candles, \"wicks\", \"Show candle wicks\"); field(candles, \"candleBorders\", \"Show candle borders\");\n        field(candles, \"priceLine\", \"Last price line\"); field(candles, \"lastValue\", \"Last value label\");\n        const scales = section(\"Scales\");\n        field(scales, \"axisBorders\", \"Axis borders\"); field(scales, \"timeLabels\", \"Show intraday time\"); field(scales, \"seconds\", \"Show seconds\");\n        const footer = document.createElement(\"footer\"); footer.className = \"appearance-footer\";\n        const reset = document.createElement(\"button\"); reset.type = \"button\"; reset.className = \"workspace-button\"; reset.innerHTML = toolIcon(\"undo\") + \"Reset to theme\";\n        reset.addEventListener(\"click\", () => apply({}));\n        const note = document.createElement(\"small\"); note.textContent = \"Saved with your workspace and templates.\";\n        footer.append(reset, note); dialog.append(footer);\n        dialog.addEventListener(\"click\", e => { if (e.target === dialog) { const b = dialog.getBoundingClientRect(); if (e.clientX < b.left || e.clientX > b.right || e.clientY < b.top || e.clientY > b.bottom) dialog.close(); } });\n        syncControls();\n        document.body.append(dialog); dialog.showModal();\n    }\n}\n","import type { HorzScaleOptions } from \"lightweight-charts\";\n\n/** Native rendering LOD: combine bars only below the screen's detail limit.\n * Original series data, logical indices, exports and indicator inputs stay intact.\n * Build dense caches on demand; avoid the library's startup precompute overhead.\n */\nexport const DENSE_CHART_OPTIONS: Partial<HorzScaleOptions> = {\n    enableConflation: true,\n    conflationThresholdFactor: 1,\n    precomputeConflationOnInit: false,\n};\n","export const WATCHLIST_ASSETS = [\n    { symbol: \"EURUSD\", name: \"Euro / US Dollar\", market: \"Forex\", base: 1.0852, decimals: 5, color: \"#6366f1\", mark: \"€\" },\n    { symbol: \"GBPUSD\", name: \"British Pound / US Dollar\", market: \"Forex\", base: 1.2846, decimals: 5, color: \"#8b5cf6\", mark: \"£\" },\n    { symbol: \"USDJPY\", name: \"US Dollar / Japanese Yen\", market: \"Forex\", base: 149.72, decimals: 3, color: \"#ec4899\", mark: \"¥\" },\n    { symbol: \"AUDUSD\", name: \"Australian Dollar / US Dollar\", market: \"Forex\", base: .6624, decimals: 5, color: \"#14b8a6\", mark: \"A$\" },\n    { symbol: \"BTCUSD\", name: \"Bitcoin\", market: \"Crypto\", base: 68420, decimals: 2, color: \"#f59e0b\", mark: \"₿\" },\n    { symbol: \"ETHUSD\", name: \"Ethereum\", market: \"Crypto\", base: 3480, decimals: 2, color: \"#818cf8\", mark: \"Ξ\" },\n    { symbol: \"AAPL\", name: \"Apple\", market: \"Stocks\", base: 224.86, decimals: 2, color: \"#64748b\", mark: \"A\" },\n    { symbol: \"MSFT\", name: \"Microsoft\", market: \"Stocks\", base: 426.72, decimals: 2, color: \"#0ea5e9\", mark: \"M\" },\n    { symbol: \"NVDA\", name: \"NVIDIA\", market: \"Stocks\", base: 138.45, decimals: 2, color: \"#84cc16\", mark: \"N\" },\n    { symbol: \"TSLA\", name: \"Tesla\", market: \"Stocks\", base: 248.62, decimals: 2, color: \"#ef4444\", mark: \"T\" },\n    { symbol: \"AMZN\", name: \"Amazon\", market: \"Stocks\", base: 196.52, decimals: 2, color: \"#f97316\", mark: \"a\" },\n] as const;\nexport type WatchlistAsset = typeof WATCHLIST_ASSETS[number];\nexport interface WatchlistItem { asset: WatchlistAsset; symbol: string; price: number; previousClose: number; change: number; changePct: number; history: number[]; }\nconst round = (value: number, decimals: number) => Number(value.toFixed(decimals));\nexport function createWatchlist(random = Math.random): WatchlistItem[] {\n    return WATCHLIST_ASSETS.map(asset => {\n        let value: number = asset.base;\n        const history = Array.from({ length: 36 }, () => { value *= 1 + (random() - .49) * .003; return round(value, asset.decimals); });\n        const price = history[history.length - 1], previousClose = asset.base;\n        return { asset, symbol: asset.symbol, price, previousClose, change: price - previousClose, changePct: (price / previousClose - 1) * 100,\n            history };\n    });\n}\nexport function advanceQuote(item: WatchlistItem, random = Math.random): void {\n    item.price = round(Math.max(item.previousClose * .1, item.price * (1 + (random() - .5) * .0012)), item.asset.decimals);\n    item.change = item.price - item.previousClose; item.changePct = item.change / item.previousClose * 100;\n    item.history.push(item.price); item.history.shift();\n}\nexport function sparklinePath(history: readonly number[], width = 72, height = 24): string {\n    if (!history.length) return \"\";\n    const min = Math.min(...history), span = Math.max(...history) - min;\n    return history.map((value, i) => `${i ? \"L\" : \"M\"}${(i * width / Math.max(1, history.length - 1)).toFixed(1)},${(span ? height - 2 - (value - min) / span * (height - 4) : height / 2).toFixed(1)}`).join(\" \");\n}\n","import { advanceQuote, createWatchlist, sparklinePath, WATCHLIST_ASSETS, type WatchlistItem } from \"./WatchlistModel.ts\";\nimport { toolIcon } from \"./workspace/ToolIcons\";\nexport type { WatchlistItem } from \"./WatchlistModel.ts\";\nexport interface WatchlistOptions { container: HTMLElement; onSelectSymbol: (symbol: string) => void; }\n\nexport class Watchlist {\n    private readonly items = createWatchlist();\n    private readonly rows = new Map<string, HTMLElement>();\n    private readonly favorites = new Set<string>();\n    private market = \"All\";\n    private search = \"\";\n    private sort = \"default\";\n    private paused = false;\n    private mounted = false;\n    private list!: HTMLElement;\n    private empty!: HTMLElement;\n    private feedStatus!: HTMLElement;\n    constructor(private readonly options: WatchlistOptions) {}\n    public mount(): void {\n        if (this.mounted) return; this.mounted = true;\n        try { const saved: unknown = JSON.parse(localStorage.getItem(\"chartix.watchlist.favorites\") ?? \"[]\"); if (Array.isArray(saved)) for (const value of saved) if (typeof value === \"string\" && WATCHLIST_ASSETS.some(a => a.symbol === value)) this.favorites.add(value); } catch { /* Session-only preferences when storage is unavailable. */ }\n        const root = this.options.container; root.replaceChildren(); root.classList.add(\"market-watchlist\");\n        const tools = document.createElement(\"div\"); tools.className = \"watchlist-tools\";\n        const search = document.createElement(\"input\"); search.type = \"search\"; search.placeholder = \"Search symbols\"; search.setAttribute(\"aria-label\", \"Search watchlist\");\n        search.addEventListener(\"input\", () => { this.search = search.value.toLowerCase().trim(); this.renderList(); });\n        const pause = document.createElement(\"button\"); pause.type = \"button\"; pause.className = \"watchlist-pause\"; pause.innerHTML = toolIcon(\"pause\"); pause.setAttribute(\"aria-label\", \"Pause simulated quotes\"); pause.setAttribute(\"aria-pressed\", \"false\");\n        pause.addEventListener(\"click\", () => { this.paused = !this.paused; pause.innerHTML = toolIcon(this.paused ? \"play\" : \"pause\"); pause.setAttribute(\"aria-label\", this.paused ? \"Resume simulated quotes\" : \"Pause simulated quotes\"); pause.setAttribute(\"aria-pressed\", String(this.paused)); this.updateStatus(); });\n        const searchBox = document.createElement(\"label\");\n        searchBox.className = \"watchlist-search\";\n        searchBox.innerHTML = toolIcon(\"search\");\n        searchBox.append(search);\n        tools.append(searchBox, pause); root.append(tools);\n        const tabs = document.createElement(\"div\"); tabs.className = \"watchlist-tabs\"; tabs.setAttribute(\"role\", \"group\"); tabs.setAttribute(\"aria-label\", \"Watchlist markets\");\n        for (const name of [\"All\", \"Forex\", \"Crypto\", \"Stocks\", \"Starred\"]) {\n            const tab = document.createElement(\"button\"); tab.type = \"button\"; if (name === \"Starred\") tab.innerHTML = toolIcon(\"star\"); else tab.textContent = name; tab.setAttribute(\"aria-label\", name === \"Starred\" ? \"Starred symbols\" : name); tab.setAttribute(\"aria-pressed\", String(this.market === name));\n            tab.addEventListener(\"click\", () => { this.market = name; for (const t of tabs.querySelectorAll(\"button\")) t.setAttribute(\"aria-pressed\", String(t === tab)); this.renderList(); }); tabs.append(tab);\n        }\n        root.append(tabs);\n        const columns = document.createElement(\"div\"); columns.className = \"watchlist-columns\";\n        const symbol = document.createElement(\"span\"); symbol.textContent = \"SYMBOL / TREND\";\n        const sort = document.createElement(\"select\"); sort.setAttribute(\"aria-label\", \"Sort watchlist\");\n        for (const [value, name] of [[\"default\", \"Price / change\"], [\"symbol\", \"Symbol A–Z\"], [\"gainers\", \"Top gainers\"], [\"losers\", \"Top losers\"], [\"price\", \"Highest price\"]]) sort.add(new Option(name, value));\n        sort.addEventListener(\"change\", () => { this.sort = sort.value; this.renderList(); }); columns.append(symbol, sort); root.append(columns);\n        this.list = document.createElement(\"div\"); this.list.className = \"watchlist-quotes\"; this.list.setAttribute(\"aria-label\", \"Simulated quotes\"); root.append(this.list);\n        this.empty = document.createElement(\"p\"); this.empty.className = \"watchlist-empty\"; this.empty.textContent = \"No matching symbols.\"; root.append(this.empty);\n        for (const item of this.items) this.rows.set(item.symbol, this.createRow(item));\n        this.feedStatus = document.createElement(\"div\"); this.feedStatus.className = \"watchlist-feed-status\"; root.append(this.feedStatus);\n        this.renderList(); this.updateStatus();\n        window.setInterval(() => this.tick(), 2000);\n        document.addEventListener(\"visibilitychange\", () => this.updateStatus());\n    }\n    private createRow(item: WatchlistItem): HTMLElement {\n        const row = document.createElement(\"div\"); row.className = \"watchlist-row\";\n        const quote = document.createElement(\"button\"); quote.type = \"button\"; quote.className = \"watchlist-quote\"; quote.dataset.symbol = item.symbol;\n        quote.title = `Open ${item.symbol} in the active chart`;\n        quote.setAttribute(\"aria-label\", quote.title);\n        quote.innerHTML = `<span class=\"asset-mark\" style=\"--asset-color:${item.asset.color}\">${item.asset.mark}</span>\n            <span class=\"quote-symbol\"><strong>${item.symbol}</strong><small>${item.asset.market}</small></span>\n            <svg viewBox=\"0 0 72 24\" class=\"quote-spark\" aria-hidden=\"true\"><path fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"/></svg>\n            <span class=\"quote-values\"><strong data-quote=\"price\"></strong><small data-quote=\"change\"></small></span>`;\n        quote.addEventListener(\"click\", () => this.options.onSelectSymbol(item.symbol));\n        const star = document.createElement(\"button\"); star.type = \"button\"; star.className = \"watchlist-star\"; star.innerHTML = toolIcon(\"star\");\n        star.addEventListener(\"click\", () => {\n            if (this.favorites.has(item.symbol)) this.favorites.delete(item.symbol); else this.favorites.add(item.symbol);\n            try { localStorage.setItem(\"chartix.watchlist.favorites\", JSON.stringify([...this.favorites])); } catch { /* Keep session favorites usable. */ }\n            this.updateRow(item, row); if (this.market === \"Starred\") this.renderList();\n        });\n        row.append(quote, star); this.updateRow(item, row); return row;\n    }\n    private updateRow(item: WatchlistItem, row = this.rows.get(item.symbol)!): void {\n        row.querySelector(\"[data-quote=price]\")!.textContent = this.price(item, item.price);\n        row.querySelector(\"[data-quote=change]\")!.textContent = `${item.changePct >= 0 ? \"+\" : \"\"}${item.changePct.toFixed(2)}%`;\n        row.dataset.direction = item.change >= 0 ? \"up\" : \"down\";\n        row.querySelector(\"path\")!.setAttribute(\"d\", sparklinePath(item.history));\n        const starred = this.favorites.has(item.symbol), star = row.querySelector(\".watchlist-star\")!;\n        star.setAttribute(\"aria-pressed\", String(starred)); star.setAttribute(\"aria-label\", `${starred ? \"Unstar\" : \"Star\"} ${item.symbol}`);\n    }\n    private renderList(): void {\n        const items = this.items.filter(q => (this.market === \"All\" || (this.market === \"Starred\" ? this.favorites.has(q.symbol) : q.asset.market === this.market)) && `${q.symbol} ${q.asset.name}`.toLowerCase().includes(this.search));\n        if (this.sort === \"symbol\") items.sort((a, b) => a.symbol.localeCompare(b.symbol));\n        if (this.sort === \"gainers\") items.sort((a, b) => b.changePct - a.changePct);\n        if (this.sort === \"losers\") items.sort((a, b) => a.changePct - b.changePct);\n        if (this.sort === \"price\") items.sort((a, b) => b.price - a.price);\n        for (const item of items) this.updateRow(item);\n        const rows = items.map(item => this.rows.get(item.symbol)!);\n        if (rows.length !== this.list.children.length || rows.some((row, i) => row !== this.list.children[i])) {\n            const focused = this.list.contains(document.activeElement) ? document.activeElement as HTMLElement : null;\n            this.list.replaceChildren(...rows);\n            if (focused?.isConnected) focused.focus({ preventScroll: true });\n        }\n        this.empty.hidden = !!items.length;\n    }\n    private price(item: WatchlistItem, value: number): string { return value.toLocaleString(\"en-US\", { minimumFractionDigits: item.asset.decimals, maximumFractionDigits: item.asset.decimals }); }\n    private updateStatus(): void { if (this.feedStatus) { this.feedStatus.textContent = this.paused ? \"● Simulation paused\" : document.hidden ? \"● Paused while tab is hidden\" : \"● Simulated feed · updates every 2s\"; this.feedStatus.dataset.paused = String(this.paused || document.hidden); } }\n    private tick(): void {\n        if (this.paused || document.hidden || this.options.container.closest(\"[hidden]\")) return;\n        for (const item of this.items) advanceQuote(item);\n        if ([\"gainers\", \"losers\", \"price\"].includes(this.sort)) this.renderList();\n        else for (const item of this.items) if (this.rows.get(item.symbol)?.isConnected) this.updateRow(item);\n    }\n}\n","import { toolIcon, type ToolIcon } from \"./workspace/ToolIcons\";\n\nexport interface ContextMenuOptions {\n    chartContainer: HTMLElement;\n    focusTarget?: HTMLElement;\n    resetZoom: () => void;\n    toggleTheme: () => void;\n    exportCsv: () => void;\n    openSettings?: () => void;\n    showRsi?: () => void;\n    removeAllIndicators?: () => void;\n    removeAllObjects?: () => void;\n}\n\ninterface MenuItem { text: string; icon: ToolIcon; action: () => void; destructive?: boolean; }\n\n/** One menu per chart; actions always belong to the chart that was clicked. */\nexport class ContextMenu {\n    private readonly chartContainer: HTMLElement;\n    private readonly menu = document.createElement(\"div\");\n    private rows: HTMLButtonElement[] = [];\n\n    constructor(private readonly options: ContextMenuOptions) {\n        this.chartContainer = options.chartContainer;\n    }\n\n    public mount(): void { this.createMenu(); this.bindEvents(); }\n\n    private createMenu(): void {\n        this.menu.className = \"chartix-context-menu\";\n        this.menu.setAttribute(\"role\", \"menu\");\n        this.menu.setAttribute(\"aria-label\", \"Chart actions\");\n        this.menu.hidden = true;\n        const items: MenuItem[] = [\n            { text: \"Reset Zoom\", icon: \"fit\", action: this.options.resetZoom },\n            { text: \"Toggle Theme\", icon: \"sun\", action: this.options.toggleTheme },\n            { text: \"Show RSI\", icon: \"activity\", action: () => {\n                if (this.options.showRsi) this.options.showRsi();\n                else document.getElementById(\"rsiChart\")?.classList.toggle(\"hidden\");\n            } },\n            { text: \"Export as CSV\", icon: \"download\", action: this.options.exportCsv },\n        ];\n        if (this.options.openSettings) items.unshift({ text: \"Chart settings…\", icon: \"settings\", action: this.options.openSettings });\n        if (this.options.removeAllIndicators) items.push({ text: \"Remove all indicators\", icon: \"clear\", destructive: true, action: this.options.removeAllIndicators });\n        if (this.options.removeAllObjects) items.push({ text: \"Remove all objects\", icon: \"delete\", destructive: true, action: this.options.removeAllObjects });\n        for (const item of items) {\n            const row = document.createElement(\"button\");\n            row.type = \"button\";\n            row.className = item.destructive ? \"context-menu-action is-destructive\" : \"context-menu-action\";\n            row.innerHTML = toolIcon(item.icon);\n            row.append(document.createTextNode(item.text));\n            row.setAttribute(\"role\", \"menuitem\");\n            row.addEventListener(\"click\", event => { event.stopPropagation(); this.hide(); item.action(); });\n            this.menu.append(row); this.rows.push(row);\n        }\n        document.body.append(this.menu);\n    }\n    private show(x: number, y: number): void {\n        this.menu.hidden = false;\n        const bounds = this.menu.getBoundingClientRect();\n        this.menu.style.left = `${Math.max(8, Math.min(x, window.innerWidth - bounds.width - 8))}px`;\n        this.menu.style.top = `${Math.max(8, Math.min(y, window.innerHeight - bounds.height - 8))}px`;\n        this.rows[0]?.focus({ preventScroll: true });\n    }\n    private bindEvents(): void {\n        this.chartContainer.addEventListener(\"contextmenu\", event => {\n            event.preventDefault(); event.stopPropagation(); this.show(event.clientX, event.clientY);\n        });\n        this.chartContainer.addEventListener(\"keydown\", event => {\n            if (event.key === \"ContextMenu\" || (event.shiftKey && event.key === \"F10\")) {\n                event.preventDefault();\n                const bounds = this.chartContainer.getBoundingClientRect();\n                this.show(bounds.left + bounds.width / 2, bounds.top + bounds.height / 2);\n            }\n        });\n        this.menu.addEventListener(\"keydown\", event => {\n            if (event.key === \"Escape\") { event.preventDefault(); this.hide(); (this.options.focusTarget ?? this.chartContainer).focus({ preventScroll: true }); }\n            if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n                event.preventDefault();\n                const index = this.rows.indexOf(document.activeElement as HTMLButtonElement);\n                this.rows[(index + (event.key === \"ArrowDown\" ? 1 : -1) + this.rows.length) % this.rows.length].focus();\n            }\n        });\n        document.addEventListener(\"pointerdown\", event => { if (!this.menu.contains(event.target as Node)) this.hide(); });\n        document.addEventListener(\"contextmenu\", event => { if (!this.chartContainer.contains(event.target as Node)) this.hide(); }, true);\n    }\n    private hide(): void { this.menu.hidden = true; }\n}\n","import { toolIcon } from \"./workspace/ToolIcons\";\nimport {\n    LineStyle,\n    type IChartApi,\n    type ISeriesApi,\n    type MouseEventParams,\n    type Time,\n} from \"lightweight-charts\";\n\nimport type { Candle } from \"./ChartApi\";\n\ntype CandleSeriesApi = ISeriesApi<\"Candlestick\">;\ntype ReplayPriceLine = ReturnType<CandleSeriesApi[\"createPriceLine\"]>;\n\nexport interface ReplayOptions {\n    chart: IChartApi;\n    candleSeries: CandleSeriesApi;\n\n    barReplayButton: HTMLButtonElement;\n    replayControls: HTMLElement;\n    previousBarButton: HTMLButtonElement;\n    nextBarButton: HTMLButtonElement;\n    exitReplayButton: HTMLButtonElement;\n    currentBarNumber: HTMLElement;\n    totalBarNumber: HTMLElement;\n    onDisplayChange?: () => void;\n    styleCandle?: (candle: Candle) => Candle;\n}\n\ninterface ReplayState {\n    isReplaying: boolean;\n    isSelectingStartBar: boolean;\n    currentBarIndex: number;\n    totalBars: number;\n    fullData: Candle[];\n    priceLine: ReplayPriceLine | null;\n}\n\nfunction timeEquals(a: Time, b: Time): boolean {\n    return JSON.stringify(a) === JSON.stringify(b);\n}\n\nexport class Replay {\n    private readonly chart: IChartApi;\n    private readonly candleSeries: CandleSeriesApi;\n\n    private readonly barReplayButton: HTMLButtonElement;\n    private readonly replayControls: HTMLElement;\n    private readonly previousBarButton: HTMLButtonElement;\n    private readonly nextBarButton: HTMLButtonElement;\n    private readonly exitReplayButton: HTMLButtonElement;\n    private readonly currentBarNumber: HTMLElement;\n    private readonly totalBarNumber: HTMLElement;\n    private readonly onDisplayChange?: () => void;\n    private readonly styleCandle: (candle: Candle) => Candle;\n    private displayedBarIndex = -1;\n    private originalScrollOptions: {\n        shiftVisibleRangeOnNewBar: boolean;\n        allowShiftVisibleRangeOnWhitespaceReplacement: boolean;\n    } | null = null;\n\n    private state: ReplayState = {\n        isReplaying: false,\n        isSelectingStartBar: false,\n        currentBarIndex: 0,\n        totalBars: 0,\n        fullData: [],\n        priceLine: null,\n    };\n\n    constructor(options: ReplayOptions) {\n        this.chart = options.chart;\n        this.candleSeries = options.candleSeries;\n\n        this.barReplayButton = options.barReplayButton;\n        this.replayControls = options.replayControls;\n        this.previousBarButton = options.previousBarButton;\n        this.nextBarButton = options.nextBarButton;\n        this.exitReplayButton = options.exitReplayButton;\n        this.currentBarNumber = options.currentBarNumber;\n        this.totalBarNumber = options.totalBarNumber;\n        this.onDisplayChange = options.onDisplayChange;\n        this.styleCandle = options.styleCandle ?? (candle => candle);\n    }\n\n    public mount(): void {\n        this.barReplayButton.addEventListener(\"click\", () => {\n            if (!this.state.isReplaying && !this.state.isSelectingStartBar) {\n                this.startSelectionMode();\n            } else {\n                this.exit();\n            }\n        });\n\n        this.previousBarButton.addEventListener(\"click\", () => {\n            this.previousBar();\n        });\n\n        this.nextBarButton.addEventListener(\"click\", () => {\n            this.nextBar();\n        });\n\n        this.exitReplayButton.addEventListener(\"click\", () => {\n            this.exit();\n        });\n    }\n\n    public isReplaying(): boolean { return this.state.isReplaying; }\n\n    public getReplayTime(): Time | undefined {\n        return this.state.isReplaying ? this.state.fullData[this.state.currentBarIndex]?.time : undefined;\n    }\n\n    public setData(data: Candle[]): void {\n        this.state.fullData = data;\n        this.state.totalBars = data.length;\n        // ChartApp installs this same full array on the candle series.\n        this.displayedBarIndex = data.length - 1;\n    }\n\n    public refreshCandleStyles(): void {\n        this.keepViewport(() => {\n            const displayed = this.state.fullData.slice(0, this.displayedBarIndex + 1);\n            this.candleSeries.setData(displayed.map(this.styleCandle));\n        });\n    }\n\n    public handleChartClick(param: MouseEventParams<Time>): void {\n        if (!param.time) {\n            return;\n        }\n\n        const clickedBarIndex = this.state.fullData.findIndex((bar) => {\n            return timeEquals(bar.time, param.time as Time);\n        });\n\n        if (clickedBarIndex === -1) {\n            return;\n        }\n\n        if (this.state.isSelectingStartBar) {\n            this.startFromBar(clickedBarIndex);\n            return;\n        }\n\n        if (this.state.isReplaying) {\n            this.state.currentBarIndex = clickedBarIndex;\n            this.updateDisplay();\n        }\n    }\n\n    public exit(restoreFullChart = true): void {\n        this.state.isReplaying = false;\n        this.state.isSelectingStartBar = false;\n        this.state.currentBarIndex = 0;\n\n        this.barReplayButton.classList.remove(\"btn-active\");\n        this.barReplayButton.innerHTML = toolIcon(\"play\");\n        this.barReplayButton.title = \"Bar replay\";\n        this.barReplayButton.setAttribute(\"aria-pressed\", \"false\");\n\n        this.replayControls.classList.add(\"hidden\");\n\n        if (this.state.priceLine) {\n            this.candleSeries.removePriceLine(this.state.priceLine);\n            this.state.priceLine = null;\n        }\n\n        if (restoreFullChart && this.state.fullData.length > 0) {\n            this.keepViewport(() => {\n                this.candleSeries.setData(this.state.fullData.map(this.styleCandle));\n                this.displayedBarIndex = this.state.fullData.length - 1;\n                this.restoreScrollOptions();\n            });\n        } else this.restoreScrollOptions();\n    }\n\n    private startSelectionMode(): void {\n        if (this.state.fullData.length === 0) {\n            this.barReplayButton.dispatchEvent(new CustomEvent(\"chartix:notice\", {\n                bubbles: true, detail: \"No data loaded. Please fetch data first.\",\n            }));\n            return;\n        }\n\n        this.state.isSelectingStartBar = true;\n        this.state.isReplaying = false;\n        this.state.totalBars = this.state.fullData.length;\n\n        this.barReplayButton.classList.add(\"btn-active\");\n        this.barReplayButton.innerHTML = toolIcon(\"stop\");\n        this.barReplayButton.title = \"Stop replay\";\n        this.barReplayButton.setAttribute(\"aria-pressed\", \"true\");\n\n        this.replayControls.classList.remove(\"hidden\");\n\n        this.keepViewport(() => {\n            const scale = this.chart.timeScale();\n            const options = scale.options();\n            this.originalScrollOptions ??= {\n                shiftVisibleRangeOnNewBar: options.shiftVisibleRangeOnNewBar,\n                allowShiftVisibleRangeOnWhitespaceReplacement: options.allowShiftVisibleRangeOnWhitespaceReplacement,\n            };\n            // Replaying a new bar must never switch on an implicit follow mode.\n            scale.applyOptions({\n                shiftVisibleRangeOnNewBar: false,\n                allowShiftVisibleRangeOnWhitespaceReplacement: false,\n            });\n        });\n        this.previousBarButton.disabled = true;\n        this.nextBarButton.disabled = true;\n\n        this.currentBarNumber.textContent = \"?\";\n        this.totalBarNumber.textContent = String(this.state.totalBars);\n\n        console.log(\"Click on a bar to start replay from that point.\");\n    }\n\n    private startFromBar(barIndex: number): void {\n        this.state.isReplaying = true;\n        this.state.isSelectingStartBar = false;\n        this.state.currentBarIndex = barIndex;\n\n        this.addPriceLine();\n        this.updateDisplay();\n    }\n\n    private previousBar(): void {\n        if (!this.state.isReplaying) {\n            return;\n        }\n\n        if (this.state.currentBarIndex > 0) {\n            this.state.currentBarIndex -= 1;\n            this.updateDisplay();\n        }\n    }\n\n    private nextBar(): void {\n        if (!this.state.isReplaying) {\n            return;\n        }\n\n        if (this.state.currentBarIndex < this.state.totalBars - 1) {\n            this.state.currentBarIndex += 1;\n            this.updateDisplay();\n        }\n    }\n\n    /** Preserve the user's current view, including fractional zoom and future space. */\n    private keepViewport(update: () => void): void {\n        const scale = this.chart.timeScale();\n        const logical = scale.getVisibleLogicalRange();\n        const priceScale = this.candleSeries.priceScale();\n        const manualPriceRange = priceScale.options().autoScale ? null : priceScale.getVisibleRange();\n        try {\n            update();\n        } finally {\n            // Logical indices preserve blank space beyond the final candle;\n            // visible date ranges cannot represent that space reliably.\n            if (logical) scale.setVisibleLogicalRange(logical);\n            if (manualPriceRange) priceScale.setVisibleRange(manualPriceRange);\n        }\n        this.onDisplayChange?.();\n    }\n\n    private restoreScrollOptions(): void {\n        if (!this.originalScrollOptions) return;\n        this.chart.timeScale().applyOptions(this.originalScrollOptions);\n        this.originalScrollOptions = null;\n    }\n\n    private updateDisplay(): void {\n        const target = this.state.currentBarIndex;\n        this.keepViewport(() => {\n            if (target === this.displayedBarIndex + 1) {\n                this.candleSeries.update(this.styleCandle(this.state.fullData[target]));\n            } else if (target === this.displayedBarIndex - 1) {\n                this.candleSeries.pop(1);\n            } else if (target !== this.displayedBarIndex) {\n                // A click can seek to any bar; rebuild only for such a seek.\n                this.candleSeries.setData(this.state.fullData.slice(0, target + 1).map(this.styleCandle));\n            }\n            this.displayedBarIndex = target;\n            this.updatePriceLine();\n        });\n\n        this.currentBarNumber.textContent = String(this.state.currentBarIndex + 1);\n        this.totalBarNumber.textContent = String(this.state.totalBars);\n\n        this.previousBarButton.disabled = this.state.currentBarIndex === 0;\n        this.nextBarButton.disabled =\n            this.state.currentBarIndex === this.state.totalBars - 1;\n    }\n\n    private addPriceLine(): void {\n        if (this.state.priceLine) {\n            this.candleSeries.removePriceLine(this.state.priceLine);\n        }\n\n        const currentBar = this.state.fullData[this.state.currentBarIndex];\n\n        if (!currentBar) {\n            return;\n        }\n\n        this.state.priceLine = this.candleSeries.createPriceLine({\n            price: currentBar.close,\n            color: \"#FF6B6B\",\n            lineWidth: 2,\n            lineStyle: LineStyle.Dashed,\n            axisLabelVisible: true,\n            title: \"Current Bar\",\n        });\n    }\n\n    private updatePriceLine(): void {\n        if (!this.state.priceLine) {\n            return;\n        }\n\n        const currentBar = this.state.fullData[this.state.currentBarIndex];\n\n        if (!currentBar) {\n            return;\n        }\n\n        this.state.priceLine.applyOptions({\n            price: currentBar.close,\n        });\n    }\n}\n","import { DENSE_CHART_OPTIONS } from \"./DenseChartOptions\";\nimport {\n    createChart,\n    type IChartApi,\n    type LogicalRange,\n} from \"lightweight-charts\";\n\nexport interface IndicatorPaneOptions {\n    mainChart: IChartApi;\n    mainContainer: HTMLElement;\n    indicatorContainer: HTMLElement;\n    separator: HTMLElement;\n\n    /**\n     * The chart/container immediately above this separator.\n     *\n     * For the first pane these are the main price chart/container.\n     * For later panes these are the previous indicator pane/chart.\n     */\n    resizeUpperContainer?: HTMLElement;\n    resizeUpperChart?: IChartApi;\n}\n\nfunction isValidLogicalRange(\n    range: LogicalRange | null,\n): range is LogicalRange {\n    if (!range) {\n        return false;\n    }\n\n    if (!Number.isFinite(range.from)) {\n        return false;\n    }\n\n    if (!Number.isFinite(range.to)) {\n        return false;\n    }\n\n    return range.to > range.from;\n}\n\nfunction logicalRangesEqual(\n    left: LogicalRange | null,\n    right: LogicalRange | null,\n    epsilon = 0.001,\n): boolean {\n    if (\n        !isValidLogicalRange(left)\n        || !isValidLogicalRange(right)\n    ) {\n        return false;\n    }\n\n    return (\n        Math.abs(left.from - right.from) <= epsilon\n        && Math.abs(left.to - right.to) <= epsilon\n    );\n}\n\nexport class IndicatorPane {\n    public readonly chart: IChartApi;\n\n    private readonly mainChart: IChartApi;\n    private readonly mainContainer: HTMLElement;\n    private readonly indicatorContainer: HTMLElement;\n    private readonly separator: HTMLElement;\n\n    private resizeUpperContainer: HTMLElement;\n    private resizeUpperChart: IChartApi;\n\n    private isDragging = false;\n    private isSyncing = false;\n\n    /**\n     * Pane -> main synchronization is deliberately disabled until the pane\n     * has first been seeded from the main chart. This prevents an empty/new\n     * pane from overwriting the main chart's startup fitContent() range.\n     */\n    private reverseSyncReady = false;\n\n    /*\n     * Lightweight Charts may emit a visible-range callback shortly after a\n     * programmatic setVisibleLogicalRange(). With several panes, those delayed\n     * callbacks used to race back into the main chart and undo a mouse-wheel\n     * zoom. Keep a short provenance window so programmatic pane feedback is\n     * ignored, while a genuine wheel/pointer action immediately wins.\n     */\n    private suppressPaneFeedbackStartedAt = 0;\n    private suppressPaneFeedbackUntil = 0;\n    private lastPaneInteractionAt = 0;\n\n    private dragStartY = 0;\n    private dragStartUpperHeight = 0;\n    private dragStartPaneHeight = 0;\n\n    private readonly handleSeparatorMouseDown = (\n        event: MouseEvent,\n    ): void => {\n        event.preventDefault();\n\n        this.isDragging = true;\n        this.dragStartY = event.clientY;\n        this.dragStartUpperHeight =\n            this.resizeUpperContainer.getBoundingClientRect().height;\n        this.dragStartPaneHeight =\n            this.indicatorContainer.getBoundingClientRect().height;\n\n        document.body.style.cursor = \"row-resize\";\n        document.body.style.userSelect = \"none\";\n    };\n\n    private readonly handleDocumentMouseUp = (): void => {\n        if (!this.isDragging) {\n            return;\n        }\n\n        this.isDragging = false;\n        document.body.style.cursor = \"default\";\n        document.body.style.userSelect = \"\";\n    };\n\n    private readonly handleDocumentMouseMove = (\n        event: MouseEvent,\n    ): void => {\n        if (!this.isDragging) {\n            return;\n        }\n\n        const delta = event.clientY - this.dragStartY;\n\n        const minUpperHeight = 120;\n        const minPaneHeight = 100;\n\n        const nextUpperHeight =\n            this.dragStartUpperHeight + delta;\n\n        const nextPaneHeight =\n            this.dragStartPaneHeight - delta;\n\n        if (\n            nextUpperHeight < minUpperHeight\n            || nextPaneHeight < minPaneHeight\n        ) {\n            return;\n        }\n\n        this.resizeUpperContainer.style.flex = \"none\";\n        this.indicatorContainer.style.flex = \"none\";\n\n        this.resizeUpperContainer.style.height =\n            `${nextUpperHeight}px`;\n\n        this.indicatorContainer.style.height =\n            `${nextPaneHeight}px`;\n\n        this.resizeUpperChart.resize(\n            this.resizeUpperContainer.clientWidth,\n            this.resizeUpperContainer.clientHeight,\n        );\n\n        this.chart.resize(\n            this.indicatorContainer.clientWidth,\n            this.indicatorContainer.clientHeight,\n        );\n    };\n\n    private readonly markPaneInteraction = (): void => {\n        this.lastPaneInteractionAt = performance.now();\n    };\n\n    private suppressPaneFeedback(): void {\n        const now = performance.now();\n        this.suppressPaneFeedbackStartedAt = now;\n        this.suppressPaneFeedbackUntil = now + 120;\n    }\n\n    private readonly handleMainRangeChange = (\n        range: LogicalRange | null,\n    ): void => {\n        if (this.isSyncing) {\n            return;\n        }\n\n        if (!isValidLogicalRange(range)) {\n            return;\n        }\n\n        const paneRange =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        if (logicalRangesEqual(paneRange, range)) {\n            return;\n        }\n\n        this.suppressPaneFeedback();\n        this.isSyncing = true;\n\n        try {\n            this.chart\n                .timeScale()\n                .setVisibleLogicalRange(range);\n        } finally {\n            this.isSyncing = false;\n        }\n    };\n\n    private readonly handlePaneRangeChange = (\n        range: LogicalRange | null,\n    ): void => {\n        if (!this.reverseSyncReady) {\n            return;\n        }\n\n        if (this.isSyncing) {\n            return;\n        }\n\n        if (!isValidLogicalRange(range)) {\n            return;\n        }\n\n        const now = performance.now();\n        const isProgrammaticEcho = (\n            now < this.suppressPaneFeedbackUntil\n            && this.lastPaneInteractionAt\n                <= this.suppressPaneFeedbackStartedAt\n        );\n\n        if (isProgrammaticEcho) {\n            return;\n        }\n\n        const mainRange =\n            this.mainChart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        if (logicalRangesEqual(mainRange, range)) {\n            return;\n        }\n\n        this.isSyncing = true;\n\n        try {\n            this.mainChart\n                .timeScale()\n                .setVisibleLogicalRange(range);\n        } finally {\n            this.isSyncing = false;\n        }\n    };\n\n    constructor(options: IndicatorPaneOptions) {\n        this.mainChart = options.mainChart;\n        this.mainContainer = options.mainContainer;\n        this.indicatorContainer = options.indicatorContainer;\n        this.separator = options.separator;\n\n        this.resizeUpperContainer =\n            options.resizeUpperContainer\n            ?? options.mainContainer;\n\n        this.resizeUpperChart =\n            options.resizeUpperChart\n            ?? options.mainChart;\n\n        this.chart = createChart(\n            this.indicatorContainer,\n            {\n                width:\n                    this.indicatorContainer.clientWidth,\n\n                height:\n                    this.indicatorContainer.clientHeight,\n\n                layout: {\n                    background: {\n                        color: \"white\",\n                    },\n                    textColor: \"#000\",\n                },\n\n                leftPriceScale: {\n                    visible: false,\n                    borderColor: \"#ccc\",\n                },\n\n                rightPriceScale: {\n                    borderColor: \"#ccc\",\n                },\n\n                timeScale: {\n                    ...DENSE_CHART_OPTIONS,\n                    minBarSpacing: 0.001,\n                    borderColor: \"#ccc\",\n                    timeVisible: true,\n                },\n\n                handleScroll: {\n                    pressedMouseMove: true,\n                    horzTouchDrag: true,\n                    vertTouchDrag: true,\n                    mouseWheel: true,\n                },\n\n                handleScale: {\n                    mouseWheel: true,\n                    pinch: true,\n                    axisPressedMouseMove: true,\n                },\n            },\n        );\n\n        this.indicatorContainer.addEventListener(\n            \"wheel\",\n            this.markPaneInteraction,\n            { passive: true, capture: true },\n        );\n\n        this.indicatorContainer.addEventListener(\n            \"pointerdown\",\n            this.markPaneInteraction,\n            true,\n        );\n\n        this.bindResizeDrag();\n        this.bindTwoWayTimeSync();\n    }\n\n    /**\n     * Used after pane deletion so the pane below it can resize against its new\n     * immediate upper neighbour.\n     */\n    public setResizeUpper(\n        container: HTMLElement,\n        chart: IChartApi,\n    ): void {\n        this.resizeUpperContainer = container;\n        this.resizeUpperChart = chart;\n    }\n\n    public resize(): void {\n        this.chart.resize(\n            this.indicatorContainer.clientWidth,\n            this.indicatorContainer.clientHeight,\n        );\n    }\n\n    public applyTheme(isDark: boolean): void {\n        this.chart.applyOptions({\n            layout: {\n                background: {\n                    color: isDark\n                        ? \"#0f172a\"\n                        : \"white\",\n                },\n\n                textColor: isDark\n                    ? \"#e5e7eb\"\n                    : \"#000\",\n            },\n\n            leftPriceScale: {\n                borderColor: isDark\n                    ? \"#334155\"\n                    : \"#ccc\",\n            },\n\n            rightPriceScale: {\n                borderColor: isDark\n                    ? \"#334155\"\n                    : \"#ccc\",\n            },\n\n            timeScale: {\n                borderColor: isDark\n                    ? \"#334155\"\n                    : \"#ccc\",\n\n                timeVisible: true,\n            },\n        });\n    }\n\n    /**\n     * Explicitly initialize/re-align this pane from the main chart.\n     * Only after this succeeds is pane -> main synchronization enabled.\n     */\n    public copyMainVisibleRange(): void {\n        const mainRange =\n            this.mainChart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        if (!isValidLogicalRange(mainRange)) {\n            return;\n        }\n\n        if (logicalRangesEqual(\n            this.chart.timeScale().getVisibleLogicalRange(),\n            mainRange,\n        )) {\n            this.reverseSyncReady = true;\n            return;\n        }\n\n        this.suppressPaneFeedback();\n        this.isSyncing = true;\n\n        try {\n            this.chart\n                .timeScale()\n                .setVisibleLogicalRange(mainRange);\n        } finally {\n            this.isSyncing = false;\n        }\n\n        this.reverseSyncReady = true;\n    }\n\n    /**\n     * setData()/series creation can itself cause Lightweight Charts to emit a\n     * visible-range event. Keep reverse synchronization muted for the whole\n     * update so indicator recalculation never moves the main chart.\n     */\n    public updateIndicatorWithoutMovingMain(\n        updateFn: () => void,\n    ): void {\n        const mainRangeBeforeUpdate =\n            this.mainChart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        this.isSyncing = true;\n\n        try {\n            updateFn();\n\n            if (\n                isValidLogicalRange(\n                    mainRangeBeforeUpdate,\n                )\n                && !logicalRangesEqual(\n                    this.chart.timeScale().getVisibleLogicalRange(),\n                    mainRangeBeforeUpdate,\n                )\n            ) {\n                this.suppressPaneFeedback();\n\n                this.chart\n                    .timeScale()\n                    .setVisibleLogicalRange(\n                        mainRangeBeforeUpdate,\n                    );\n            }\n        } catch (error) {\n            console.error(\n                \"Indicator update failed:\",\n                error,\n            );\n\n            throw error;\n        } finally {\n            this.isSyncing = false;\n        }\n\n        if (\n            isValidLogicalRange(\n                mainRangeBeforeUpdate,\n            )\n        ) {\n            this.reverseSyncReady = true;\n        }\n    }\n\n    public destroy(): void {\n        this.separator.removeEventListener(\n            \"mousedown\",\n            this.handleSeparatorMouseDown,\n        );\n\n        document.removeEventListener(\n            \"mouseup\",\n            this.handleDocumentMouseUp,\n        );\n\n        document.removeEventListener(\n            \"mousemove\",\n            this.handleDocumentMouseMove,\n        );\n\n        this.mainChart\n            .timeScale()\n            .unsubscribeVisibleLogicalRangeChange(\n                this.handleMainRangeChange,\n            );\n\n        this.chart\n            .timeScale()\n            .unsubscribeVisibleLogicalRangeChange(\n                this.handlePaneRangeChange,\n            );\n\n        this.indicatorContainer.removeEventListener(\n            \"wheel\",\n            this.markPaneInteraction,\n            true,\n        );\n\n        this.indicatorContainer.removeEventListener(\n            \"pointerdown\",\n            this.markPaneInteraction,\n            true,\n        );\n\n        this.chart.remove();\n    }\n\n    private bindResizeDrag(): void {\n        this.separator.addEventListener(\n            \"mousedown\",\n            this.handleSeparatorMouseDown,\n        );\n\n        document.addEventListener(\n            \"mouseup\",\n            this.handleDocumentMouseUp,\n        );\n\n        document.addEventListener(\n            \"mousemove\",\n            this.handleDocumentMouseMove,\n        );\n    }\n\n    private bindTwoWayTimeSync(): void {\n        this.mainChart\n            .timeScale()\n            .subscribeVisibleLogicalRangeChange(\n                this.handleMainRangeChange,\n            );\n\n        this.chart\n            .timeScale()\n            .subscribeVisibleLogicalRangeChange(\n                this.handlePaneRangeChange,\n            );\n    }\n}\n","import type {\r\n    IndicatorRequest,\r\n    IndicatorResponse,\r\n} from \"./IndicatorContracts\";\r\n\r\nexport type IndicatorUrlBuilder = (indicatorId: string) => string;\r\n\r\nfunction getCookie(name: string): string | null {\r\n    const prefix = `${name}=`;\r\n\r\n    for (const rawPart of document.cookie.split(\";\")) {\r\n        const part = rawPart.trim();\r\n\r\n        if (part.startsWith(prefix)) {\r\n            return decodeURIComponent(part.slice(prefix.length));\r\n        }\r\n    }\r\n\r\n    return null;\r\n}\r\n\r\nfunction assertIndicatorResponse(value: unknown): asserts value is IndicatorResponse {\r\n    if (!value || typeof value !== \"object\") {\r\n        throw new Error(\"Indicator response is not an object.\");\r\n    }\r\n\r\n    const response = value as Partial<IndicatorResponse>;\r\n\r\n    if (!response.indicator || typeof response.indicator !== \"object\") {\r\n        throw new Error(\"Indicator response is missing indicator metadata.\");\r\n    }\r\n\r\n    if (\r\n        typeof response.indicator.id !== \"string\" ||\r\n        typeof response.indicator.title !== \"string\"\r\n    ) {\r\n        throw new Error(\"Indicator metadata is invalid.\");\r\n    }\r\n\r\n    if (!Array.isArray(response.parameters)) {\r\n        throw new Error(\"Indicator response is missing parameters.\");\r\n    }\r\n\r\n    if (!Array.isArray(response.plots)) {\r\n        throw new Error(\"Indicator response is missing plots.\");\r\n    }\r\n\r\n    if (!response.metrics || typeof response.metrics !== \"object\") {\r\n        throw new Error(\"Indicator response is missing metrics.\");\r\n    }\r\n}\r\n\r\nexport class LabApi {\r\n    private readonly indicatorUrlBuilder: IndicatorUrlBuilder;\r\n\r\n    constructor(indicatorUrlBuilder: IndicatorUrlBuilder) {\r\n        this.indicatorUrlBuilder = indicatorUrlBuilder;\r\n    }\r\n\r\n    public async fetchIndicator(\r\n        request: IndicatorRequest,\r\n        signal?: AbortSignal,\r\n    ): Promise<IndicatorResponse> {\r\n        const rawUrl =\r\n            this.indicatorUrlBuilder(\r\n                request.indicatorId,\r\n            );\r\n\r\n        const url =\r\n            new URL(\r\n                rawUrl,\r\n                window.location.href,\r\n            );\r\n\r\n        url.searchParams.set(\r\n            \"symbol\",\r\n            request.symbol,\r\n        );\r\n\r\n        url.searchParams.set(\r\n            \"timeframe\",\r\n            request.timeframe,\r\n        );\r\n\r\n        const csrfToken = getCookie(\"csrftoken\");\r\n\r\n        const headers: Record<string, string> = {\r\n            \"Content-Type\": \"application/json\",\r\n            Accept: \"application/json\",\r\n            \"X-Chartix-Indicator-Transport\": \"2\",\r\n        };\r\n\r\n        if (csrfToken) {\r\n            headers[\"X-CSRFToken\"] = csrfToken;\r\n        }\r\n\r\n        const response = await fetch(url.toString(), {\r\n            method: \"POST\",\r\n            credentials: \"same-origin\",\r\n            headers,\r\n            body: JSON.stringify({\r\n                params: request.params,\r\n                source: request.source,\r\n            }),\r\n            signal,\r\n        });\r\n\r\n        let payload: unknown;\r\n\r\n        try {\r\n            payload = await response.json();\r\n        } catch {\r\n            throw new Error(\r\n                `Indicator request failed with HTTP ${response.status}; the response was not JSON.`,\r\n            );\r\n        }\r\n\r\n        if (!response.ok) {\r\n            const message =\r\n                payload &&\r\n                typeof payload === \"object\" &&\r\n                \"error\" in payload &&\r\n                typeof payload.error === \"string\"\r\n                    ? payload.error\r\n                    : `Indicator request failed with HTTP ${response.status}.`;\r\n\r\n            throw new Error(message);\r\n        }\r\n\r\n        assertIndicatorResponse(payload);\r\n        return payload;\r\n    }\r\n}\r\n","import type {\r\n    IndicatorParameterSpec,\r\n    IndicatorParameterValue,\r\n} from \"./IndicatorContracts\";\r\n\r\n\r\nexport interface IndicatorControlsOptions {\r\n    container: HTMLElement;\r\n    onValueChange?: () => void;\r\n}\r\n\r\n\r\ntype ControlElement =\r\n    | HTMLInputElement\r\n    | HTMLSelectElement;\r\n\r\n\r\ninterface RenderedControl {\r\n    spec: IndicatorParameterSpec;\r\n    element: ControlElement;\r\n}\r\n\r\n\r\n/**\r\n * Generic renderer for backend indicator parameters.\r\n *\r\n * `select` is intentionally first-class.  ChartApp uses that type for the\r\n * synthetic Source parameter, so every indicator gets the same source UI\r\n * without requiring indicator-specific frontend code.\r\n */\r\nexport class IndicatorControls {\r\n    private readonly container: HTMLElement;\r\n    private readonly onValueChange?: () => void;\r\n\r\n    private readonly controls =\r\n        new Map<string, RenderedControl>();\r\n\r\n    private globallyDisabled = false;\r\n\r\n\r\n    public constructor(\r\n        options: IndicatorControlsOptions,\r\n    ) {\r\n        this.container = options.container;\r\n        this.onValueChange = options.onValueChange;\r\n    }\r\n\r\n\r\n    public clear(): void {\r\n        this.controls.clear();\r\n        this.container.replaceChildren();\r\n    }\r\n\r\n\r\n    public render(\r\n        parameters: IndicatorParameterSpec[],\r\n    ): void {\r\n        this.clear();\r\n\r\n        for (const spec of parameters) {\r\n            this.renderParameter(spec);\r\n        }\r\n\r\n        this.applyDisabledState();\r\n    }\r\n\r\n\r\n    public getValues(): Record<\r\n        string,\r\n        IndicatorParameterValue\r\n    > {\r\n        const values: Record<\r\n            string,\r\n            IndicatorParameterValue\r\n        > = Object.create(null);\r\n\r\n        for (\r\n            const [id, rendered]\r\n            of this.controls\r\n        ) {\r\n            values[id] = this.readValue(\r\n                rendered,\r\n            );\r\n        }\r\n\r\n        return values;\r\n    }\r\n\r\n\r\n    public setDisabled(\r\n        disabled: boolean,\r\n    ): void {\r\n        this.globallyDisabled = disabled;\r\n        this.applyDisabledState();\r\n    }\r\n\r\n\r\n    private renderParameter(\r\n        spec: IndicatorParameterSpec,\r\n    ): void {\r\n        const row = document.createElement(\"div\");\r\n        row.className = \"indicator-control\";\r\n        row.dataset.indicatorParameterId = spec.id;\r\n\r\n        Object.assign(\r\n            row.style,\r\n            {\r\n                display: \"grid\",\r\n                gridTemplateColumns: \"84px minmax(0, 1fr)\",\r\n                gap: \"8px\",\r\n                alignItems: \"center\",\r\n                marginBottom: \"8px\",\r\n            },\r\n        );\r\n\r\n        const label = document.createElement(\"label\");\r\n        label.textContent = spec.label;\r\n        label.style.fontSize = \"12px\";\r\n        label.style.minWidth = \"0\";\r\n\r\n        const control =\r\n            this.createControl(spec);\r\n\r\n        control.dataset.indicatorParameterId = spec.id;\r\n\r\n        row.append(label, control);\r\n        this.container.append(row);\r\n\r\n        if (spec.description) {\r\n            const description =\r\n                document.createElement(\"div\");\r\n\r\n            description.className =\r\n                \"indicator-control-description\";\r\n\r\n            description.textContent =\r\n                spec.description;\r\n\r\n            Object.assign(\r\n                description.style,\r\n                {\r\n                    gridColumn: \"2\",\r\n                    marginTop: \"-4px\",\r\n                    marginBottom: \"8px\",\r\n                    fontSize: \"11px\",\r\n                    lineHeight: \"1.35\",\r\n                    opacity: \"0.72\",\r\n                },\r\n            );\r\n\r\n            this.container.append(\r\n                description,\r\n            );\r\n        }\r\n\r\n        this.controls.set(\r\n            spec.id,\r\n            {\r\n                spec,\r\n                element: control,\r\n            },\r\n        );\r\n    }\r\n\r\n\r\n    private createControl(\r\n        spec: IndicatorParameterSpec,\r\n    ): ControlElement {\r\n        if (spec.type === \"select\") {\r\n            const select =\r\n                document.createElement(\"select\");\r\n\r\n            select.style.width = \"100%\";\r\n            select.style.minWidth = \"0\";\r\n\r\n            const options = spec.options ?? [];\r\n\r\n            options.forEach(\r\n                (option, index) => {\r\n                    const element =\r\n                        document.createElement(\"option\");\r\n\r\n                    /*\r\n                     * Store the option index rather than stringifying the\r\n                     * value. This preserves number/string/boolean select\r\n                     * values exactly, including the JSON string used by the\r\n                     * Source selector.\r\n                     */\r\n                    element.value = String(index);\r\n                    element.textContent = option.label;\r\n\r\n                    if (\r\n                        this.valuesEqual(\r\n                            option.value,\r\n                            spec.value,\r\n                        )\r\n                    ) {\r\n                        element.selected = true;\r\n                    }\r\n\r\n                    select.append(element);\r\n                },\r\n            );\r\n\r\n            if (\r\n                options.length > 0\r\n                && select.selectedIndex < 0\r\n            ) {\r\n                select.selectedIndex = 0;\r\n            }\r\n\r\n            select.addEventListener(\r\n                \"change\",\r\n                () => this.onValueChange?.(),\r\n            );\r\n\r\n            return select;\r\n        }\r\n\r\n        const input =\r\n            document.createElement(\"input\");\r\n\r\n        input.style.width = \"100%\";\r\n        input.style.minWidth = \"0\";\r\n\r\n        if (spec.type === \"boolean\") {\r\n            input.type = \"checkbox\";\r\n            input.checked = Boolean(spec.value);\r\n\r\n            input.addEventListener(\r\n                \"change\",\r\n                () => this.onValueChange?.(),\r\n            );\r\n\r\n            return input;\r\n        }\r\n\r\n        if (\r\n            spec.type === \"number\"\r\n            || spec.type === \"integer\"\r\n        ) {\r\n            input.type = \"number\";\r\n            input.value = String(spec.value);\r\n\r\n            if (spec.min !== undefined) {\r\n                input.min = String(spec.min);\r\n            }\r\n\r\n            if (spec.max !== undefined) {\r\n                input.max = String(spec.max);\r\n            }\r\n\r\n            if (spec.step !== undefined) {\r\n                input.step = String(spec.step);\r\n            } else if (spec.type === \"integer\") {\r\n                input.step = \"1\";\r\n            }\r\n\r\n            input.addEventListener(\r\n                \"input\",\r\n                () => this.onValueChange?.(),\r\n            );\r\n\r\n            return input;\r\n        }\r\n\r\n        input.type = \"text\";\r\n        input.value = String(spec.value ?? \"\");\r\n\r\n        input.addEventListener(\r\n            \"input\",\r\n            () => this.onValueChange?.(),\r\n        );\r\n\r\n        return input;\r\n    }\r\n\r\n\r\n    private readValue(\r\n        rendered: RenderedControl,\r\n    ): IndicatorParameterValue {\r\n        const { spec, element } = rendered;\r\n\r\n        if (\r\n            spec.type === \"select\"\r\n            && element instanceof HTMLSelectElement\r\n        ) {\r\n            const options = spec.options ?? [];\r\n            const index = element.selectedIndex;\r\n\r\n            if (\r\n                index < 0\r\n                || index >= options.length\r\n            ) {\r\n                throw new Error(\r\n                    `${spec.label} has no valid selection.`,\r\n                );\r\n            }\r\n\r\n            return options[index].value;\r\n        }\r\n\r\n        if (!(element instanceof HTMLInputElement)) {\r\n            throw new Error(\r\n                `${spec.label} has an invalid control.`,\r\n            );\r\n        }\r\n\r\n        if (spec.type === \"boolean\") {\r\n            return element.checked;\r\n        }\r\n\r\n        if (\r\n            spec.type === \"number\"\r\n            || spec.type === \"integer\"\r\n        ) {\r\n            const value = Number(element.value);\r\n\r\n            if (!Number.isFinite(value)) {\r\n                throw new Error(\r\n                    `${spec.label} must be a number.`,\r\n                );\r\n            }\r\n\r\n            if (\r\n                spec.type === \"integer\"\r\n                && !Number.isInteger(value)\r\n            ) {\r\n                throw new Error(\r\n                    `${spec.label} must be an integer.`,\r\n                );\r\n            }\r\n\r\n            if (\r\n                spec.min !== undefined\r\n                && value < spec.min\r\n            ) {\r\n                throw new Error(\r\n                    `${spec.label} must be at least ${spec.min}.`,\r\n                );\r\n            }\r\n\r\n            if (\r\n                spec.max !== undefined\r\n                && value > spec.max\r\n            ) {\r\n                throw new Error(\r\n                    `${spec.label} must be at most ${spec.max}.`,\r\n                );\r\n            }\r\n\r\n            return value;\r\n        }\r\n\r\n        return element.value;\r\n    }\r\n\r\n\r\n    private applyDisabledState(): void {\r\n        for (const { spec, element } of this.controls.values()) {\r\n            element.disabled = (\r\n                this.globallyDisabled\r\n                || spec.disabled === true\r\n            );\r\n        }\r\n    }\r\n\r\n\r\n    private valuesEqual(\r\n        left: IndicatorParameterValue,\r\n        right: IndicatorParameterValue,\r\n    ): boolean {\r\n        return (\r\n            typeof left === typeof right\r\n            && left === right\r\n        );\r\n    }\r\n}\r\n","import { toolIcon } from \"./workspace/ToolIcons\";\nimport type {\n    IndicatorLineSpec,\n} from \"./IndicatorContracts\";\n\n\nexport interface IndicatorLineScaleOption {\n    value: string;\n    label: string;\n}\n\n\nexport interface IndicatorLineLegendItem {\n    instanceId: string;\n    instanceLabel: string;\n    plotId: string;\n    line: IndicatorLineSpec;\n    visible: boolean;\n\n    /** Current scale selection plus valid merge targets for this pane. */\n    scaleValue: string;\n    scaleOptions: IndicatorLineScaleOption[];\n}\n\n\nexport interface IndicatorLineLegendOptions {\n    container: HTMLElement;\n\n    onVisibilityChange: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        visible: boolean,\n    ) => void;\n\n    onScaleChange?: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        scaleValue: string,\n    ) => void;\n\n    onDeleteIndicator?: (instanceId: string) => void;\n\n    onDownloadIndicator?: (\n        instanceId: string,\n    ) => void;\n\n    onLineDragStart?: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        title: string,\n    ) => void;\n\n    onLineDragEnd?: () => void;\n}\n\n\nconst STYLE_ELEMENT_ID = \"indicator-line-legend-styles\";\n\n\nfunction injectStyles(): void {\n    if (document.getElementById(STYLE_ELEMENT_ID)) {\n        return;\n    }\n\n    const style = document.createElement(\"style\");\n    style.id = STYLE_ELEMENT_ID;\n\n    style.textContent = `\n        .indicator-line-legend {\n            position: absolute;\n            top: 7px;\n            left: 8px;\n            z-index: 40;\n\n            max-width: calc(100% - 16px);\n\n            display: none;\n            align-items: center;\n            flex-wrap: wrap;\n            gap: 3px;\n\n            pointer-events: auto;\n        }\n\n        .indicator-line-legend.is-visible {\n            display: flex;\n        }\n\n        .indicator-line-toggle {\n            height: 22px;\n            min-width: 0;\n\n            display: inline-flex;\n            align-items: center;\n            gap: 2px;\n\n            padding: 1px 2px;\n\n            border: 1px solid hsl(var(--bc) / 0.10);\n            border-radius: 5px;\n\n            background: hsl(var(--b1) / 0.86);\n            color: hsl(var(--bc));\n\n            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n            backdrop-filter: blur(6px);\n\n            cursor: grab;\n            user-select: none;\n\n            transition:\n                opacity 110ms ease,\n                border-color 110ms ease,\n                background-color 110ms ease;\n        }\n\n        .indicator-line-toggle:hover {\n            border-color: hsl(var(--p) / 0.32);\n        }\n\n        .indicator-line-toggle:active {\n            cursor: grabbing;\n        }\n\n        .indicator-line-toggle.is-dragging {\n            opacity: 0.55;\n        }\n\n        .indicator-line-toggle.is-hidden {\n            opacity: 0.48;\n            background: hsl(var(--b2) / 0.76);\n        }\n\n        /* Compact drag/key control. The full line name lives only in tooltip. */\n        .indicator-line-drag-grip {\n            width: 17px;\n            height: 17px;\n            flex: none;\n\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n\n            border-radius: 4px;\n            background: hsl(var(--bc) / 0.055);\n\n            font-size: 9px;\n            line-height: 1;\n            letter-spacing: -2px;\n            opacity: 0.62;\n            user-select: none;\n        }\n\n        .indicator-line-scale-select {\n            width: 68px;\n            max-width: 68px;\n            height: 17px;\n\n            margin: 0;\n            padding: 0 13px 0 4px;\n\n            border: 1px solid hsl(var(--bc) / 0.10);\n            border-radius: 4px;\n\n            background: hsl(var(--b2) / 0.74);\n            color: hsl(var(--bc) / 0.76);\n\n            font: inherit;\n            font-size: 8px;\n            font-weight: 650;\n            line-height: 1;\n\n            cursor: pointer;\n        }\n\n        .indicator-line-scale-select:hover,\n        .indicator-line-scale-select:focus {\n            border-color: hsl(var(--p) / 0.34);\n            outline: none;\n        }\n\n        .indicator-line-download-button,\n        .indicator-line-eye-button {\n            width: 17px;\n            height: 17px;\n            flex: none;\n\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n\n            padding: 0;\n\n            border: 0;\n            border-radius: 4px;\n\n            background: transparent;\n            color: inherit;\n\n            cursor: pointer;\n            opacity: 0.62;\n        }\n\n        .indicator-line-download-button:hover,\n        .indicator-line-eye-button:hover {\n            background: hsl(var(--bc) / 0.07);\n            opacity: 1;\n        }\n\n        .indicator-line-download-icon,\n        .indicator-line-eye {\n            width: 10px;\n            flex: none;\n\n            font-size: 8px;\n            line-height: 1;\n            text-align: center;\n        }\n\n        @media (max-width: 680px) {\n            .indicator-line-legend {\n                top: 5px;\n                left: 6px;\n                max-width: calc(100% - 12px);\n                gap: 2px;\n            }\n\n            .indicator-line-scale-select {\n                width: 58px;\n                max-width: 58px;\n            }\n        }\n    `;\n\n    document.head.append(style);\n}\n\n\nexport class IndicatorLineLegend {\n    private readonly container: HTMLElement;\n\n    private readonly onVisibilityChange: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        visible: boolean,\n    ) => void;\n\n    private readonly onScaleChange?: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        scaleValue: string,\n    ) => void;\n\n    private readonly onDeleteIndicator?: (instanceId: string) => void;\n\n    private readonly onDownloadIndicator?: (\n        instanceId: string,\n    ) => void;\n\n    private readonly onLineDragStart?: (\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        title: string,\n    ) => void;\n\n    private readonly onLineDragEnd?: () => void;\n\n    private readonly root: HTMLDivElement;\n    private lines: IndicatorLineLegendItem[] = [];\n\n\n    constructor(options: IndicatorLineLegendOptions) {\n        injectStyles();\n\n        this.container = options.container;\n        this.onVisibilityChange = options.onVisibilityChange;\n        this.onScaleChange = options.onScaleChange;\n        this.onDeleteIndicator = options.onDeleteIndicator;\n        this.onDownloadIndicator = options.onDownloadIndicator;\n        this.onLineDragStart = options.onLineDragStart;\n        this.onLineDragEnd = options.onLineDragEnd;\n\n        if (getComputedStyle(this.container).position === \"static\") {\n            this.container.style.position = \"relative\";\n        }\n\n        this.root = document.createElement(\"div\");\n        this.root.className = \"indicator-line-legend\";\n        this.root.setAttribute(\n            \"aria-label\",\n            \"Indicator line visibility, scale and placement\",\n        );\n\n        this.container.append(this.root);\n    }\n\n\n    public render(\n        lines: IndicatorLineLegendItem[],\n    ): void {\n        this.lines = lines.map((item) => ({\n            ...item,\n            scaleOptions: item.scaleOptions.map(\n                (option) => ({ ...option }),\n            ),\n        }));\n\n        this.renderItems();\n    }\n\n\n    public clear(): void {\n        this.lines = [];\n        this.root.replaceChildren();\n        this.root.classList.remove(\"is-visible\");\n    }\n\n\n    public destroy(): void {\n        this.clear();\n        this.root.remove();\n    }\n\n\n    private renderItems(): void {\n        this.root.replaceChildren();\n\n        if (this.lines.length === 0) {\n            this.root.classList.remove(\"is-visible\");\n            return;\n        }\n\n        const fragment = document.createDocumentFragment();\n\n        const seen = new Set<string>();\n        for (const item of this.lines) {\n            fragment.append(this.createItem(item, !seen.has(item.instanceId)));\n            seen.add(item.instanceId);\n        }\n\n        this.root.append(fragment);\n        this.root.classList.add(\"is-visible\");\n    }\n\n\n    private createItem(\n        item: IndicatorLineLegendItem,\n        showDelete: boolean,\n    ): HTMLDivElement {\n        const row = document.createElement(\"div\");\n        row.className = \"indicator-line-toggle\";\n        row.draggable = true;\n        row.classList.toggle(\"is-hidden\", !item.visible);\n\n        const fullTitle = (\n            `${item.instanceLabel} · ${item.line.title}`\n        );\n\n        row.title = fullTitle;\n        row.setAttribute(\"role\", \"group\");\n        row.setAttribute(\"aria-label\", fullTitle);\n\n        const grip = document.createElement(\"span\");\n        grip.className = \"indicator-line-drag-grip\";\n        grip.textContent = \"⠿\";\n        grip.title = `Drag ${fullTitle}`;\n        grip.setAttribute(\"aria-hidden\", \"true\");\n\n        const title = document.createElement(\"span\");\n        title.className = \"indicator-line-title\";\n        title.textContent = item.line.title;\n\n        const scaleSelect = document.createElement(\"select\");\n        scaleSelect.className = \"indicator-line-scale-select\";\n        scaleSelect.draggable = false;\n        scaleSelect.title = \"Y scale: keep separate or merge with another line\";\n        scaleSelect.setAttribute(\n            \"aria-label\",\n            `${fullTitle} Y scale`,\n        );\n\n        for (const scaleOption of item.scaleOptions) {\n            const option = document.createElement(\"option\");\n            option.value = scaleOption.value;\n            option.textContent = scaleOption.label;\n            scaleSelect.append(option);\n        }\n\n        scaleSelect.value = item.scaleValue;\n\n        const downloadButton = document.createElement(\"button\");\n        downloadButton.type = \"button\";\n        downloadButton.className = \"indicator-line-download-button\";\n        downloadButton.draggable = false;\n        downloadButton.title = `Download ${item.instanceLabel} results as CSV`;\n        downloadButton.setAttribute(\n            \"aria-label\",\n            `Download ${item.instanceLabel} results as CSV`,\n        );\n\n        downloadButton.innerHTML = toolIcon(\"download\");\n\n        const eyeButton = document.createElement(\"button\");\n        eyeButton.type = \"button\";\n        eyeButton.className = \"indicator-line-eye-button\";\n        eyeButton.draggable = false;\n        eyeButton.title = item.visible\n            ? `Hide ${fullTitle}`\n            : `Show ${fullTitle}`;\n        eyeButton.setAttribute(\n            \"aria-pressed\",\n            String(item.visible),\n        );\n\n        eyeButton.setAttribute(\"aria-label\", eyeButton.title);\n        eyeButton.innerHTML = toolIcon(item.visible ? \"eye\" : \"eyeOff\");\n        row.append(grip, title, scaleSelect, downloadButton, eyeButton);\n        if (showDelete && this.onDeleteIndicator) {\n            const remove = document.createElement(\"button\");\n            remove.type = \"button\";\n            remove.draggable = false;\n            remove.className = \"indicator-line-delete-button chartix-delete-button\";\n            remove.title = `Delete ${item.instanceLabel}`;\n            remove.setAttribute(\"aria-label\", remove.title);\n            remove.innerHTML = toolIcon(\"delete\");\n            remove.addEventListener(\"dragstart\", event => { event.preventDefault(); event.stopPropagation(); });\n            remove.addEventListener(\"click\", event => {\n                event.stopPropagation();\n                this.onDeleteIndicator?.(item.instanceId);\n            });\n            row.append(remove);\n        }\n\n        /*\n         * Lower panes use pointerdown on the pane container to activate the\n         * pane owner. Legend interaction must not rebuild the legend before\n         * dragstart or a control click completes.\n         */\n        row.addEventListener(\"pointerdown\", (event) => {\n            event.stopPropagation();\n        });\n\n        scaleSelect.addEventListener(\"pointerdown\", (event) => {\n            event.stopPropagation();\n        });\n\n        scaleSelect.addEventListener(\"dragstart\", (event) => {\n            event.preventDefault();\n            event.stopPropagation();\n        });\n\n        scaleSelect.addEventListener(\"change\", (event) => {\n            event.stopPropagation();\n\n            item.scaleValue = scaleSelect.value;\n\n            this.onScaleChange?.(\n                item.instanceId,\n                item.plotId,\n                item.line.id,\n                item.scaleValue,\n            );\n        });\n\n        downloadButton.addEventListener(\"pointerdown\", (event) => {\n            event.stopPropagation();\n        });\n\n        downloadButton.addEventListener(\"dragstart\", (event) => {\n            event.preventDefault();\n            event.stopPropagation();\n        });\n\n        downloadButton.addEventListener(\"click\", (event) => {\n            event.stopPropagation();\n            this.onDownloadIndicator?.(item.instanceId);\n        });\n\n        eyeButton.addEventListener(\"pointerdown\", (event) => {\n            event.stopPropagation();\n        });\n\n        eyeButton.addEventListener(\"dragstart\", (event) => {\n            event.preventDefault();\n            event.stopPropagation();\n        });\n\n        eyeButton.addEventListener(\"click\", (event) => {\n            event.stopPropagation();\n\n            item.visible = !item.visible;\n\n            this.onVisibilityChange(\n                item.instanceId,\n                item.plotId,\n                item.line.id,\n                item.visible,\n            );\n\n            this.renderItems();\n        });\n\n        row.addEventListener(\"dragstart\", (event) => {\n            row.classList.add(\"is-dragging\");\n\n            if (event.dataTransfer) {\n                event.dataTransfer.effectAllowed = \"move\";\n                event.dataTransfer.setData(\n                    \"text/plain\",\n                    `${item.instanceId}:${item.plotId}:${item.line.id}`,\n                );\n            }\n\n            this.onLineDragStart?.(\n                item.instanceId,\n                item.plotId,\n                item.line.id,\n                fullTitle,\n            );\n        });\n\n        row.addEventListener(\"dragend\", () => {\n            row.classList.remove(\"is-dragging\");\n            this.onLineDragEnd?.();\n        });\n\n        return row;\n    }\n}\n","import type { IPrimitivePaneRenderer, ISeriesPrimitive, SeriesAttachedParameter, Time } from \"lightweight-charts\";\nimport { chartTime } from \"./ChartApi\";\nimport type { IndicatorFillPoint, IndicatorFillSpec } from \"./IndicatorContracts\";\n\ntype PriceCoordinates = Pick<SeriesAttachedParameter<Time>[\"series\"], \"priceToCoordinate\">;\n\nfunction lowerBound(points: readonly IndicatorFillPoint[], time: number): number {\n    let low = 0;\n    let high = points.length;\n    while (low < high) {\n        const middle = (low + high) >>> 1;\n        if (chartTime(points[middle].time) < time) low = middle + 1;\n        else high = middle;\n    }\n    return low;\n}\n\nexport class IndicatorFillPrimitive implements ISeriesPrimitive<Time> {\n    private attachedTo?: SeriesAttachedParameter<Time>;\n    private fills: readonly IndicatorFillSpec[] = [];\n\n    private readonly view = [{\n        zOrder: () => \"bottom\" as const,\n        renderer: () => this.renderer,\n    }];\n\n    private readonly renderer: IPrimitivePaneRenderer = {\n        draw: target => {\n            const attachment = this.attachedTo;\n            if (!attachment) return;\n            const scale = attachment.chart.timeScale();\n            const visible = scale.getVisibleRange();\n            if (!visible) return;\n            const cutoff = this.replayCutoff();\n            target.useMediaCoordinateSpace(({ context }) => {\n                context.save();\n                for (const fill of this.fills) {\n                    const other = this.otherSeries(fill.otherLineId);\n                    if (!other) continue;\n                    const points = fill.points;\n                    const start = Math.max(0, lowerBound(points, chartTime(visible.from)) - 1);\n                    const end = Math.min(points.length, lowerBound(points, chartTime(visible.to)) + 2);\n                    let run: { x: number; first: number; second: number }[] = [];\n                    let color: string | undefined;\n                    const paint = () => {\n                        if (color && run.length >= 2) {\n                            context.fillStyle = color;\n                            context.beginPath();\n                            context.moveTo(run[0].x, run[0].first);\n                            for (const point of run.slice(1)) context.lineTo(point.x, point.first);\n                            for (let index = run.length - 1; index >= 0; index--) {\n                                const point = run[index];\n                                context.lineTo(point.x, point.second);\n                            }\n                            context.closePath();\n                            context.fill();\n                        }\n                        run = [];\n                    };\n                    for (let index = start; index < end; index++) {\n                        const point = points[index];\n                        if (point.availableAt > cutoff) break;\n                        const x = scale.timeToCoordinate(point.time);\n                        const first = attachment.series.priceToCoordinate(point.first);\n                        const second = other.priceToCoordinate(point.second);\n                        if (x === null || first === null || second === null) {\n                            paint();\n                            continue;\n                        }\n                        const vertex = { x, first, second };\n                        if (point.startsGap) paint();\n                        if (run.length) {\n                            run.push(vertex);\n                            if (point.color === color) continue;\n                            paint();\n                        }\n                        color = point.color;\n                        run = [vertex];\n                    }\n                    paint();\n                }\n                context.restore();\n            });\n        },\n    };\n\n    public constructor(\n        private readonly otherSeries: (id: string) => PriceCoordinates | undefined,\n        private readonly replayCutoff: () => number,\n    ) {}\n\n    public paneViews() { return this.view; }\n    public attached(attachment: SeriesAttachedParameter<Time>): void { this.attachedTo = attachment; }\n    public detached(): void { this.attachedTo = undefined; }\n\n    public setFills(fills: readonly IndicatorFillSpec[]): void {\n        if (this.fills === fills) return;\n        this.fills = fills;\n        this.refresh();\n    }\n\n    public refresh(): void { this.attachedTo?.requestUpdate(); }\n}\n","import {\n    type IChartApi,\n    type ISeriesApi,\n} from \"lightweight-charts\";\n\n\ntype IndicatorSeriesApi = ISeriesApi<\"Line\"> | ISeriesApi<\"Histogram\">;\n\n\nexport interface VisibleScaleRailEntry {\n    scaleId: string;\n    title: string;\n    color: string;\n    series: IndicatorSeriesApi;\n}\n\n\ninterface RegisteredChart {\n    chart: IChartApi;\n    container: HTMLElement;\n    root: HTMLDivElement;\n    entries: VisibleScaleRailEntry[];\n    rangeHandler: () => void;\n    resizeObserver: ResizeObserver | null;\n    interactionHandler: () => void;\n}\n\n\ninterface ActiveRailDrag {\n    pointerId: number;\n    startY: number;\n    from: number;\n    to: number;\n}\n\n\nconst RAIL_WIDTH = 58;\nconst RAIL_GAP = 1;\nconst TICK_COUNT = 7;\n\n\n/**\n * Lightweight Charts exposes unlimited overlay price scales, but only the\n * built-in `left` and `right` scales are visible in its UI. Chartix keeps the\n * native axes for the first available scales and renders these rails for every\n * additional overlay scale.\n *\n * The labels are not an approximation of the data range: each label is\n * obtained through the real series.coordinateToPrice() mapping, so it follows\n * the exact Lightweight Charts scale transformation.\n */\nexport class VisiblePriceScaleRails {\n    private readonly registrations =\n        new Map<IChartApi, RegisteredChart>();\n\n    private readonly dirtyCharts =\n        new Set<IChartApi>();\n\n    private frame: number | null = null;\n\n\n    public registerChart(\n        chart: IChartApi,\n        container: HTMLElement,\n    ): void {\n        const existing =\n            this.registrations.get(chart);\n\n        if (existing) {\n            if (existing.container !== container) {\n                existing.container = container;\n            }\n\n            this.schedule(chart);\n            return;\n        }\n\n        const position =\n            window.getComputedStyle(container).position;\n\n        if (position === \"static\") {\n            container.style.position = \"relative\";\n        }\n\n        const root = document.createElement(\"div\");\n        root.className = \"chartix-visible-scale-rails\";\n\n        Object.assign(root.style, {\n            position: \"absolute\",\n            inset: \"0\",\n            zIndex: \"24\",\n            pointerEvents: \"none\",\n            overflow: \"hidden\",\n        });\n\n        container.append(root);\n\n        const rangeHandler = (): void => {\n            this.schedule(chart);\n        };\n\n        const interactionHandler = (): void => {\n            this.schedule(chart);\n        };\n\n        chart.timeScale().subscribeVisibleLogicalRangeChange(\n            rangeHandler,\n        );\n\n        container.addEventListener(\n            \"wheel\",\n            interactionHandler,\n            { passive: true, capture: true },\n        );\n\n        container.addEventListener(\n            \"pointerup\",\n            interactionHandler,\n            true,\n        );\n\n        container.addEventListener(\n            \"dblclick\",\n            interactionHandler,\n            true,\n        );\n\n        const resizeObserver = (\n            typeof ResizeObserver !== \"undefined\"\n                ? new ResizeObserver(() => {\n                    this.schedule(chart);\n                })\n                : null\n        );\n\n        resizeObserver?.observe(container);\n\n        this.registrations.set(\n            chart,\n            {\n                chart,\n                container,\n                root,\n                entries: [],\n                rangeHandler,\n                resizeObserver,\n                interactionHandler,\n            },\n        );\n    }\n\n\n    public unregisterChart(\n        chart: IChartApi,\n    ): void {\n        const registration =\n            this.registrations.get(chart);\n\n        if (!registration) {\n            return;\n        }\n\n        chart.timeScale().unsubscribeVisibleLogicalRangeChange(\n            registration.rangeHandler,\n        );\n\n        registration.container.removeEventListener(\n            \"wheel\",\n            registration.interactionHandler,\n            true,\n        );\n\n        registration.container.removeEventListener(\n            \"pointerup\",\n            registration.interactionHandler,\n            true,\n        );\n\n        registration.container.removeEventListener(\n            \"dblclick\",\n            registration.interactionHandler,\n            true,\n        );\n\n        registration.resizeObserver?.disconnect();\n        registration.root.remove();\n\n        this.dirtyCharts.delete(chart);\n        this.registrations.delete(chart);\n    }\n\n\n    public update(\n        chart: IChartApi,\n        entries: VisibleScaleRailEntry[],\n    ): void {\n        const registration =\n            this.registrations.get(chart);\n\n        if (!registration) {\n            return;\n        }\n\n        registration.entries = [...entries];\n        this.schedule(chart);\n    }\n\n\n    public refreshAll(): void {\n        for (const chart of this.registrations.keys()) {\n            this.schedule(chart);\n        }\n    }\n\n\n    private schedule(\n        chart: IChartApi,\n    ): void {\n        if (!this.registrations.has(chart)) {\n            return;\n        }\n\n        this.dirtyCharts.add(chart);\n\n        if (this.frame !== null) {\n            return;\n        }\n\n        this.frame = window.requestAnimationFrame(() => {\n            this.frame = null;\n\n            const charts = [...this.dirtyCharts];\n            this.dirtyCharts.clear();\n\n            for (const dirtyChart of charts) {\n                this.render(dirtyChart);\n            }\n        });\n    }\n\n\n    private render(\n        chart: IChartApi,\n    ): void {\n        const registration =\n            this.registrations.get(chart);\n\n        if (!registration) {\n            return;\n        }\n\n        const {\n            container,\n            root,\n            entries,\n        } = registration;\n\n        root.replaceChildren();\n\n        if (entries.length === 0) {\n            return;\n        }\n\n        const timeScaleHeight =\n            chart.timeScale().height();\n\n        const plotHeight = Math.max(\n            32,\n            container.clientHeight\n                - timeScaleHeight,\n        );\n\n        const rightNativeWidth =\n            chart.priceScale(\"right\").width();\n\n        const leftNativeWidth =\n            chart.priceScale(\"left\").width();\n\n        let rightIndex = 0;\n        let leftIndex = 0;\n\n        entries.forEach((entry, index) => {\n            const side: \"left\" | \"right\" = (\n                index % 2 === 0\n                    ? \"right\"\n                    : \"left\"\n            );\n\n            const rail = this.createRail(\n                chart,\n                entry,\n                plotHeight,\n                side,\n            );\n\n            const offset = (\n                side === \"right\"\n                    ? rightNativeWidth\n                        + rightIndex * (RAIL_WIDTH + RAIL_GAP)\n                    : leftNativeWidth\n                        + leftIndex * (RAIL_WIDTH + RAIL_GAP)\n            );\n\n            if (side === \"right\") {\n                rail.style.right = `${offset}px`;\n                rightIndex += 1;\n            } else {\n                rail.style.left = `${offset}px`;\n                leftIndex += 1;\n            }\n\n            root.append(rail);\n        });\n    }\n\n\n    private createRail(\n        chart: IChartApi,\n        entry: VisibleScaleRailEntry,\n        plotHeight: number,\n        side: \"left\" | \"right\",\n    ): HTMLDivElement {\n        const isDark = (\n            document.body.classList.contains(\"dark\")\n            || document.body.getAttribute(\"data-theme\") === \"dark\"\n        );\n\n        const rail = document.createElement(\"div\");\n        rail.className = (\n            \"chartix-visible-price-scale \"\n            + `chartix-visible-price-scale-${side}`\n        );\n        rail.dataset.priceScaleId = entry.scaleId;\n        rail.title = `${entry.title} · drag to scale · double-click to autoscale`;\n\n        Object.assign(rail.style, {\n            position: \"absolute\",\n            top: \"0\",\n            width: `${RAIL_WIDTH}px`,\n            height: `${plotHeight}px`,\n            boxSizing: \"border-box\",\n            pointerEvents: \"auto\",\n            cursor: \"ns-resize\",\n            userSelect: \"none\",\n            background: isDark\n                ? \"rgba(15, 23, 42, 0.91)\"\n                : \"rgba(255, 255, 255, 0.92)\",\n            color: isDark\n                ? \"#cbd5e1\"\n                : \"#475569\",\n            borderLeft: side === \"right\"\n                ? `1px solid ${isDark ? \"#334155\" : \"#d5d9df\"}`\n                : \"none\",\n            borderRight: side === \"left\"\n                ? `1px solid ${isDark ? \"#334155\" : \"#d5d9df\"}`\n                : \"none\",\n            fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace\",\n            fontSize: \"9px\",\n            lineHeight: \"1\",\n        });\n\n        const accent = document.createElement(\"div\");\n\n        Object.assign(accent.style, {\n            position: \"absolute\",\n            top: \"0\",\n            left: \"0\",\n            right: \"0\",\n            height: \"2px\",\n            background: entry.color,\n            opacity: \"0.9\",\n            pointerEvents: \"none\",\n        });\n\n        rail.append(accent);\n\n        const topPadding = 12;\n        const bottomPadding = 10;\n        const usableHeight = Math.max(\n            1,\n            plotHeight - topPadding - bottomPadding,\n        );\n\n        for (let tick = 0; tick < TICK_COUNT; tick += 1) {\n            const ratio = (\n                tick / (TICK_COUNT - 1)\n            );\n\n            const y = (\n                topPadding\n                + ratio * usableHeight\n            );\n\n            const price =\n                entry.series.coordinateToPrice(y);\n\n            if (\n                price === null\n                || !Number.isFinite(price)\n            ) {\n                continue;\n            }\n\n            const label = document.createElement(\"div\");\n            label.textContent = this.formatValue(price);\n\n            Object.assign(label.style, {\n                position: \"absolute\",\n                top: `${y}px`,\n                left: \"3px\",\n                right: \"3px\",\n                transform: \"translateY(-50%)\",\n                textAlign: side === \"right\"\n                    ? \"left\"\n                    : \"right\",\n                whiteSpace: \"nowrap\",\n                overflow: \"hidden\",\n                textOverflow: \"clip\",\n                pointerEvents: \"none\",\n            });\n\n            rail.append(label);\n        }\n\n        this.bindScaleInteraction(\n            rail,\n            chart,\n            entry.scaleId,\n        );\n\n        return rail;\n    }\n\n\n    private bindScaleInteraction(\n        rail: HTMLDivElement,\n        chart: IChartApi,\n        scaleId: string,\n    ): void {\n        let drag: ActiveRailDrag | null = null;\n\n        const scale = chart.priceScale(scaleId);\n\n        rail.addEventListener(\n            \"pointerdown\",\n            (event) => {\n                if (event.button !== 0) {\n                    return;\n                }\n\n                const range = scale.getVisibleRange();\n\n                if (\n                    !range\n                    || !Number.isFinite(range.from)\n                    || !Number.isFinite(range.to)\n                    || range.from === range.to\n                ) {\n                    return;\n                }\n\n                event.preventDefault();\n                event.stopPropagation();\n\n                scale.setAutoScale(false);\n\n                drag = {\n                    pointerId: event.pointerId,\n                    startY: event.clientY,\n                    from: range.from,\n                    to: range.to,\n                };\n\n                rail.setPointerCapture(\n                    event.pointerId,\n                );\n            },\n        );\n\n        rail.addEventListener(\n            \"pointermove\",\n            (event) => {\n                if (\n                    !drag\n                    || drag.pointerId !== event.pointerId\n                ) {\n                    return;\n                }\n\n                event.preventDefault();\n                event.stopPropagation();\n\n                const delta =\n                    event.clientY - drag.startY;\n\n                const factor = Math.exp(\n                    delta * 0.008,\n                );\n\n                const center =\n                    (drag.from + drag.to) / 2;\n\n                const halfSpan =\n                    Math.abs(drag.to - drag.from)\n                    * factor\n                    / 2;\n\n                scale.setVisibleRange({\n                    from: center - halfSpan,\n                    to: center + halfSpan,\n                });\n\n            },\n        );\n\n        const stopDrag = (\n            event: PointerEvent,\n        ): void => {\n            if (\n                !drag\n                || drag.pointerId !== event.pointerId\n            ) {\n                return;\n            }\n\n            event.preventDefault();\n            event.stopPropagation();\n\n            drag = null;\n\n            if (\n                rail.hasPointerCapture(\n                    event.pointerId,\n                )\n            ) {\n                rail.releasePointerCapture(\n                    event.pointerId,\n                );\n            }\n\n            this.schedule(chart);\n        };\n\n        rail.addEventListener(\n            \"pointerup\",\n            stopDrag,\n        );\n\n        rail.addEventListener(\n            \"pointercancel\",\n            stopDrag,\n        );\n\n        rail.addEventListener(\n            \"wheel\",\n            (event) => {\n                const range = scale.getVisibleRange();\n\n                if (\n                    !range\n                    || !Number.isFinite(range.from)\n                    || !Number.isFinite(range.to)\n                    || range.from === range.to\n                ) {\n                    return;\n                }\n\n                event.preventDefault();\n                event.stopPropagation();\n\n                scale.setAutoScale(false);\n\n                const factor = Math.exp(\n                    event.deltaY * 0.0015,\n                );\n\n                const center =\n                    (range.from + range.to) / 2;\n\n                const halfSpan =\n                    Math.abs(range.to - range.from)\n                    * factor\n                    / 2;\n\n                scale.setVisibleRange({\n                    from: center - halfSpan,\n                    to: center + halfSpan,\n                });\n\n                this.schedule(chart);\n            },\n            { passive: false },\n        );\n\n        rail.addEventListener(\n            \"dblclick\",\n            (event) => {\n                event.preventDefault();\n                event.stopPropagation();\n\n                scale.setAutoScale(true);\n                this.schedule(chart);\n            },\n        );\n    }\n\n\n    private formatValue(\n        value: number,\n    ): string {\n        const absolute = Math.abs(value);\n\n        if (absolute >= 1_000_000_000) {\n            return `${(value / 1_000_000_000).toFixed(2)}B`;\n        }\n\n        if (absolute >= 1_000_000) {\n            return `${(value / 1_000_000).toFixed(2)}M`;\n        }\n\n        if (absolute >= 10_000) {\n            return `${(value / 1_000).toFixed(1)}K`;\n        }\n\n        if (absolute >= 100) {\n            return value.toFixed(1);\n        }\n\n        if (absolute >= 1) {\n            return value.toFixed(3);\n        }\n\n        if (absolute >= 0.01) {\n            return value.toFixed(4);\n        }\n\n        if (absolute === 0) {\n            return \"0\";\n        }\n\n        if (absolute >= 0.000001) {\n            return value.toFixed(6);\n        }\n\n        return value.toExponential(2);\n    }\n}\n","import { chartTime } from \"./ChartApi\";\nimport { IndicatorFillPrimitive } from \"./IndicatorFillPrimitive\";\nimport {\n    HistogramSeries,\n    LineSeries,\n    LineStyle,\n    type IChartApi,\n    type ISeriesApi,\n    type LineData,\n    type Time,\n    type WhitespaceData,\n} from \"lightweight-charts\";\n\nimport type {\n    IndicatorLineSpec,\n    IndicatorPlotSpec,\n} from \"./IndicatorContracts\";\n\nimport {\n    VisiblePriceScaleRails,\n    type VisibleScaleRailEntry,\n} from \"./VisiblePriceScaleRails\";\n\ntype LineSeriesApi = ISeriesApi<\"Line\">;\ntype IndicatorSeriesApi = LineSeriesApi | ISeriesApi<\"Histogram\">;\n\nconst LINE_STYLES = { solid: LineStyle.Solid, dotted: LineStyle.Dotted, dashed: LineStyle.Dashed };\n\ninterface StoredLine {\n    indicatorId: string;\n    plotId: string;\n    lineId: string;\n    spec: IndicatorLineSpec;\n    visible: boolean;\n\n    chart: IChartApi;\n    series: IndicatorSeriesApi | null;\n    fillPrimitive?: IndicatorFillPrimitive;\n\n    /**\n     * Lightweight Charts priceScaleId used by this rendered line.\n     *\n     * Different IDs => independent Y scales.\n     * Same ID      => merged/shared Y scale.\n     */\n    priceScaleId: string;\n}\n\nexport class SeriesManager {\n    private anchorTimes: Time[] = [];\n    private replayTime = Infinity;\n\n    public setReplayTime(time: Time | undefined): boolean {\n        const previous = this.replayTime;\n        this.replayTime = time === undefined ? Infinity : chartTime(time);\n        if (previous === this.replayTime) return false;\n        let changed = false;\n        for (const { series, spec, fillPrimitive } of this.linesByKey.values()) {\n            fillPrimitive?.refresh();\n            if (!series || !spec.respectReplay) continue;\n            const before = this.replayCount(spec, previous);\n            const after = this.replayCount(spec, this.replayTime);\n            if (after === before) continue;\n            if (after === before + 1) series.update(spec.data[before]);\n            else if (after === before - 1) series.pop(1);\n            else series.setData(this.displayedData(spec));\n            changed = true;\n        }\n        return changed;\n    }\n\n    public displayedData(spec: IndicatorLineSpec): IndicatorLineSpec[\"data\"] {\n        if (!spec.respectReplay || this.replayTime === Infinity) return spec.data;\n        return spec.data.slice(0, this.replayCount(spec, this.replayTime));\n    }\n\n    private replayCount(spec: IndicatorLineSpec, cutoff: number): number {\n        let low = 0;\n        let high = spec.data.length;\n        while (low < high) {\n            const middle = Math.floor((low + high) / 2);\n            const availableAt = Math.max(chartTime(spec.data[middle].time), spec.replaySourceTimes?.[middle] ?? -Infinity);\n            if (availableAt <= cutoff) low = middle + 1;\n            else high = middle;\n        }\n        return low;\n    }\n\n    private scaleSerial = 0;\n\n    private readonly scaleRails =\n        new VisiblePriceScaleRails();\n\n    public constructor(\n        private readonly mainChart: IChartApi,\n        mainContainer: HTMLElement,\n    ) {\n        this.scaleRails.registerChart(\n            mainChart,\n            mainContainer,\n        );\n    }\n\n    /**\n     * Every pane gets its own invisible timeline anchor. Main-chart indicators\n     * do not need an anchor because the candle series already owns that\n     * timeline.\n     */\n    private readonly timeAnchors =\n        new Map<IChartApi, LineSeriesApi>();\n\n    private readonly linesByKey =\n        new Map<string, StoredLine>();\n\n    public registerPaneChart(\n        chart: IChartApi,\n        container: HTMLElement,\n    ): void {\n        this.scaleRails.registerChart(\n            chart,\n            container,\n        );\n\n        if (this.timeAnchors.has(chart)) {\n            this.refreshScalePresentation(chart);\n            return;\n        }\n\n        const anchor = chart.addSeries(\n            LineSeries,\n            {\n                title: \"Time Anchor\",\n                color: \"rgba(0, 0, 0, 0)\",\n                lineWidth: 1,\n                priceLineVisible: false,\n                lastValueVisible: false,\n                crosshairMarkerVisible: false,\n            },\n        );\n\n        this.timeAnchors.set(\n            chart,\n            anchor,\n        );\n\n        const data: WhitespaceData<Time>[] =\n            this.anchorTimes.map(\n                (time) => ({ time }),\n            );\n\n        anchor.setData(data);\n        this.refreshScalePresentation(chart);\n    }\n\n    public unregisterPaneChart(\n        chart: IChartApi,\n    ): void {\n        this.timeAnchors.delete(chart);\n        this.scaleRails.unregisterChart(chart);\n    }\n\n    /**\n     * Save the complete candle timeline and push it into every existing pane.\n     * Newly-created panes receive the saved timeline in registerPaneChart().\n     */\n    public setTimeAnchor(times: Time[]): void {\n        this.anchorTimes = [...times];\n\n        const data: WhitespaceData<Time>[] =\n            times.map(\n                (time) => ({ time }),\n            );\n\n        for (\n            const anchor\n            of this.timeAnchors.values()\n        ) {\n            anchor.setData(data);\n        }\n    }\n\n    /**\n     * Replace the complete plotted result for one indicator.\n     *\n     * chart may be the main price chart or one specific indicator pane. Each\n     * stored line remembers its own chart, so many indicators can coexist on\n     * different charts safely.\n     */\n    public setPlots(\n        indicatorId: string,\n        plots: IndicatorPlotSpec[],\n        chart: IChartApi,\n    ): void {\n        const activeKeys = new Set<string>();\n        const affectedCharts =\n            new Set<IChartApi>([chart]);\n\n        for (const plot of plots) {\n            for (const line of plot.lines) {\n                const key = this.makeKey(\n                    indicatorId,\n                    plot.id,\n                    line.id,\n                );\n\n                activeKeys.add(key);\n\n                const previousChart =\n                    this.setIndicatorLine(\n                        indicatorId,\n                        plot.id,\n                        line,\n                        chart,\n                        false,\n                    );\n\n                if (previousChart) {\n                    affectedCharts.add(\n                        previousChart,\n                    );\n                }\n            }\n        }\n\n        const keysToDelete: string[] = [];\n\n        for (\n            const [key, stored]\n            of this.linesByKey.entries()\n        ) {\n            if (\n                stored.indicatorId === indicatorId\n                && !activeKeys.has(key)\n            ) {\n                affectedCharts.add(\n                    stored.chart,\n                );\n\n                this.removeStoredSeries(\n                    stored,\n                );\n\n                keysToDelete.push(key);\n            }\n        }\n\n        for (const key of keysToDelete) {\n            this.linesByKey.delete(key);\n        }\n\n        for (\n            const affectedChart\n            of affectedCharts\n        ) {\n            this.rebalanceScaleSlots(\n                affectedChart,\n            );\n\n            this.enableAutoScale(\n                affectedChart,\n            );\n        }\n    }\n\n    public setIndicatorLine(\n        indicatorId: string,\n        plotId: string,\n        line: IndicatorLineSpec,\n        chart: IChartApi,\n        moveExisting = true,\n    ): IChartApi | null {\n        const key = this.makeKey(\n            indicatorId,\n            plotId,\n            line.id,\n        );\n\n        const existing =\n            this.linesByKey.get(key);\n\n        if (existing) {\n            const previousChart =\n                existing.chart;\n\n            if ((existing.spec.plotStyle ?? \"line\") !== (line.plotStyle ?? \"line\")\n                || (existing.spec.drawInPane ?? true) !== (line.drawInPane ?? true)) {\n                this.removeStoredSeries(existing);\n            }\n            existing.spec = line;\n\n            if (\n                moveExisting\n                && existing.chart !== chart\n            ) {\n                this.removeStoredSeries(\n                    existing,\n                );\n\n                existing.chart = chart;\n                existing.priceScaleId =\n                    this.createIndependentScaleId(\n                        chart,\n                        existing,\n                    );\n            }\n\n            if (existing.visible) {\n                const series =\n                    this.ensureSeries(\n                        existing,\n                    );\n\n                this.applyLineOptions(\n                    series,\n                    line,\n                );\n\n                series.setData(this.displayedData(line));\n            } else {\n                this.removeStoredSeries(\n                    existing,\n                );\n            }\n\n            return previousChart === chart\n                ? null\n                : previousChart;\n        }\n\n        const stored: StoredLine = {\n            indicatorId,\n            plotId,\n            lineId: line.id,\n            spec: line,\n            visible: true,\n            chart,\n            series: null,\n\n            /*\n             * A single IndicatorPlot is one visual unit. Its lines should\n             * begin on the same Y scale (Pine/TradingView semantics), while\n             * a different indicator/plot still receives its own independent\n             * scale by default. Manual Separate/Merge actions can override\n             * this afterwards.\n             */\n            priceScaleId: line.onPriceScale && chart === this.mainChart\n                ? \"right\"\n                : this.getOrCreatePlotScaleId(chart, indicatorId, plotId),\n        };\n\n        this.linesByKey.set(\n            key,\n            stored,\n        );\n\n        const series =\n            this.ensureSeries(stored);\n\n        series.setData(this.displayedData(line));\n\n        return null;\n    }\n\n    /**\n     * Incremental/bar-by-bar path.\n     */\n    public updateIndicatorPoint(\n        indicatorId: string,\n        plotId: string,\n        line: Omit<IndicatorLineSpec, \"data\">,\n        point: LineData<Time>,\n        chart: IChartApi,\n    ): void {\n        const key = this.makeKey(\n            indicatorId,\n            plotId,\n            line.id,\n        );\n\n        const existing =\n            this.linesByKey.get(key);\n\n        if (existing) {\n            existing.spec = {\n                ...line,\n                data: [\n                    ...existing.spec.data,\n                    point,\n                ],\n            };\n\n            if (existing.chart !== chart) {\n                const previousChart =\n                    existing.chart;\n\n                this.removeStoredSeries(\n                    existing,\n                );\n\n                existing.chart = chart;\n                existing.priceScaleId =\n                    this.createIndependentScaleId(\n                        chart,\n                        existing,\n                    );\n\n                this.enableAutoScale(\n                    previousChart,\n                );\n            }\n\n            if (existing.visible) {\n                const series =\n                    this.ensureSeries(\n                        existing,\n                    );\n\n                this.applyLineOptions(\n                    series,\n                    existing.spec,\n                );\n\n                series.update(point);\n            }\n\n            this.enableAutoScale(chart);\n            return;\n        }\n\n        const spec: IndicatorLineSpec = {\n            ...line,\n            data: [point],\n        };\n\n        const stored: StoredLine = {\n            indicatorId,\n            plotId,\n            lineId: line.id,\n            spec,\n            visible: true,\n            chart,\n            series: null,\n            priceScaleId:\n                this.getOrCreatePlotScaleId(\n                    chart,\n                    indicatorId,\n                    plotId,\n                ),\n        };\n\n        this.linesByKey.set(\n            key,\n            stored,\n        );\n\n        const series =\n            this.ensureSeries(stored);\n\n        series.update(point);\n        this.enableAutoScale(chart);\n    }\n\n    public getLineChart(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): IChartApi | null {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        return stored?.chart ?? null;\n    }\n\n\n    /**\n     * Number of logical indicator lines placed on one chart. Hidden lines\n     * still count: hiding a line must not accidentally destroy its pane.\n     */\n    public countLinesOnChart(\n        chart: IChartApi,\n    ): number {\n        let count = 0;\n\n        for (const stored of this.linesByKey.values()) {\n            if (stored.chart === chart) {\n                count += 1;\n            }\n        }\n\n        return count;\n    }\n\n\n    /**\n     * Recalculation should preserve manual pane placement. This returns one\n     * existing destination for the indicator without moving any lines.\n     */\n    public getFirstIndicatorChart(\n        indicatorId: string,\n    ): IChartApi | null {\n        for (const stored of this.linesByKey.values()) {\n            if (stored.indicatorId === indicatorId) {\n                return stored.chart;\n            }\n        }\n\n        return null;\n    }\n\n\n    /**\n     * Used when a pane is clicked after its original owner line has been\n     * moved away. Activate an indicator that is actually present there.\n     */\n    public getFirstIndicatorIdOnChart(\n        chart: IChartApi,\n    ): string | null {\n        for (const stored of this.linesByKey.values()) {\n            if (stored.chart === chart) {\n                return stored.indicatorId;\n            }\n        }\n\n        return null;\n    }\n\n\n    public getLineScaleId(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): string | null {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        return stored?.priceScaleId ?? null;\n    }\n\n\n    /**\n     * Return this line to a scale that no other indicator line currently uses.\n     *\n     * In a lower pane, the first independent line may use the pane's normal\n     * right scale so the user still gets a visible numeric axis. On the main\n     * chart the candle series already owns \"right\", so indicators receive a\n     * custom overlay scale instead.\n     */\n    public separateLineScale(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): boolean {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        if (!stored) {\n            return false;\n        }\n\n        const groupSize =\n            this.countLinesOnScale(\n                stored.chart,\n                stored.priceScaleId,\n            );\n\n        const alreadyIndependent =\n            groupSize <= 1\n            && !(\n                stored.chart === this.mainChart\n                && stored.priceScaleId === \"right\"\n            );\n\n        if (alreadyIndependent) {\n            return false;\n        }\n\n        stored.priceScaleId =\n            this.createIndependentScaleId(\n                stored.chart,\n                stored,\n            );\n\n        this.applyStoredScale(stored);\n        this.rebalanceScaleSlots(stored.chart);\n        this.enableAutoScale(stored.chart);\n\n        return true;\n    }\n\n\n    /**\n     * Attach one line to another line's Y scale. Both lines must currently\n     * live in the same pane/chart.\n     */\n    public mergeLineScaleWithLine(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n        targetIndicatorId: string,\n        targetPlotId: string,\n        targetLineId: string,\n    ): boolean {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        const target =\n            this.linesByKey.get(\n                this.makeKey(\n                    targetIndicatorId,\n                    targetPlotId,\n                    targetLineId,\n                ),\n            );\n\n        if (\n            !stored\n            || !target\n            || stored === target\n            || stored.chart !== target.chart\n        ) {\n            return false;\n        }\n\n        if (\n            stored.priceScaleId\n            === target.priceScaleId\n        ) {\n            return false;\n        }\n\n        stored.priceScaleId =\n            target.priceScaleId;\n\n        this.applyStoredScale(stored);\n        this.rebalanceScaleSlots(stored.chart);\n        this.enableAutoScale(stored.chart);\n\n        return true;\n    }\n\n\n    /**\n     * Main-chart convenience: explicitly merge an indicator line onto the\n     * candle price axis.\n     */\n    public mergeLineScaleWithPrice(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): boolean {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        if (\n            !stored\n            || stored.chart !== this.mainChart\n            || stored.priceScaleId === \"right\"\n        ) {\n            return false;\n        }\n\n        stored.priceScaleId = \"right\";\n\n        this.applyStoredScale(stored);\n        this.rebalanceScaleSlots(stored.chart);\n        this.enableAutoScale(stored.chart);\n\n        return true;\n    }\n\n\n    /**\n     * Move one already-computed line to another chart/pane.\n     * The data/spec/visibility stay unchanged; only the Lightweight Charts\n     * series object is recreated on the destination chart.\n     */\n    public moveIndicatorLine(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n        chart: IChartApi,\n    ): boolean {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        if (!stored || stored.chart === chart) {\n            return false;\n        }\n\n        const previousChart = stored.chart;\n\n        this.removeStoredSeries(stored);\n        stored.chart = chart;\n\n        // Placement and scaling are deliberately separate concepts. A move\n        // always starts the line on an independent scale in the destination\n        // pane/chart. The user can explicitly merge scales afterwards.\n        stored.priceScaleId =\n            this.createIndependentScaleId(\n                chart,\n                stored,\n            );\n\n        if (stored.visible) {\n            const series = this.ensureSeries(stored);\n            this.applyLineOptions(series, stored.spec);\n            series.setData(this.displayedData(stored.spec));\n        }\n\n        this.rebalanceScaleSlots(previousChart);\n        this.rebalanceScaleSlots(chart);\n\n        this.enableAutoScale(previousChart);\n        this.enableAutoScale(chart);\n\n        return true;\n    }\n\n    /**\n     * Used before destroying a pane. Guest lines that currently live on that\n     * chart are moved somewhere safe instead of disappearing with the pane.\n     */\n    public moveLinesFromChart(\n        sourceChart: IChartApi,\n        targetChart: IChartApi,\n    ): number {\n        let moved = 0;\n\n        for (const stored of this.linesByKey.values()) {\n            if (stored.chart !== sourceChart) {\n                continue;\n            }\n\n            if (\n                this.moveIndicatorLine(\n                    stored.indicatorId,\n                    stored.plotId,\n                    stored.lineId,\n                    targetChart,\n                )\n            ) {\n                moved += 1;\n            }\n        }\n\n        return moved;\n    }\n\n    public setLineVisible(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n        visible: boolean,\n    ): void {\n        const key = this.makeKey(\n            indicatorId,\n            plotId,\n            lineId,\n        );\n\n        const stored =\n            this.linesByKey.get(key);\n\n        if (\n            !stored\n            || stored.visible === visible\n        ) {\n            return;\n        }\n\n        stored.visible = visible;\n\n        if (visible) {\n            const series =\n                this.ensureSeries(stored);\n\n            this.applyLineOptions(\n                series,\n                stored.spec,\n            );\n\n            series.setData(this.displayedData(stored.spec));\n        } else {\n            this.removeStoredSeries(\n                stored,\n            );\n        }\n\n        this.enableAutoScale(\n            stored.chart,\n        );\n    }\n\n    public isLineVisible(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): boolean {\n        const stored =\n            this.linesByKey.get(\n                this.makeKey(\n                    indicatorId,\n                    plotId,\n                    lineId,\n                ),\n            );\n\n        return stored?.visible ?? true;\n    }\n\n    public clearIndicator(\n        indicatorId: string,\n    ): void {\n        const keysToDelete: string[] = [];\n        const affectedCharts =\n            new Set<IChartApi>();\n\n        for (\n            const [key, stored]\n            of this.linesByKey.entries()\n        ) {\n            if (\n                stored.indicatorId\n                === indicatorId\n            ) {\n                affectedCharts.add(\n                    stored.chart,\n                );\n\n                this.removeStoredSeries(\n                    stored,\n                );\n\n                keysToDelete.push(key);\n            }\n        }\n\n        for (const key of keysToDelete) {\n            this.linesByKey.delete(key);\n        }\n\n        for (\n            const chart\n            of affectedCharts\n        ) {\n            this.rebalanceScaleSlots(chart);\n            this.enableAutoScale(chart);\n        }\n    }\n\n    public clearAllIndicators(): void {\n        const affectedCharts =\n            new Set<IChartApi>();\n\n        for (\n            const stored\n            of this.linesByKey.values()\n        ) {\n            affectedCharts.add(\n                stored.chart,\n            );\n\n            this.removeStoredSeries(\n                stored,\n            );\n        }\n\n        this.linesByKey.clear();\n\n        for (\n            const chart\n            of affectedCharts\n        ) {\n            this.rebalanceScaleSlots(chart);\n            this.enableAutoScale(chart);\n        }\n\n        // Pane time anchors intentionally remain alive.\n    }\n\n    private ensureSeries(\n        stored: StoredLine,\n    ): IndicatorSeriesApi {\n        if (stored.series) {\n            this.syncFillPrimitive(stored, stored.series);\n            return stored.series;\n        }\n\n        const options = this.indicatorOptions(stored.spec);\n        const scale = { priceScaleId: stored.priceScaleId };\n        const series = stored.spec.plotStyle === \"histogram\"\n            ? stored.chart.addSeries(HistogramSeries, { ...options, ...scale, base: stored.spec.histogramBase ?? 0 })\n            : stored.chart.addSeries(LineSeries, { ...options, ...scale });\n\n        stored.series = series;\n        this.syncFillPrimitive(stored, series);\n\n        return series;\n    }\n\n    private syncFillPrimitive(stored: StoredLine, series: IndicatorSeriesApi): void {\n        if (!stored.spec.fills?.length) {\n            if (stored.fillPrimitive) {\n                series.detachPrimitive(stored.fillPrimitive);\n                stored.fillPrimitive = undefined;\n            }\n            return;\n        }\n        if (!stored.fillPrimitive) {\n            stored.fillPrimitive = new IndicatorFillPrimitive(otherId => {\n                const other = this.linesByKey.get(this.makeKey(stored.indicatorId, stored.plotId, otherId));\n                return other?.chart === stored.chart ? other.series ?? undefined : undefined;\n            }, () => this.replayTime);\n            series.attachPrimitive(stored.fillPrimitive);\n        }\n        stored.fillPrimitive.setFills(stored.spec.fills);\n    }\n\n    private removeStoredSeries(\n        stored: StoredLine,\n    ): void {\n        if (!stored.series) {\n            return;\n        }\n\n        if (stored.fillPrimitive) {\n            stored.series.detachPrimitive(stored.fillPrimitive);\n            stored.fillPrimitive = undefined;\n        }\n        stored.chart.removeSeries(\n            stored.series,\n        );\n\n        stored.series = null;\n    }\n\n    private indicatorOptions(line: IndicatorLineSpec) {\n        const precision = line.precision;\n        const type = line.priceFormat ?? \"price\";\n        return {\n            title: line.title,\n            color: line.color ?? \"#2962ff\",\n            lineWidth: line.lineWidth ?? 2,\n            ...(line.lineStyle ? { lineStyle: LINE_STYLES[line.lineStyle] } : {}),\n            ...(line.priceFormat || precision !== undefined ? {\n                priceFormat: { type, ...(precision === undefined ? {} : { precision, minMove: 10 ** -precision }) },\n            } : {}),\n            priceLineVisible: false,\n            lastValueVisible: line.showPriceLabel ?? true,\n            ...(line.drawInPane === false ? { autoscaleInfoProvider: () => null } : {}),\n        };\n    }\n\n    private applyLineOptions(series: IndicatorSeriesApi, line: IndicatorLineSpec): void {\n        const options = this.indicatorOptions(line);\n        if (line.plotStyle === \"histogram\") {\n            (series as ISeriesApi<\"Histogram\">).applyOptions({ ...options, base: line.histogramBase ?? 0 });\n        } else {\n            (series as LineSeriesApi).applyOptions(options);\n        }\n    }\n\n    private applyStoredScale(\n        stored: StoredLine,\n    ): void {\n        if (!stored.series) {\n            return;\n        }\n\n        stored.series.applyOptions({\n            priceScaleId:\n                stored.priceScaleId,\n        });\n    }\n\n\n    /**\n     * Initial scale policy for a multi-line plot.\n     *\n     * All lines emitted by the same indicator instance + plot ID are born\n     * on the same Y scale when they share a chart. This makes a multi-line\n     * indicator behave as one visual pane/axis unit. Different plots and\n     * different indicator instances remain independent by default.\n     *\n     * Existing manual scale choices are never rewritten here; this helper is\n     * used only when a brand-new logical line is created.\n     */\n    private getOrCreatePlotScaleId(\n        chart: IChartApi,\n        indicatorId: string,\n        plotId: string,\n    ): string {\n        for (const stored of this.linesByKey.values()) {\n            if (\n                stored.chart === chart\n                && stored.indicatorId === indicatorId\n                && stored.plotId === plotId\n            ) {\n                return stored.priceScaleId;\n            }\n        }\n\n        return this.createIndependentScaleId(\n            chart,\n        );\n    }\n\n\n    private createIndependentScaleId(\n        chart: IChartApi,\n        exclude?: StoredLine,\n    ): string {\n        /*\n         * Use the two native, visible Lightweight Charts axes before falling\n         * back to an overlay scale. On the main chart the candle series owns\n         * \"right\", so the first independent indicator uses \"left\". A lower\n         * pane has no candle owner, therefore it uses right, then left.\n         */\n        if (chart !== this.mainChart) {\n            if (\n                !this.chartHasIndicatorOnScale(\n                    chart,\n                    \"right\",\n                    exclude,\n                )\n            ) {\n                return \"right\";\n            }\n\n            if (\n                !this.chartHasIndicatorOnScale(\n                    chart,\n                    \"left\",\n                    exclude,\n                )\n            ) {\n                return \"left\";\n            }\n        } else if (\n            !this.chartHasIndicatorOnScale(\n                chart,\n                \"left\",\n                exclude,\n            )\n        ) {\n            return \"left\";\n        }\n\n        return this.createCustomScaleId();\n    }\n\n\n    private createCustomScaleId(): string {\n        this.scaleSerial += 1;\n\n        return (\n            \"chartix-indicator-scale-\"\n            + this.scaleSerial\n        );\n    }\n\n\n    /**\n     * Compact the remaining independent scale groups into the visible native\n     * slots whenever possible. The grouping itself is preserved: all lines\n     * that currently share a scale continue to share one after compaction.\n     *\n     * Main chart:\n     *   right = candle/explicit Price axis\n     *   left  = first independent indicator group\n     *\n     * Lower pane:\n     *   right = first independent group\n     *   left  = second independent group\n     *\n     * Further groups retain/use custom overlay scale IDs and receive Chartix\n     * visible scale rails from refreshScalePresentation().\n     */\n    private rebalanceScaleSlots(\n        chart: IChartApi,\n    ): void {\n        const groups =\n            new Map<string, StoredLine[]>();\n\n        for (const stored of this.linesByKey.values()) {\n            if (stored.chart !== chart) {\n                continue;\n            }\n\n            const group =\n                groups.get(stored.priceScaleId)\n                ?? [];\n\n            group.push(stored);\n            groups.set(\n                stored.priceScaleId,\n                group,\n            );\n        }\n\n        if (groups.size === 0) {\n            this.refreshScalePresentation(chart);\n            return;\n        }\n\n        const reservedMainPriceGroup = (\n            chart === this.mainChart\n                ? groups.get(\"right\") ?? null\n                : null\n        );\n\n        const independentGroups =\n            [...groups.entries()].filter(\n                ([scaleId]) => !(\n                    chart === this.mainChart\n                    && scaleId === \"right\"\n                ),\n            );\n\n        const nativeSlots = (\n            chart === this.mainChart\n                ? [\"left\"]\n                : [\"right\", \"left\"]\n        );\n\n        independentGroups.forEach(\n            ([oldScaleId, lines], index) => {\n                let nextScaleId: string;\n\n                if (index < nativeSlots.length) {\n                    nextScaleId = nativeSlots[index];\n                } else if (\n                    oldScaleId !== \"left\"\n                    && oldScaleId !== \"right\"\n                ) {\n                    nextScaleId = oldScaleId;\n                } else {\n                    nextScaleId = this.createCustomScaleId();\n                }\n\n                if (oldScaleId === nextScaleId) {\n                    return;\n                }\n\n                for (const stored of lines) {\n                    stored.priceScaleId = nextScaleId;\n                    this.applyStoredScale(stored);\n                }\n            },\n        );\n\n        if (reservedMainPriceGroup) {\n            for (const stored of reservedMainPriceGroup) {\n                if (stored.priceScaleId !== \"right\") {\n                    stored.priceScaleId = \"right\";\n                    this.applyStoredScale(stored);\n                }\n            }\n        }\n\n        this.refreshScalePresentation(chart);\n    }\n\n\n    private chartHasIndicatorOnScale(\n        chart: IChartApi,\n        priceScaleId: string,\n        exclude?: StoredLine,\n    ): boolean {\n        for (const stored of this.linesByKey.values()) {\n            if (\n                stored === exclude\n                || stored.chart !== chart\n            ) {\n                continue;\n            }\n\n            if (\n                stored.priceScaleId\n                === priceScaleId\n            ) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n\n    private countLinesOnScale(\n        chart: IChartApi,\n        priceScaleId: string,\n    ): number {\n        let count = 0;\n\n        for (const stored of this.linesByKey.values()) {\n            if (\n                stored.chart === chart\n                && stored.priceScaleId\n                    === priceScaleId\n            ) {\n                count += 1;\n            }\n        }\n\n        return count;\n    }\n\n\n    /**\n     * Keep the two real Lightweight Charts axes visible only when they have a\n     * visible indicator group (the main chart's candle right axis is always\n     * visible). Every remaining custom overlay scale gets one Chartix rail.\n     */\n    private refreshScalePresentation(\n        chart: IChartApi,\n    ): void {\n        const groups =\n            new Map<string, VisibleScaleRailEntry>();\n\n        let leftVisible = false;\n        let rightVisible = (\n            chart === this.mainChart\n        );\n\n        for (const stored of this.linesByKey.values()) {\n            if (\n                stored.chart !== chart\n                || !stored.visible\n                || !stored.series\n            ) {\n                continue;\n            }\n\n            if (stored.priceScaleId === \"left\") {\n                leftVisible = true;\n                continue;\n            }\n\n            if (stored.priceScaleId === \"right\") {\n                rightVisible = true;\n                continue;\n            }\n\n            if (!groups.has(stored.priceScaleId)) {\n                groups.set(\n                    stored.priceScaleId,\n                    {\n                        scaleId:\n                            stored.priceScaleId,\n\n                        title:\n                            stored.spec.title,\n\n                        color:\n                            stored.spec.color\n                            ?? \"#2962ff\",\n\n                        series:\n                            stored.series,\n                    },\n                );\n            }\n        }\n\n        chart.applyOptions({\n            leftPriceScale: {\n                visible: leftVisible,\n            },\n\n            rightPriceScale: {\n                visible: rightVisible,\n            },\n        });\n\n        this.scaleRails.update(\n            chart,\n            [...groups.values()],\n        );\n    }\n\n\n    private enableAutoScale(\n        chart: IChartApi,\n    ): void {\n        /*\n         * Preserve the legacy behaviour for the primary right scale. Custom\n         * scale rails have their own manual/auto state and must not be reset\n         * merely because an unrelated indicator recalculated.\n         */\n        chart\n            .priceScale(\"right\")\n            .applyOptions({\n                autoScale: true,\n            });\n\n        this.refreshScalePresentation(chart);\n    }\n\n    private makeKey(\n        indicatorId: string,\n        plotId: string,\n        lineId: string,\n    ): string {\n        return (\n            `${indicatorId}:`\n            + `${plotId}:`\n            + `${lineId}`\n        );\n    }\n}\n","import type { Time } from \"lightweight-charts\";\nimport type { IndicatorBackgroundPoint } from \"./IndicatorContracts\";\n\ninterface ColorRun { start: number; end: number; color: string; }\nexport interface BackgroundRunIndex { times: Float64Array; runs: ColorRun[]; }\nexport function backgroundTime(time: Time): number {\n    return typeof time === \"number\" ? time : typeof time === \"string\" ? Date.parse(time) / 1000 : Date.UTC(time.year, time.month - 1, time.day) / 1000;\n}\nexport function indexBackground(points: readonly IndicatorBackgroundPoint[]): BackgroundRunIndex | null {\n    const times = new Float64Array(points.length);\n    const runs: ColorRun[] = [];\n    for (let i = 0; i < points.length; i++) {\n        times[i] = backgroundTime(points[i].time);\n        if (!Number.isFinite(times[i]) || (i > 0 && times[i] < times[i - 1])) return null;\n        const previous = runs[runs.length - 1];\n        if (previous?.color === points[i].color) previous.end = i + 1;\n        else runs.push({start:i,end:i + 1,color:points[i].color});\n    }\n    return {times,runs};\n}\nfunction lowerBound(values: Float64Array, value: number, upper = false): number {\n    let lo = 0, hi = values.length;\n    while (lo < hi) { const mid = (lo + hi) >>> 1; if (values[mid] < value || (upper && values[mid] === value)) lo = mid + 1; else hi = mid; }\n    return lo;\n}\nexport function visibleBackgroundRuns(index: BackgroundRunIndex, from: Time, to: Time): ColorRun[] {\n    const start = Math.max(0, lowerBound(index.times, backgroundTime(from)) - 1);\n    const end = Math.min(index.times.length, lowerBound(index.times, backgroundTime(to), true) + 1);\n    let lo = 0, hi = index.runs.length;\n    while (lo < hi) { const mid = (lo + hi) >>> 1; if (index.runs[mid].end <= start) lo = mid + 1; else hi = mid; }\n    const visible: ColorRun[] = [];\n    for (let i = lo; i < index.runs.length && index.runs[i].start < end; i++) {\n        const run = index.runs[i];\n        visible.push({start:Math.max(start,run.start),end:Math.min(end,run.end),color:run.color});\n    }\n    return visible;\n}\n","import { indexBackground, visibleBackgroundRuns, type BackgroundRunIndex } from \"./BackgroundRunIndex\";\nimport type {\n    IChartApi,\n} from \"lightweight-charts\";\n\nimport type {\n    IndicatorBackgroundSpec,\n} from \"./IndicatorContracts\";\n\n\nexport interface IndicatorBackgroundEntry {\n    key: string;\n    background: IndicatorBackgroundSpec;\n}\n\n\nexport interface IndicatorBackgroundTarget {\n    chart: IChartApi;\n    container: HTMLElement;\n    entries: IndicatorBackgroundEntry[];\n}\n\n\ninterface ChartBackgroundState {\n    chart: IChartApi;\n    container: HTMLElement;\n    canvas: HTMLCanvasElement;\n    entries: IndicatorBackgroundEntry[];\n    resizeObserver: ResizeObserver | null;\n    logicalRangeHandler: () => void;\n    sizeHandler: () => void;\n    drawFrame: number | null;\n}\n\n\n/**\n * Display-only indicator backgrounds.\n *\n * IMPORTANT ARCHITECTURE RULE:\n * This class is deliberately NOT owned or called by SeriesManager. The stable\n * series/pane move transaction must complete before this visual layer runs.\n * All public/event paths are fail-safe: a rendering problem may hide the tint,\n * but it must never interrupt pane cleanup, legend movement or viewport state.\n */\nexport class IndicatorBackgroundLayer {\n    private readonly indices = new WeakMap<IndicatorBackgroundSpec[\"data\"], BackgroundRunIndex | null>();\n    private readonly axisIndices = new WeakMap<IChartApi, WeakMap<IndicatorBackgroundSpec[\"data\"], {key:string;index:BackgroundRunIndex}>>();\n    private readonly states =\n        new Map<IChartApi, ChartBackgroundState>();\n\n\n    /**\n     * Synchronize the complete set of live chart backgrounds.\n     * This method is safe to call from requestAnimationFrame after Chartix core\n     * state has already settled.\n     */\n    public sync(\n        targets: IndicatorBackgroundTarget[],\n    ): void {\n        try {\n            const liveCharts = new Set<IChartApi>();\n\n            for (const target of targets) {\n                if (!target.entries.length) continue;\n                liveCharts.add(target.chart);\n\n                try {\n                    const state = this.ensureState(\n                        target.chart,\n                        target.container,\n                    );\n\n                    state.container = target.container;\n                    state.entries = target.entries;\n                    this.axisIndices.delete(target.chart);\n                    this.requestDraw(state);\n                } catch (error) {\n                    console.warn(\n                        \"[Chartix background] target refresh failed; core chart state is unaffected.\",\n                        error,\n                    );\n                }\n            }\n\n            for (\n                const chart\n                of [...this.states.keys()]\n            ) {\n                if (!liveCharts.has(chart)) {\n                    this.disposeState(chart);\n                }\n            }\n        } catch (error) {\n            console.warn(\n                \"[Chartix background] refresh failed; core chart state is unaffected.\",\n                error,\n            );\n        }\n    }\n\n\n    public destroy(): void {\n        for (const chart of [...this.states.keys()]) {\n            this.disposeState(chart);\n        }\n    }\n\n\n    private ensureState(\n        chart: IChartApi,\n        container: HTMLElement,\n    ): ChartBackgroundState {\n        const existing = this.states.get(chart);\n\n        if (existing) {\n            if (\n                existing.container !== container\n                || existing.canvas.parentElement !== container\n            ) {\n                existing.container = container;\n                container.appendChild(existing.canvas);\n            }\n\n            return existing;\n        }\n\n        const canvas = document.createElement(\"canvas\");\n        canvas.className = \"chartix-indicator-background-layer\";\n        canvas.setAttribute(\"aria-hidden\", \"true\");\n\n        Object.assign(canvas.style, {\n            position: \"absolute\",\n            pointerEvents: \"none\",\n            zIndex: \"2\",\n            left: \"0\",\n            top: \"0\",\n            width: \"0\",\n            height: \"0\",\n        });\n\n        if (\n            window.getComputedStyle(container).position\n            === \"static\"\n        ) {\n            container.style.position = \"relative\";\n        }\n\n        container.appendChild(canvas);\n\n        const state: ChartBackgroundState = {\n            chart,\n            container,\n            canvas,\n            entries: [],\n            resizeObserver: null,\n            logicalRangeHandler: () => {},\n            sizeHandler: () => {},\n            drawFrame: null,\n        };\n\n        state.logicalRangeHandler = () => {\n            this.requestDraw(state);\n        };\n\n        state.sizeHandler = () => {\n            this.requestDraw(state);\n        };\n\n        const timeScale = chart.timeScale();\n\n        try {\n            timeScale.subscribeVisibleLogicalRangeChange(\n                state.logicalRangeHandler,\n            );\n        } catch (error) {\n            console.warn(\n                \"[Chartix background] logical-range subscription unavailable.\",\n                error,\n            );\n        }\n\n        /*\n         * Some Lightweight Charts builds expose subscribeSizeChange and some\n         * older local typings/builds do not. Feature-detect at runtime so the\n         * optional background can never break the chart.\n         */\n        const optionalTimeScale = timeScale as typeof timeScale & {\n            subscribeSizeChange?: (handler: () => void) => void;\n        };\n\n        try {\n            optionalTimeScale.subscribeSizeChange?.(\n                state.sizeHandler,\n            );\n        } catch (error) {\n            console.warn(\n                \"[Chartix background] size subscription unavailable.\",\n                error,\n            );\n        }\n\n        if (typeof ResizeObserver !== \"undefined\") {\n            try {\n                state.resizeObserver = new ResizeObserver(\n                    () => this.requestDraw(state),\n                );\n\n                state.resizeObserver.observe(container);\n            } catch (error) {\n                console.warn(\n                    \"[Chartix background] ResizeObserver unavailable.\",\n                    error,\n                );\n            }\n        }\n\n        this.states.set(chart, state);\n        return state;\n    }\n\n\n    private disposeState(chart: IChartApi): void {\n        const state = this.states.get(chart);\n\n        if (!state) {\n            return;\n        }\n\n        if (state.drawFrame !== null) {\n            window.cancelAnimationFrame(state.drawFrame);\n            state.drawFrame = null;\n        }\n\n        try {\n            chart\n                .timeScale()\n                .unsubscribeVisibleLogicalRangeChange(\n                    state.logicalRangeHandler,\n                );\n        } catch {\n            // Optional visual layer: teardown must never break pane removal.\n        }\n\n        const timeScale = chart.timeScale() as ReturnType<IChartApi[\"timeScale\"]> & {\n            unsubscribeSizeChange?: (handler: () => void) => void;\n        };\n\n        try {\n            timeScale.unsubscribeSizeChange?.(\n                state.sizeHandler,\n            );\n        } catch {\n            // Ignore optional API differences.\n        }\n\n        try {\n            state.resizeObserver?.disconnect();\n        } catch {\n            // Ignore teardown-only errors.\n        }\n\n        try {\n            state.canvas.remove();\n        } catch {\n            // Pane may already have been removed from the DOM.\n        }\n\n        this.states.delete(chart);\n    }\n\n\n    private requestDraw(\n        state: ChartBackgroundState,\n    ): void {\n        if (state.drawFrame !== null) {\n            return;\n        }\n\n        state.drawFrame = window.requestAnimationFrame(\n            () => {\n                state.drawFrame = null;\n\n                try {\n                    this.draw(state);\n                } catch (error) {\n                    console.warn(\n                        \"[Chartix background] draw failed; core chart state is unaffected.\",\n                        error,\n                    );\n                }\n            },\n        );\n    }\n\n\n    private draw(state: ChartBackgroundState): void {\n        const {\n            chart,\n            container,\n            canvas,\n            entries,\n        } = state;\n\n        if (!container.isConnected || container.clientWidth <= 0 || container.clientHeight <= 0) {\n            return;\n        }\n\n        const timeScale = chart.timeScale();\n        const plotWidth = Math.max(\n            0,\n            timeScale.width(),\n        );\n\n        const plotHeight = Math.max(\n            0,\n            container.clientHeight\n                - timeScale.height(),\n        );\n\n        let leftOffset = 0;\n\n        try {\n            leftOffset = Math.max(\n                0,\n                chart.priceScale(\"left\").width(),\n            );\n        } catch {\n            leftOffset = 0;\n        }\n\n        if (canvas.style.left !== `${leftOffset}px`) canvas.style.left = `${leftOffset}px`;\n        if (canvas.style.width !== `${plotWidth}px`) canvas.style.width = `${plotWidth}px`;\n        if (canvas.style.height !== `${plotHeight}px`) canvas.style.height = `${plotHeight}px`;\n\n        const dpr = Math.max(\n            1,\n            window.devicePixelRatio || 1,\n        );\n\n        const physicalWidth = Math.max(\n            1,\n            Math.round(plotWidth * dpr),\n        );\n\n        const physicalHeight = Math.max(\n            1,\n            Math.round(plotHeight * dpr),\n        );\n\n        if (\n            canvas.width !== physicalWidth\n            || canvas.height !== physicalHeight\n        ) {\n            canvas.width = physicalWidth;\n            canvas.height = physicalHeight;\n        }\n\n        const context = canvas.getContext(\"2d\");\n\n        if (!context) {\n            return;\n        }\n\n        context.setTransform(\n            dpr,\n            0,\n            0,\n            dpr,\n            0,\n            0,\n        );\n\n        context.clearRect(\n            0,\n            0,\n            plotWidth,\n            plotHeight,\n        );\n\n        if (\n            plotWidth <= 0\n            || plotHeight <= 0\n            || entries.length === 0\n        ) {\n            return;\n        }\n\n        for (const entry of entries) {\n            this.drawEntry(\n                context,\n                chart,\n                entry,\n                plotWidth,\n                plotHeight,\n            );\n        }\n    }\n\n\n    private indexOnAxis(chart: IChartApi, points: IndicatorBackgroundSpec[\"data\"], index: BackgroundRunIndex): BackgroundRunIndex {\n        const scale = chart.timeScale();\n        if (typeof scale.timeToIndex !== \"function\") return index;\n        const first = points[0].time, last = points[points.length - 1].time;\n        // These bounds also change when replay removes/restores future times.\n        const key = [scale.timeToIndex(first),scale.timeToIndex(last),scale.timeToIndex(first,true),scale.timeToIndex(last,true)].join(\":\");\n        let cache = this.axisIndices.get(chart);\n        if (!cache) { cache = new WeakMap(); this.axisIndices.set(chart,cache); }\n        const cached = cache.get(points); if (cached?.key === key) return cached.index;\n        const runs: BackgroundRunIndex[\"runs\"] = [];\n        // Do this once per axis/data version, not during every pan. Unknown\n        // timestamps split runs so merged shading cannot bridge missing cells.\n        for (const source of index.runs) {\n            let start = -1;\n            for (let i = source.start; i < source.end; i++) {\n                const exists = scale.timeToIndex(points[i].time) !== null;\n                if (exists && start < 0) start = i;\n                if (!exists && start >= 0) { runs.push({start,end:i,color:source.color}); start = -1; }\n            }\n            if (start >= 0) runs.push({start,end:source.end,color:source.color});\n        }\n        const projected = {times:index.times,runs}; cache.set(points,{key,index:projected});\n        return projected;\n    }\n\n    private drawEntry(\n        context: CanvasRenderingContext2D,\n        chart: IChartApi,\n        entry: IndicatorBackgroundEntry,\n        plotWidth: number,\n        plotHeight: number,\n    ): void {\n        const points = entry.background.data;\n        if (!points.length) return;\n        let indexed = this.indices.get(points);\n        if (indexed === undefined) {\n            indexed = indexBackground(points);\n            this.indices.set(points, indexed);\n        }\n        if (!indexed) {\n            this.drawEntryRaw(context, chart, entry, plotWidth, plotHeight);\n            return;\n        }\n        const scale = chart.timeScale(), visible = scale.getVisibleRange();\n        if (!visible) return;\n        const runs = visibleBackgroundRuns(this.indexOnAxis(chart,points,indexed), visible.from, visible.to);\n        const coordinates = new Map<number, number | null>();\n        const x = (i: number): number | null => {\n            if (i < 0 || i >= points.length) return null;\n            if (!coordinates.has(i)) coordinates.set(i, scale.timeToCoordinate(points[i].time));\n            return coordinates.get(i) ?? null;\n        };\n        const cell = (i: number): {left:number;right:number} | null => {\n            const center = x(i); if (center === null) return null;\n            const previous = x(i - 1), next = x(i + 1);\n            return {\n                left: previous !== null ? (previous + center) / 2 : next !== null ? center - (next - center) / 2 : center - .5,\n                right: next !== null ? (center + next) / 2 : previous !== null ? center + (center - previous) / 2 : center + .5,\n            };\n        };\n        const paint = (color: string, left: number, right: number): void => {\n            left = Math.max(0, Math.min(plotWidth,left)); right = Math.max(0, Math.min(plotWidth,right));\n            if (right <= left) return;\n            context.fillStyle = color;\n            context.fillRect(left,0,right - left,plotHeight);\n        };\n        context.save(); context.globalAlpha = this.clampOpacity(entry.background.opacity ?? .12);\n        for (const run of runs) {\n            const first = cell(run.start), last = cell(run.end - 1);\n            if (first && last) paint(run.color,first.left,last.right);\n            else {\n                // Warm-up/shifted timestamps can lie outside this chart's axis.\n                // Preserve the existing per-cell fallback for such edge runs.\n                for (let i = run.start; i < run.end; i++) {\n                    const bounds = cell(i); if (bounds) paint(run.color,bounds.left,bounds.right);\n                }\n            }\n        }\n        context.restore();\n    }\n\n    private drawEntryRaw(\n        context: CanvasRenderingContext2D,\n        chart: IChartApi,\n        entry: IndicatorBackgroundEntry,\n        plotWidth: number,\n        plotHeight: number,\n    ): void {\n        const points = entry.background.data;\n\n        if (points.length === 0) {\n            return;\n        }\n\n        const opacity = this.clampOpacity(\n            entry.background.opacity ?? 0.12,\n        );\n\n        const coordinates = points.map(\n            (point) => ({\n                point,\n                x: chart\n                    .timeScale()\n                    .timeToCoordinate(point.time),\n            }),\n        );\n\n        context.save();\n        context.globalAlpha = opacity;\n\n        for (\n            let index = 0;\n            index < coordinates.length;\n            index += 1\n        ) {\n            const current = coordinates[index];\n\n            if (current.x === null) {\n                continue;\n            }\n\n            const previous = (\n                index > 0\n                    ? coordinates[index - 1]\n                    : null\n            );\n\n            const next = (\n                index + 1 < coordinates.length\n                    ? coordinates[index + 1]\n                    : null\n            );\n\n            const previousX = previous?.x ?? null;\n            const nextX = next?.x ?? null;\n\n            let left: number;\n            let right: number;\n\n            if (previousX !== null) {\n                left = (\n                    previousX + current.x\n                ) / 2;\n            } else if (nextX !== null) {\n                left = current.x\n                    - (nextX - current.x) / 2;\n            } else {\n                left = current.x - 0.5;\n            }\n\n            if (nextX !== null) {\n                right = (\n                    current.x + nextX\n                ) / 2;\n            } else if (previousX !== null) {\n                right = current.x\n                    + (current.x - previousX) / 2;\n            } else {\n                right = current.x + 0.5;\n            }\n\n            const clippedLeft = Math.max(\n                0,\n                Math.min(plotWidth, left),\n            );\n\n            const clippedRight = Math.max(\n                0,\n                Math.min(plotWidth, right),\n            );\n\n            if (clippedRight <= clippedLeft) {\n                continue;\n            }\n\n            context.fillStyle = current.point.color;\n            context.fillRect(\n                clippedLeft,\n                0,\n                clippedRight - clippedLeft,\n                plotHeight,\n            );\n        }\n\n        context.restore();\n    }\n\n\n    private clampOpacity(value: number): number {\n        if (!Number.isFinite(value)) {\n            return 0.12;\n        }\n\n        return Math.min(\n            1,\n            Math.max(0, value),\n        );\n    }\n}\n","import { isScriptIndicator, isScriptPreview } from \"../zero/ScriptLibrary\";\nimport { runScript, type CompiledScript } from \"../zero/wasm\";\nimport { toolIcon } from \"./workspace/ToolIcons\";\nimport { defaultAppearance, appearanceOptions, candleAppearanceOptions, type AppearanceOverrides, type ChartPalette } from \"./ChartAppearance.ts\";\nimport { ChartAppearancePanel } from \"./ChartAppearancePanel\";\nimport { DENSE_CHART_OPTIONS } from \"./DenseChartOptions\";\nimport {\n    CandlestickSeries,\n    createChart,\n    type IChartApi,\n    type ISeriesApi,\n    type MouseEventParams,\n    type Time,\n} from \"lightweight-charts\";\n\nimport {\n    ChartApi,\n    chartTime,\n    type Candle,\n    type DataUrlBuilder,\n} from \"./ChartApi\";\n\nimport { Watchlist } from \"./Watchlist\";\nimport { ContextMenu } from \"./ContextMenu\";\nimport { Replay } from \"./Replay\";\nimport { IndicatorPane } from \"./IndicatorPane\";\n\nimport {\n    LabApi,\n    type IndicatorUrlBuilder,\n} from \"./LabApi\";\n\nimport { IndicatorControls } from \"./IndicatorControls\";\nimport {\n    IndicatorLineLegend,\n    type IndicatorLineLegendItem,\n    type IndicatorLineScaleOption,\n} from \"./IndicatorLineLegend\";\nimport { SeriesManager } from \"./SeriesManager\";\nimport {\n    IndicatorBackgroundLayer,\n    type IndicatorBackgroundEntry,\n    type IndicatorBackgroundTarget,\n} from \"./IndicatorBackgroundLayer\";\n\nimport type {\n    IndicatorParameterSpec,\n    IndicatorParameterValue,\n    IndicatorPlotSpec,\n    IndicatorPriceSourceField,\n    IndicatorRecipe,\n    IndicatorResponse,\n    IndicatorSourceRecipe,\n} from \"./IndicatorContracts\";\n\n\ntype CandleSeriesApi = ISeriesApi<\"Candlestick\">;\n\n\nconst CHART_BAR_LIMIT = 20_000;\nconst SOURCE_PARAMETER_ID = \"__source__\";\n\nconst OWN_SCALE_VALUE = \"__own_scale__\";\nconst PRICE_SCALE_VALUE = \"__price_scale__\";\n\nconst MAIN_PANE_KEY = \"__main_chart__\";\nconst TIME_AXIS_RESTORE_ZONE_PX = 36;\nconst MINIMIZED_PANE_HEIGHT = 42;\n\n\nexport interface ChartAppOptions {\n    chartContainerId: string;\n    indicatorContainerId: string;\n    separatorId: string;\n\n    tickerInputId: string;\n    timeframeSelectId: string;\n\n    themeToggleId: string;\n\n    barReplayButtonId: string;\n    replayControlsId: string;\n    previousBarButtonId: string;\n    nextBarButtonId: string;\n    exitReplayButtonId: string;\n    currentBarNumberId: string;\n    totalBarNumberId: string;\n\n    watchlistItemsId: string;\n\n    indicatorTitleId: string;\n    indicatorControlsContainerId: string;\n    applyIndicatorButtonId: string;\n    clearIndicatorButtonId: string;\n    indicatorLiveInputId: string;\n\n    dataUrlBuilder: DataUrlBuilder;\n    indicatorUrlBuilder: IndicatorUrlBuilder;\n    loadScript?: (id: string) => Promise<CompiledScript>;\n    initialSymbol?: string;\n    initialTimeframe?: string;\n    onWatchlistSelect?: (symbol: string) => void;\n    onRemoveAllObjects?: () => void;\n    onSelectPalette?: (palette: ChartPalette) => void;\n}\n\nexport interface ChartTemplateState {\n    appearance?: AppearanceOverrides;\n    symbol: string;\n    timeframe: string;\n    indicators: Array<{\n        instanceId: string;\n        indicatorId: string;\n        params?: Record<string, IndicatorParameterValue>;\n        source: IndicatorSourceSelection;\n    }>;\n}\n\n\nfunction requireElement<T extends HTMLElement>(\n    id: string,\n): T {\n    const element = document.getElementById(id);\n\n    if (!element) {\n        throw new Error(\n            `Missing required element: #${id}`,\n        );\n    }\n\n    return element as T;\n}\n\n\nfunction isAbortError(\n    error: unknown,\n): boolean {\n    return (\n        error instanceof DOMException &&\n        error.name === \"AbortError\"\n    );\n}\n\n\ninterface IndicatorPaneSlot {\n    pane: IndicatorPane;\n    container: HTMLDivElement;\n    separator: HTMLElement;\n    usesPrimaryDom: boolean;\n    minimized: boolean;\n}\n\n\ninterface SharedCursorTarget {\n    line: HTMLDivElement;\n\n    handler: (\n        param: MouseEventParams<Time>,\n    ) => void;\n}\n\n\ninterface DraggedIndicatorLine {\n    instanceId: string;\n    plotId: string;\n    lineId: string;\n    title: string;\n}\n\n\ninterface IndicatorLineScaleTarget {\n    instanceId: string;\n    plotId: string;\n    lineId: string;\n}\n\n\ntype IndicatorSourceSelection =\n    | {\n        kind: \"price\";\n        field: IndicatorPriceSourceField;\n    }\n    | {\n        kind: \"indicator\";\n        instanceId: string;\n        plotId: string;\n        lineId: string;\n    };\n\n\ninterface IndicatorInstanceState {\n    instanceId: string;\n    indicatorId: string;\n    title: string;\n    source: IndicatorSourceSelection;\n    params?: Record<string, IndicatorParameterValue>;\n    parameters: IndicatorParameterSpec[];\n    plots: IndicatorPlotSpec[];\n    barColors?: IndicatorResponse[\"barColors\"];\n    pane: boolean;\n    loaded: boolean;\n}\n\n\nexport class ChartApp {\n    private readonly options: ChartAppOptions;\n\n    private readonly api: ChartApi;\n    private readonly labApi: LabApi;\n    private readonly scriptBarColors = new Map<number, string>();\n\n    private chartContainer!: HTMLDivElement;\n    private indicatorContainer!: HTMLDivElement;\n    private separator!: HTMLElement;\n    private chartStack!: HTMLDivElement;\n\n    private tickerInput!: HTMLInputElement;\n    private timeframeSelect!: HTMLSelectElement;\n    private themeToggle!: HTMLButtonElement;\n\n    private indicatorTitle!: HTMLElement;\n    private indicatorControlsContainer!: HTMLElement;\n\n    private applyIndicatorButton!: HTMLButtonElement;\n    private clearIndicatorButton!: HTMLButtonElement;\n    private indicatorLiveInput!: HTMLInputElement;\n\n    private chart!: IChartApi;\n    private candleSeries!: CandleSeriesApi;\n\n    private replay!: Replay;\n    private watchlist: Watchlist | null = null;\n    private contextMenu!: ContextMenu;\n\n    private indicatorControls!: IndicatorControls;\n    private readonly indicatorLineLegends =\n        new Map<HTMLElement, IndicatorLineLegend>();\n    private seriesManager!: SeriesManager;\n\n    /*\n     * Background rendering is deliberately outside SeriesManager. It runs only\n     * after the stable v7 pane/legend transaction has completed.\n     */\n    private readonly indicatorBackgroundLayer =\n        new IndicatorBackgroundLayer();\n\n    private indicatorBackgroundFrame: number | null = null;\n\n    private readonly panesByIndicator =\n        new Map<string, IndicatorPaneSlot>();\n\n    private readonly paneOrder: string[] = [];\n\n    private readonly sharedCursorTargets =\n        new Map<IChartApi, SharedCursorTarget>();\n\n    private readonly lineDropTargetCharts =\n        new Map<HTMLElement, IChartApi>();\n\n    private readonly lineDropTargetBound =\n        new WeakSet<HTMLElement>();\n\n    private fullscreenPaneKey: string | null = null;\n    private lowerPanesHidden = false;\n    private mainPaneMinimized = false;\n\n    private draggedIndicatorLine:\n        DraggedIndicatorLine | null = null;\n\n    private candles: Candle[] = [];\n\n    private activeSymbol = \"\";\n    private loadedTimeframe = \"\";\n    private appearance: AppearanceOverrides = {};\n    private palette?: ChartPalette;\n    private appearancePanel: ChartAppearancePanel | null = null;\n    private activeTheme: \"light\" | \"dark\" = \"light\";\n\n    /*\n     * There is deliberately no default indicator.\n     *\n     * It remains null until the user selects an item from\n     * the indicator catalog.\n     */\n    private activeIndicatorId: string | null = null;\n    private activeIndicatorInstanceId: string | null = null;\n\n    private indicatorInstanceSerial = 0;\n\n    private readonly indicatorInstances =\n        new Map<string, IndicatorInstanceState>();\n\n    /*\n     * True after the backend has returned the selected\n     * indicator's parameter schema.\n     */\n    private indicatorReady = false;\n    private indicatorBusy = false;\n\n    private typingBox!: HTMLDivElement;\n    private typingBuffer = \"\";\n    private isTyping = false;\n\n    private indicatorTimer: number | null = null;\n\n    private indicatorAbortController:\n        AbortController | null = null;\n\n    private indicatorRequestVersion = 0;\n    private previewError?: string;\n    private symbolRequestVersion = 0;\n    private symbolLoading = false;\n    private lastStackWidth = -1;\n    private lastStackHeight = -1;\n\n\n    constructor(options: ChartAppOptions) {\n        this.options = options;\n\n        this.api = new ChartApi(\n            options.dataUrlBuilder,\n        );\n\n        this.labApi = new LabApi(\n            options.indicatorUrlBuilder,\n        );\n    }\n\n\n    public mount(autoLoad = true): void {\n        console.info(\n            \"[Chartix] prebg-core-safe-background-v13\",\n        );\n\n        this.collectElements();\n        this.installIndicatorEnhancementStyles();\n\n        this.createChart();\n        this.createIndicatorPane();\n        this.createIndicatorControls();\n\n        this.showNoIndicatorSelected();\n\n        this.createTypingOverlay();\n        this.createControllers();\n        this.bindEvents();\n\n        this.tickerInput.value = this.options.initialSymbol || this.tickerInput.value;\n        this.timeframeSelect.value = this.options.initialTimeframe || this.timeframeSelect.value;\n\n        const initialSymbol = (\n            this.tickerInput.value.trim().toUpperCase()\n            || \"EURUSD\"\n        );\n\n        if (autoLoad) void this.loadSymbol(initialSymbol);\n\n        this.watchlist?.mount();\n        this.applyAppearance();\n    }\n\n\n    public async loadSymbol(\n        symbol: string,\n    ): Promise<boolean> {\n        const cleanSymbol = (\n            symbol.trim().toUpperCase()\n        );\n\n        if (!cleanSymbol) {\n            return false;\n        }\n\n        const requestVersion =\n            ++this.symbolRequestVersion;\n\n        this.cancelIndicatorRequest();\n        this.symbolLoading = true;\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:loading\", { bubbles: true }));\n\n        try {\n            const timeframe =\n                this.timeframeSelect.value;\n\n            const data =\n                await this.api.fetchCandles(\n                    cleanSymbol,\n                    timeframe,\n                    CHART_BAR_LIMIT,\n                );\n\n            if (\n                requestVersion !==\n                this.symbolRequestVersion\n            ) {\n                return false;\n            }\n\n            this.activeSymbol = cleanSymbol;\n            this.loadedTimeframe = timeframe;\n            this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:data\", {\n                bubbles: true, detail: { symbol: cleanSymbol, timeframe },\n            }));\n            this.tickerInput.value = cleanSymbol;\n            this.candles = data;\n            this.scriptBarColors.clear();\n            for (const instance of this.indicatorInstances.values()) instance.barColors = undefined;\n\n            this.replay.exit(false);\n            this.replay.setData(data);\n\n            this.candleSeries.setData(\n                data,\n            );\n\n            this.seriesManager.setTimeAnchor(\n                data.map(\n                    (bar) => bar.time,\n                ),\n            );\n\n            this.seriesManager.clearAllIndicators();\n            this.seriesManager.setReplayTime(undefined);\n            this.clearAllIndicatorPanes();\n\n            this.chart.timeScale().fitContent();\n\n            /*\n             * The applied-indicator graph survives symbol/timeframe changes.\n             * Recalculate every instance in dependency order so parent lines\n             * exist before children are rendered again. Stored parameters and\n             * source links are preserved.\n             */\n            if (this.indicatorInstances.size > 0) {\n                this.indicatorReady = false;\n\n                this.showIndicatorLoading(\n                    \"Recalculating indicator graph…\",\n                );\n\n                await this.recalculateAllIndicatorInstances();\n            } else {\n                this.showNoIndicatorSelected();\n            }\n\n            this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:ready\", { bubbles: true }));\n            console.log(\n                `Chart updated: ${cleanSymbol}, ` +\n                `${data.length} bars`,\n            );\n            return true;\n        } catch (error) {\n            if (!isAbortError(error)) {\n                console.error(\n                    \"Error loading symbol:\",\n                    error,\n                );\n            }\n            if (this.activeSymbol) this.tickerInput.value = this.activeSymbol;\n            if (this.loadedTimeframe) this.timeframeSelect.value = this.loadedTimeframe;\n            this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:error\", {\n                bubbles: true, detail: error instanceof Error ? error.message : \"Unable to load chart data.\",\n            }));\n            return false;\n        } finally {\n            if (requestVersion === this.symbolRequestVersion) this.symbolLoading = false;\n            this.syncIndicatorActionState();\n        }\n    }\n\n\n    public async setActiveIndicator(\n        indicatorId: string,\n    ): Promise<void> {\n        const cleanId = indicatorId.trim();\n\n        if (!cleanId) {\n            return;\n        }\n\n        if (isScriptIndicator(cleanId) && !isScriptPreview(cleanId)) this.discardScriptPreview();\n\n        /*\n         * An indicator definition and an indicator instance are different\n         * things.  Each catalogue click creates a new instance so chains such\n         * as Blackman -> Blackman -> RSI can coexist without overwriting the\n         * earlier Blackman.\n         */\n        this.cancelIndicatorRequest();\n\n        const instanceId =\n            `${cleanId}#${++this.indicatorInstanceSerial}`;\n\n        this.indicatorInstances.set(\n            instanceId,\n            {\n                instanceId,\n                indicatorId: cleanId,\n                title: cleanId,\n                source: {\n                    kind: \"price\",\n                    field: \"close\",\n                },\n                parameters: [],\n                plots: [],\n                pane: true,\n                loaded: false,\n            },\n        );\n\n        this.activeIndicatorId = cleanId;\n        this.activeIndicatorInstanceId = instanceId;\n        this.indicatorReady = false;\n\n        this.indicatorTitle.textContent =\n            \"Loading indicator…\";\n\n        if (this.candles.length === 0) {\n            this.showIndicatorMessage(\n                \"Waiting for chart data…\",\n            );\n\n            this.syncIndicatorActionState();\n            return;\n        }\n\n        this.showIndicatorLoading(\n            \"Loading default settings…\",\n        );\n\n        await this.runIndicator(\n            true,\n        );\n    }\n\n\n    private discardScriptPreview(): void {\n        const preview = [...this.indicatorInstances.values()].find(item => isScriptPreview(item.indicatorId));\n        if (preview) this.removeIndicatorInstance(preview.instanceId);\n    }\n\n    public async previewScript(id: string): Promise<void> {\n        this.previewError = undefined;\n        this.discardScriptPreview();\n        const instanceId = `${id}#${this.indicatorInstanceSerial + 1}`;\n        await this.setActiveIndicator(id);\n        const loaded = this.indicatorInstances.get(instanceId)?.loaded ?? false;\n        if (!loaded) {\n            this.removeIndicatorInstance(instanceId);\n            throw new Error(this.previewError ?? \"Preview was interrupted. Run it again when the chart is ready.\");\n        }\n    }\n\n    public isWorking(): boolean { return this.indicatorBusy || this.symbolLoading; }\n    public getChart(): IChartApi { return this.chart; }\n    public getCandleSeries(): CandleSeriesApi { return this.candleSeries; }\n    public getCandles(): readonly Candle[] { return this.candles; }\n    public isReplaying(): boolean { return this.replay.isReplaying(); }\n    public getContainer(): HTMLDivElement { return this.chartContainer; }\n    public resize(): void {\n        const width = this.chartStack.clientWidth, height = this.chartStack.clientHeight;\n        if (width <= 0 || height <= 0 || (width === this.lastStackWidth && height === this.lastStackHeight)) return;\n        this.lastStackWidth = width; this.lastStackHeight = height;\n        this.rebalancePaneHeights();\n    }\n    private notify(message: string): void {\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:notice\", { bubbles: true, detail: message }));\n    }\n    public setTheme(theme: \"light\" | \"dark\", palette?: ChartPalette, resetColors = false): void {\n        if (this.activeTheme === theme && this.palette === palette && !resetColors) return;\n        this.activeTheme = theme;\n        this.palette = palette;\n        if (resetColors && palette) {\n            for (const key of Object.keys(palette.colors) as Array<keyof AppearanceOverrides>) delete this.appearance[key];\n        }\n        this.applyAppearance();\n    }\n    public openAppearanceSettings(): void {\n        this.appearancePanel ??= new ChartAppearancePanel(\n            () => this.defaultChartAppearance(),\n            () => this.appearance,\n            value => {\n                this.appearance = { ...value }; this.applyAppearance();\n                this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:state\", { bubbles: true }));\n            },\n            () => this.palette,\n            palette => {\n                if (this.options.onSelectPalette) this.options.onSelectPalette(palette);\n                else this.setTheme(palette.scheme, palette, true);\n            },\n        );\n        this.appearancePanel.open(this.activeSymbol || this.tickerInput.value || \"Chart\");\n    }\n    private defaultChartAppearance() {\n        return { ...defaultAppearance(this.activeTheme), ...this.palette?.colors };\n    }\n    private applyAppearance(): void {\n        const resolved = { ...this.defaultChartAppearance(), ...this.appearance };\n        const options = appearanceOptions(resolved, this.palette?.shell[3]);\n        this.chart.applyOptions(options);\n        this.candleSeries.applyOptions(candleAppearanceOptions(resolved));\n        for (const slot of this.panesByIndicator.values()) slot.pane.chart.applyOptions(options);\n    }\n    public getTemplateState(): ChartTemplateState {\n        return {\n            appearance: { ...this.appearance },\n            symbol: this.activeSymbol || this.tickerInput.value,\n            timeframe: this.loadedTimeframe || this.timeframeSelect.value,\n            indicators: this.getIndicatorTopologicalOrder().filter(id => !isScriptPreview(this.indicatorInstances.get(id)!.indicatorId)).map(id => {\n                const instance = this.indicatorInstances.get(id)!;\n                return {\n                    instanceId: id, indicatorId: instance.indicatorId,\n                    params: instance.params ? { ...instance.params } : undefined,\n                    source: { ...instance.source },\n                };\n            }),\n        };\n    }\n    public async restoreTemplateState(state: ChartTemplateState): Promise<boolean> {\n        // Fetch first: a missing dataset must not erase the existing indicator graph.\n        const previousTimeframe = this.loadedTimeframe || this.timeframeSelect.value;\n        this.timeframeSelect.value = state.timeframe;\n        const previousGraph = new Map(this.indicatorInstances);\n        this.indicatorInstances.clear();\n        const loaded = await this.loadSymbol(state.symbol);\n        if (!loaded) {\n            this.timeframeSelect.value = previousTimeframe;\n            for (const [id, value] of previousGraph) this.indicatorInstances.set(id, value);\n            return false;\n        }\n        this.appearance = { ...state.appearance }; this.applyAppearance();\n        this.cancelIndicatorRequest();\n        this.activeIndicatorId = null;\n        this.activeIndicatorInstanceId = null;\n        for (const item of state.indicators) {\n            this.indicatorInstances.set(item.instanceId, {\n                ...item, source: { ...item.source }, title: item.indicatorId,\n                parameters: [], plots: [], pane: true, loaded: false,\n            });\n            const serial = Number(item.instanceId.split(\"#\").pop());\n            if (Number.isFinite(serial)) this.indicatorInstanceSerial = Math.max(this.indicatorInstanceSerial, serial);\n        }\n        const last = state.indicators[state.indicators.length - 1];\n        if (last) {\n            this.activeIndicatorId = last.indicatorId;\n            this.activeIndicatorInstanceId = last.instanceId;\n            await this.recalculateAllIndicatorInstances();\n        } else this.showNoIndicatorSelected();\n        return [...this.indicatorInstances.values()].every(item => item.loaded);\n    }\n\n\n    public exportCsv(): void {\n        if (this.candles.length === 0) {\n            this.notify(\n                \"No chart data to export.\",\n            );\n\n            return;\n        }\n\n        const csv = [\n            \"time,open,high,low,close\",\n\n            ...this.candles.map(\n                (bar) => {\n                    return (\n                        `${JSON.stringify(bar.time)},` +\n                        `${bar.open},` +\n                        `${bar.high},` +\n                        `${bar.low},` +\n                        `${bar.close}`\n                    );\n                },\n            ),\n        ].join(\"\\n\");\n\n        const blob = new Blob(\n            [csv],\n            {\n                type: \"text/csv\",\n            },\n        );\n\n        const url =\n            URL.createObjectURL(blob);\n\n        const link =\n            document.createElement(\"a\");\n\n        link.href = url;\n\n        link.download = (\n            `${this.activeSymbol || \"chart\"}_data.csv`\n        );\n\n        link.click();\n\n        URL.revokeObjectURL(url);\n    }\n\n\n    private exportIndicatorInstanceCsv(\n        instanceId: string,\n    ): void {\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance || !instance.loaded) {\n            this.notify(\n                \"This indicator has no calculated result to export yet.\",\n            );\n            return;\n        }\n\n        const columns: Array<{\n            name: string;\n            data: IndicatorPlotSpec[\"lines\"][number][\"data\"];\n        }> = [];\n\n        const usedNames = new Set<string>();\n\n        for (const plot of instance.plots) {\n            for (const line of plot.lines) {\n                const baseName = (\n                    plot.id === line.id\n                        ? line.id\n                        : `${plot.id}.${line.id}`\n                );\n\n                let columnName = baseName;\n                let suffix = 2;\n\n                while (usedNames.has(columnName)) {\n                    columnName = `${baseName}_${suffix}`;\n                    suffix += 1;\n                }\n\n                usedNames.add(columnName);\n                columns.push({\n                    name: columnName,\n                    data: this.seriesManager.displayedData(line),\n                });\n            }\n        }\n\n        if (columns.length === 0) {\n            this.notify(\n                \"This indicator returned no lines to export.\",\n            );\n            return;\n        }\n\n        type CsvRow = {\n            time: unknown;\n            values: Map<string, unknown>;\n            firstSeen: number;\n        };\n\n        const rows = new Map<string, CsvRow>();\n        let firstSeen = 0;\n\n        for (const column of columns) {\n            for (const point of column.data) {\n                const key = this.csvTimeKey(point.time);\n\n                let row = rows.get(key);\n\n                if (!row) {\n                    row = {\n                        time: point.time,\n                        values: new Map<string, unknown>(),\n                        firstSeen,\n                    };\n                    firstSeen += 1;\n                    rows.set(key, row);\n                }\n\n                row.values.set(\n                    column.name,\n                    point.value,\n                );\n            }\n        }\n\n        if (rows.size === 0) {\n            this.notify(\n                \"This indicator returned no data points to export.\",\n            );\n            return;\n        }\n\n        const candleOrder = new Map<string, number>();\n\n        this.candles.forEach((bar, index) => {\n            candleOrder.set(\n                this.csvTimeKey(bar.time),\n                index,\n            );\n        });\n\n        const orderedRows = [...rows.entries()]\n            .sort((left, right) => {\n                const leftOrder = candleOrder.get(left[0]);\n                const rightOrder = candleOrder.get(right[0]);\n\n                if (\n                    leftOrder !== undefined\n                    && rightOrder !== undefined\n                ) {\n                    return leftOrder - rightOrder;\n                }\n\n                if (leftOrder !== undefined) {\n                    return -1;\n                }\n\n                if (rightOrder !== undefined) {\n                    return 1;\n                }\n\n                return (\n                    left[1].firstSeen\n                    - right[1].firstSeen\n                );\n            })\n            .map((entry) => entry[1]);\n\n        const header = [\n            \"time\",\n            ...columns.map((column) => column.name),\n        ];\n\n        const csvLines = [\n            header\n                .map((value) => this.csvEscape(value))\n                .join(\",\"),\n\n            ...orderedRows.map((row) => {\n                return [\n                    this.csvTimeValue(row.time),\n                    ...columns.map(\n                        (column) =>\n                            row.values.get(column.name) ?? \"\",\n                    ),\n                ]\n                    .map((value) => this.csvEscape(value))\n                    .join(\",\");\n            }),\n        ];\n\n        const csv = `\\uFEFF${csvLines.join(\"\\r\\n\")}`;\n\n        const blob = new Blob(\n            [csv],\n            {\n                type: \"text/csv;charset=utf-8\",\n            },\n        );\n\n        const url = URL.createObjectURL(blob);\n        const link = document.createElement(\"a\");\n\n        const symbol = this.csvFileToken(\n            this.activeSymbol || \"chart\",\n        );\n\n        const timeframe = this.csvFileToken(\n            this.timeframeSelect.value || \"timeframe\",\n        );\n\n        const indicator = this.csvFileToken(\n            instance.indicatorId,\n        );\n\n        const instanceToken = this.csvFileToken(\n            instance.instanceId,\n        );\n\n        link.href = url;\n        link.download = (\n            `${symbol}_${timeframe}_${indicator}_${instanceToken}.csv`\n        );\n        link.style.display = \"none\";\n\n        document.body.append(link);\n        link.click();\n        link.remove();\n\n        window.setTimeout(\n            () => URL.revokeObjectURL(url),\n            0,\n        );\n    }\n\n\n    private csvTimeKey(value: unknown): string {\n        if (\n            value !== null\n            && typeof value === \"object\"\n        ) {\n            try {\n                return `object:${JSON.stringify(value)}`;\n            } catch {\n                return `object:${String(value)}`;\n            }\n        }\n\n        return `${typeof value}:${String(value)}`;\n    }\n\n\n    private csvTimeValue(value: unknown): string | number {\n        if (\n            value !== null\n            && typeof value === \"object\"\n        ) {\n            try {\n                return JSON.stringify(value);\n            } catch {\n                return String(value);\n            }\n        }\n\n        if (\n            typeof value === \"number\"\n            || typeof value === \"string\"\n        ) {\n            return value;\n        }\n\n        return String(value ?? \"\");\n    }\n\n\n    private csvEscape(value: unknown): string {\n        const text = String(value ?? \"\");\n\n        if (!/[\",\\r\\n]/.test(text)) {\n            return text;\n        }\n\n        return `\"${text.replace(/\"/g, '\"\"')}\"`;\n    }\n\n\n    private csvFileToken(value: string): string {\n        const cleaned = value\n            .trim()\n            .replace(/[^a-zA-Z0-9._-]+/g, \"_\")\n            .replace(/^_+|_+$/g, \"\");\n\n        return cleaned || \"indicator\";\n    }\n\n\n    private collectElements(): void {\n        this.chartContainer =\n            requireElement<HTMLDivElement>(\n                this.options.chartContainerId,\n            );\n\n        this.indicatorContainer =\n            requireElement<HTMLDivElement>(\n                this.options.indicatorContainerId,\n            );\n\n        this.separator =\n            requireElement<HTMLElement>(\n                this.options.separatorId,\n            );\n\n        const chartStack =\n            this.chartContainer.parentElement;\n\n        if (!(chartStack instanceof HTMLDivElement)) {\n            throw new Error(\n                \"Main chart must live inside #chartStack.\",\n            );\n        }\n\n        this.chartStack = chartStack;\n\n        this.tickerInput =\n            requireElement<HTMLInputElement>(\n                this.options.tickerInputId,\n            );\n\n        this.timeframeSelect =\n            requireElement<HTMLSelectElement>(\n                this.options.timeframeSelectId,\n            );\n\n        this.themeToggle =\n            requireElement<HTMLButtonElement>(\n                this.options.themeToggleId,\n            );\n\n        this.indicatorTitle =\n            requireElement<HTMLElement>(\n                this.options.indicatorTitleId,\n            );\n\n        this.indicatorControlsContainer =\n            requireElement<HTMLElement>(\n                this.options\n                    .indicatorControlsContainerId,\n            );\n\n        this.applyIndicatorButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .applyIndicatorButtonId,\n            );\n\n        this.clearIndicatorButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .clearIndicatorButtonId,\n            );\n\n        this.indicatorLiveInput =\n            requireElement<HTMLInputElement>(\n                this.options\n                    .indicatorLiveInputId,\n            );\n    }\n\n\n    private installIndicatorEnhancementStyles(): void {\n        const styleId =\n            \"chartix-indicator-enhancement-styles\";\n\n        if (document.getElementById(styleId)) {\n            return;\n        }\n\n        const style = document.createElement(\"style\");\n        style.id = styleId;\n        style.textContent = `\n            /*\n             * Keep the indicator-on-indicator controls visually inside the\n             * existing settings language. This is intentionally scoped to\n             * the two controls Chartix adds: Applied instance + Source.\n             */\n            [data-indicator-instance-control=\"true\"],\n            [data-indicator-parameter-id=\"__source__\"] {\n                font: inherit;\n                color: inherit;\n            }\n\n            [data-indicator-instance-control=\"true\"] label,\n            [data-indicator-parameter-id=\"__source__\"] label {\n                font: inherit !important;\n                font-size: 12px !important;\n                font-weight: 500;\n                line-height: 1.2;\n                color: inherit;\n                opacity: 0.78;\n            }\n\n            [data-indicator-instance-control=\"true\"] select,\n            [data-indicator-parameter-id=\"__source__\"] select {\n                box-sizing: border-box;\n                min-width: 0;\n                height: 30px;\n                padding: 0 9px;\n                border: 1px solid color-mix(in srgb, currentColor 18%, transparent);\n                border-radius: 6px;\n                outline: none;\n                background: color-mix(in srgb, currentColor 3.5%, transparent);\n                color: inherit;\n                font: inherit;\n                font-size: 12px;\n                line-height: 28px;\n                transition:\n                    border-color 120ms ease,\n                    background-color 120ms ease,\n                    box-shadow 120ms ease;\n            }\n\n            [data-indicator-instance-control=\"true\"] select:hover,\n            [data-indicator-parameter-id=\"__source__\"] select:hover {\n                border-color: color-mix(in srgb, currentColor 30%, transparent);\n                background: color-mix(in srgb, currentColor 5.5%, transparent);\n            }\n\n            [data-indicator-instance-control=\"true\"] select:focus,\n            [data-indicator-parameter-id=\"__source__\"] select:focus {\n                border-color: color-mix(in srgb, var(--desk-accent, #2962ff) 70%, currentColor);\n                box-shadow: 0 0 0 2px color-mix(in srgb, var(--desk-accent, #2962ff) 14%, transparent);\n            }\n\n            [data-indicator-instance-control=\"true\"] button {\n                box-sizing: border-box;\n                height: 30px;\n                padding: 0 10px !important;\n                border: 1px solid color-mix(in srgb, currentColor 16%, transparent);\n                border-radius: 6px;\n                background: transparent;\n                color: inherit;\n                font: inherit;\n                font-size: 11px !important;\n                font-weight: 600;\n                line-height: 28px;\n                white-space: nowrap;\n                cursor: pointer;\n                opacity: 0.82;\n                transition:\n                    opacity 120ms ease,\n                    border-color 120ms ease,\n                    background-color 120ms ease,\n                    transform 80ms ease;\n            }\n\n            [data-indicator-instance-control=\"true\"] button:hover {\n                opacity: 1;\n                border-color: color-mix(in srgb, var(--desk-accent, #2962ff) 48%, currentColor);\n                background: color-mix(in srgb, var(--desk-accent, #2962ff) 7%, transparent);\n            }\n\n            [data-indicator-instance-control=\"true\"] button:active {\n                transform: translateY(1px);\n            }\n\n            [data-indicator-instance-control=\"true\"] {\n                padding-bottom: 9px;\n                margin-bottom: 10px !important;\n                border-bottom: 1px solid color-mix(in srgb, currentColor 9%, transparent);\n            }\n\n            [data-indicator-parameter-id=\"__source__\"] {\n                margin-bottom: 5px !important;\n            }\n\n            [data-indicator-parameter-id=\"__source__\"]\n            + .indicator-control-description {\n                margin-top: 0 !important;\n                margin-bottom: 11px !important;\n                padding-left: 1px;\n                font: inherit;\n                font-size: 10.5px !important;\n                line-height: 1.35 !important;\n                opacity: 0.58 !important;\n            }\n\n            [data-indicator-instance-control=\"true\"] select:disabled,\n            [data-indicator-parameter-id=\"__source__\"] select:disabled,\n            [data-indicator-instance-control=\"true\"] button:disabled {\n                cursor: default;\n                opacity: 0.45;\n            }\n\n            .chartix-line-drop-target {\n                position: relative;\n            }\n\n            .chartix-line-drop-target::after {\n                content: \"Drop indicator line here\";\n                position: absolute;\n                inset: 7px;\n                z-index: 120;\n                display: flex;\n                align-items: center;\n                justify-content: center;\n                border: 1px dashed color-mix(in srgb, var(--desk-accent, #2962ff) 48%, transparent);\n                border-radius: 7px;\n                background: color-mix(in srgb, var(--desk-accent, #2962ff) 5%, transparent);\n                color: color-mix(in srgb, currentColor 72%, var(--desk-accent, #2962ff));\n                font: inherit;\n                font-size: 11px;\n                font-weight: 650;\n                letter-spacing: 0.01em;\n                opacity: 0;\n                pointer-events: none;\n                transition: opacity 100ms ease, background-color 100ms ease;\n            }\n\n            .chartix-line-drop-target.is-line-drop-available::after {\n                opacity: 0.55;\n            }\n\n            .chartix-line-drop-target.is-line-drop-over::after {\n                opacity: 1;\n                border-style: solid;\n                background: color-mix(in srgb, var(--desk-accent, #2962ff) 11%, transparent);\n            }\n\n            .chartix-line-drop-target.is-time-axis-drop-over::after {\n                content: \"Release on date/time axis → restore own pane\";\n                opacity: 1;\n                align-items: flex-end;\n                padding-bottom: 10px;\n                border-style: solid;\n                background:\n                    linear-gradient(\n                        to bottom,\n                        color-mix(in srgb, var(--desk-accent, #2962ff) 2%, transparent) 0%,\n                        color-mix(in srgb, var(--desk-accent, #2962ff) 4%, transparent) 72%,\n                        color-mix(in srgb, var(--desk-accent, #2962ff) 18%, transparent) 72%,\n                        color-mix(in srgb, var(--desk-accent, #2962ff) 18%, transparent) 100%\n                    );\n            }\n\n            .chartix-pane-controls {\n                position: absolute;\n                top: 8px;\n                right: 10px;\n                z-index: 145;\n\n                display: flex;\n                align-items: center;\n                gap: 4px;\n\n                padding: 3px;\n                border: 1px solid color-mix(in srgb, currentColor 13%, transparent);\n                border-radius: 7px;\n                background: color-mix(in srgb, canvas 91%, transparent);\n                color: inherit;\n                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n                backdrop-filter: blur(8px);\n                pointer-events: auto;\n                user-select: none;\n            }\n\n            .chartix-pane-control-title {\n                max-width: 150px;\n                padding: 0 5px 0 4px;\n                overflow: hidden;\n                text-overflow: ellipsis;\n                white-space: nowrap;\n                font: inherit;\n                font-size: 10px;\n                font-weight: 650;\n                opacity: 0.58;\n            }\n\n            .chartix-pane-control-button {\n                width: 24px;\n                height: 22px;\n                display: inline-flex;\n                align-items: center;\n                justify-content: center;\n                padding: 0;\n                border: 0;\n                border-radius: 5px;\n                background: transparent;\n                color: inherit;\n                font: inherit;\n                font-size: 12px;\n                line-height: 1;\n                cursor: pointer;\n                opacity: 0.66;\n            }\n\n            .chartix-pane-control-button:hover {\n                background: color-mix(in srgb, currentColor 8%, transparent);\n                opacity: 1;\n            }\n\n            .chartix-pane-control-button[aria-pressed=\"true\"] {\n                background: color-mix(in srgb, var(--desk-accent, #2962ff) 12%, transparent);\n                color: color-mix(in srgb, currentColor 78%, var(--desk-accent, #2962ff));\n                opacity: 1;\n            }\n\n            .chartix-pane-minimized .indicator-line-legend {\n                display: none !important;\n            }\n\n            .chartix-pane-minimized .chartix-pane-control-title {\n                opacity: 0.82;\n            }\n        `;\n\n        document.head.append(style);\n    }\n\n\n    private createChart(): void {\n        this.chart = createChart(\n            this.chartContainer,\n            {\n                width:\n                    this.chartContainer.clientWidth,\n\n                height:\n                    this.chartContainer.clientHeight,\n\n                layout: {\n                    background: {\n                        color: \"white\",\n                    },\n                    textColor: \"#000\",\n                },\n\n                rightPriceScale: {\n                    borderColor: \"#ccc\",\n                },\n\n                timeScale: {\n                    ...DENSE_CHART_OPTIONS,\n                    minBarSpacing: 0.001,\n                    borderColor: \"#ccc\",\n                    timeVisible: true,\n                },\n\n                handleScroll: {\n                    pressedMouseMove: true,\n                    horzTouchDrag: true,\n                    vertTouchDrag: true,\n                    mouseWheel: true,\n                },\n\n                handleScale: {\n                    mouseWheel: true,\n                    pinch: true,\n                    axisPressedMouseMove: true,\n                },\n            },\n        );\n\n        this.candleSeries =\n            this.chart.addSeries(\n                CandlestickSeries,\n                {\n                    upColor: \"#4caf50\",\n                    downColor: \"#f44336\",\n\n                    borderVisible: false,\n\n                    wickUpColor: \"#4caf50\",\n                    wickDownColor: \"#f44336\",\n                },\n            );\n    }\n\n\n    private createIndicatorPane(): void {\n        /*\n         * The HTML still provides one separator + one lower chart container,\n         * but they are now only the reusable first pane slot. No indicator\n         * pane is created until a pane-based indicator is actually selected.\n         */\n        this.separator.style.display = \"none\";\n        this.indicatorContainer.style.display = \"none\";\n\n        this.chartContainer.style.height = \"100%\";\n        this.chartContainer.style.flex = \"1 1 0\";\n\n        this.seriesManager =\n            new SeriesManager(\n                this.chart,\n                this.chartContainer,\n            );\n\n        this.registerSharedCursorChart(\n            this.chart,\n            this.chartContainer,\n        );\n\n        /*\n         * Each chart owns a persistent legend. A legend is a view of every\n         * indicator line currently placed on that chart, independent of\n         * which indicator happens to be active in the settings panel.\n         */\n        this.getOrCreateLineLegend(\n            this.chartContainer,\n        );\n\n        this.registerLineDropTarget(\n            this.chartContainer,\n            this.chart,\n        );\n\n        this.createPaneControls(\n            this.chartContainer,\n            MAIN_PANE_KEY,\n            \"Price\",\n        );\n    }\n\n\n    private createPaneControls(\n        container: HTMLDivElement,\n        paneKey: string,\n        label: string,\n    ): HTMLDivElement {\n        const existing =\n            container.querySelector<HTMLDivElement>(\n                \".chartix-pane-controls\",\n            );\n\n        if (existing) {\n            return existing;\n        }\n\n        const root = document.createElement(\"div\");\n        root.className = \"chartix-pane-controls\";\n        root.dataset.paneKey = paneKey;\n\n        const title = document.createElement(\"span\");\n        title.className = \"chartix-pane-control-title\";\n        title.textContent = label;\n        title.title = label;\n\n        const minimize = document.createElement(\"button\");\n        minimize.type = \"button\";\n        minimize.className = \"chartix-pane-control-button\";\n        minimize.dataset.action = \"minimize\";\n        minimize.innerHTML = toolIcon(\"minus\");\n        minimize.title = \"Minimize pane\";\n        minimize.setAttribute(\"aria-label\", \"Minimize pane\");\n        minimize.setAttribute(\"aria-pressed\", \"false\");\n\n        const fullscreen = document.createElement(\"button\");\n        fullscreen.type = \"button\";\n        fullscreen.className = \"chartix-pane-control-button\";\n        fullscreen.dataset.action = \"fullscreen\";\n        fullscreen.innerHTML = toolIcon(\"maximize\");\n        fullscreen.title = \"Maximize pane\";\n        fullscreen.setAttribute(\"aria-label\", \"Maximize pane\");\n        fullscreen.setAttribute(\"aria-pressed\", \"false\");\n\n        const stopPointer = (event: Event): void => {\n            event.stopPropagation();\n        };\n\n        root.addEventListener(\"pointerdown\", stopPointer);\n        root.addEventListener(\"dblclick\", stopPointer);\n\n        minimize.addEventListener(\n            \"click\",\n            (event) => {\n                event.preventDefault();\n                event.stopPropagation();\n                this.togglePaneMinimized(paneKey);\n            },\n        );\n\n        fullscreen.addEventListener(\n            \"click\",\n            (event) => {\n                event.preventDefault();\n                event.stopPropagation();\n                this.togglePaneFullscreen(paneKey);\n            },\n        );\n\n        root.append(\n            title,\n            minimize,\n            fullscreen,\n        );\n\n        if (paneKey !== MAIN_PANE_KEY) {\n            const remove = document.createElement(\"button\");\n            remove.type = \"button\";\n            remove.className = \"chartix-pane-control-button chartix-delete-button\";\n            remove.dataset.action = \"delete\";\n            remove.innerHTML = toolIcon(\"delete\");\n            remove.title = `Delete ${label}`;\n            remove.setAttribute(\"aria-label\", remove.title);\n            remove.addEventListener(\"click\", event => {\n                event.stopPropagation();\n                this.removeIndicatorInstance(paneKey);\n            });\n            root.append(remove);\n        }\n        container.append(root);\n        return root;\n    }\n\n\n    private togglePaneMinimized(\n        paneKey: string,\n    ): void {\n        if (paneKey === MAIN_PANE_KEY) {\n            this.mainPaneMinimized =\n                !this.mainPaneMinimized;\n        } else {\n            const slot =\n                this.panesByIndicator.get(\n                    paneKey,\n                );\n\n            if (!slot) {\n                return;\n            }\n\n            slot.minimized = !slot.minimized;\n        }\n\n        if (this.fullscreenPaneKey === paneKey) {\n            this.fullscreenPaneKey = null;\n        }\n\n        this.rebalancePaneHeights();\n    }\n\n\n    private togglePaneFullscreen(\n        paneKey: string,\n    ): void {\n        const activating =\n            this.fullscreenPaneKey !== paneKey;\n\n        if (activating) {\n            if (paneKey === MAIN_PANE_KEY) {\n                this.mainPaneMinimized = false;\n            } else {\n                const slot =\n                    this.panesByIndicator.get(\n                        paneKey,\n                    );\n\n                if (!slot) {\n                    return;\n                }\n\n                slot.minimized = false;\n            }\n        }\n\n        this.fullscreenPaneKey = (\n            activating\n                ? paneKey\n                : null\n        );\n\n        this.rebalancePaneHeights();\n    }\n\n\n    private updatePaneControlStates(): void {\n        const update = (\n            container: HTMLElement,\n            paneKey: string,\n            minimized: boolean,\n        ): void => {\n            container.classList.toggle(\n                \"chartix-pane-minimized\",\n                minimized,\n            );\n\n            const controls =\n                container.querySelector<HTMLDivElement>(\n                    \".chartix-pane-controls\",\n                );\n\n            if (!controls) {\n                return;\n            }\n\n            const minimize =\n                controls.querySelector<HTMLButtonElement>(\n                    '[data-action=\"minimize\"]',\n                );\n\n            const fullscreen =\n                controls.querySelector<HTMLButtonElement>(\n                    '[data-action=\"fullscreen\"]',\n                );\n\n            if (minimize) {\n                minimize.innerHTML = toolIcon(minimized ? \"restore\" : \"minus\");\n                minimize.title =\n                    minimized\n                        ? \"Restore pane\"\n                        : \"Minimize pane\";\n                minimize.setAttribute(\n                    \"aria-pressed\",\n                    minimized ? \"true\" : \"false\",\n                );\n            }\n\n            const isFullscreen =\n                this.fullscreenPaneKey === paneKey;\n\n            if (fullscreen) {\n                fullscreen.innerHTML = toolIcon(isFullscreen ? \"restore\" : \"maximize\");\n                fullscreen.title =\n                    isFullscreen\n                        ? \"Restore all panes\"\n                        : \"Maximize pane\";\n                fullscreen.setAttribute(\n                    \"aria-pressed\",\n                    isFullscreen ? \"true\" : \"false\",\n                );\n            }\n        };\n\n        update(\n            this.chartContainer,\n            MAIN_PANE_KEY,\n            this.mainPaneMinimized,\n        );\n\n        for (const indicatorId of this.paneOrder) {\n            const slot =\n                this.panesByIndicator.get(\n                    indicatorId,\n                );\n\n            if (!slot) {\n                continue;\n            }\n\n            update(\n                slot.container,\n                indicatorId,\n                slot.minimized,\n            );\n        }\n    }\n\n\n    private getOrCreateIndicatorPane(\n        indicatorId: string,\n    ): IndicatorPaneSlot {\n        const existing =\n            this.panesByIndicator.get(\n                indicatorId,\n            );\n\n        if (existing) {\n            return existing;\n        }\n\n        let container: HTMLDivElement;\n        let separator: HTMLElement;\n        let usesPrimaryDom = false;\n\n        if (this.paneOrder.length === 0) {\n            container = this.indicatorContainer;\n            separator = this.separator;\n            usesPrimaryDom = true;\n\n            separator.style.display = \"\";\n            container.style.display = \"\";\n        } else {\n            separator =\n                this.separator.cloneNode(\n                    false,\n                ) as HTMLElement;\n\n            separator.removeAttribute(\"id\");\n            separator.style.display = \"\";\n            separator.style.height = \"7px\";\n\n            container =\n                this.indicatorContainer.cloneNode(\n                    false,\n                ) as HTMLDivElement;\n\n            container.removeAttribute(\"id\");\n            container.replaceChildren();\n            container.style.display = \"\";\n            container.style.height = \"140px\";\n            container.style.minHeight = \"100px\";\n\n            this.chartStack.append(\n                separator,\n                container,\n            );\n        }\n\n        const previousIndicatorId =\n            this.paneOrder[\n                this.paneOrder.length - 1\n            ];\n\n        const previousSlot =\n            previousIndicatorId\n                ? this.panesByIndicator.get(\n                    previousIndicatorId,\n                )\n                : undefined;\n\n        const resizeUpperContainer =\n            previousSlot?.container\n            ?? this.chartContainer;\n\n        const resizeUpperChart =\n            previousSlot?.pane.chart\n            ?? this.chart;\n\n        const pane = new IndicatorPane({\n            mainChart: this.chart,\n            mainContainer:\n                this.chartContainer,\n            indicatorContainer:\n                container,\n            separator,\n            resizeUpperContainer,\n            resizeUpperChart,\n        });\n\n        const paneLabel = (() => {\n            const instance =\n                this.indicatorInstances.get(\n                    indicatorId,\n                );\n\n            return instance\n                ? this.indicatorInstanceLabel(instance)\n                : \"Indicator pane\";\n        })();\n\n        this.createPaneControls(\n            container,\n            indicatorId,\n            paneLabel,\n        );\n\n        const slot: IndicatorPaneSlot = {\n            pane,\n            container,\n            separator,\n            usesPrimaryDom,\n            minimized: false,\n        };\n\n        this.panesByIndicator.set(\n            indicatorId,\n            slot,\n        );\n\n        this.paneOrder.push(\n            indicatorId,\n        );\n\n        this.seriesManager\n            .registerPaneChart(\n                pane.chart,\n                container,\n            );\n\n        this.registerSharedCursorChart(\n            pane.chart,\n            container,\n        );\n\n        this.registerLineDropTarget(\n            container,\n            pane.chart,\n        );\n\n        this.getOrCreateLineLegend(\n            container,\n        );\n\n        pane.chart.applyOptions(appearanceOptions({ ...this.defaultChartAppearance(), ...this.appearance }, this.palette?.shell[3]));\n\n        // Clicking/interacting with a pane makes that applied indicator the\n        // active instance in the settings panel. This is important now that\n        // several instances of the same indicator type may coexist.\n        container.addEventListener(\n            \"pointerdown\",\n            (event) => {\n                const target = event.target as Element | null;\n\n                if (\n                    target?.closest(\n                        \".indicator-line-legend, .chartix-pane-controls\",\n                    )\n                ) {\n                    return;\n                }\n\n                const actualIndicatorId =\n                    this.seriesManager\n                        .getFirstIndicatorIdOnChart(\n                            pane.chart,\n                        )\n                    ?? indicatorId;\n\n                this.activateIndicatorInstance(\n                    actualIndicatorId,\n                );\n            },\n        );\n\n        this.rebalancePaneHeights();\n        pane.copyMainVisibleRange();\n\n        return slot;\n    }\n\n\n    private removeIndicatorPane(\n        indicatorId: string,\n    ): void {\n        const slot =\n            this.panesByIndicator.get(\n                indicatorId,\n            );\n\n        if (!slot) {\n            return;\n        }\n\n        if (this.fullscreenPaneKey === indicatorId) {\n            this.fullscreenPaneKey = null;\n        }\n\n        const mainRangeBeforeRemoval =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        // A pane can host lines that belong to other indicator instances.\n        // Move every surviving guest line to the main chart before the pane\n        // itself is destroyed.\n        this.seriesManager.moveLinesFromChart(\n            slot.pane.chart,\n            this.chart,\n        );\n\n        this.destroyLineLegend(\n            slot.container,\n        );\n\n        this.lineDropTargetCharts.delete(\n            slot.container,\n        );\n\n        this.seriesManager\n            .unregisterPaneChart(\n                slot.pane.chart,\n            );\n\n        this.unregisterSharedCursorChart(\n            slot.pane.chart,\n        );\n\n        slot.pane.destroy();\n\n        this.panesByIndicator.delete(\n            indicatorId,\n        );\n\n        const orderIndex =\n            this.paneOrder.indexOf(\n                indicatorId,\n            );\n\n        if (orderIndex >= 0) {\n            this.paneOrder.splice(\n                orderIndex,\n                1,\n            );\n        }\n\n        if (slot.usesPrimaryDom) {\n            slot.separator.style.display = \"none\";\n            slot.container.style.display = \"none\";\n            slot.container.replaceChildren();\n        } else {\n            slot.separator.remove();\n            slot.container.remove();\n        }\n\n        this.relinkPaneResizeNeighbours();\n        this.rebalancePaneHeights();\n\n        /*\n         * Resizing the main chart after a pane disappears should change only\n         * its pixel height, never the candle range the user was looking at.\n         */\n        if (mainRangeBeforeRemoval) {\n            this.chart\n                .timeScale()\n                .setVisibleLogicalRange(\n                    mainRangeBeforeRemoval,\n                );\n\n            this.syncAllPanesFromMain();\n        }\n\n        this.refreshAllLineLegends();\n    }\n\n\n    private cleanupEmptyIndicatorPanes(): void {\n        const emptyPaneIds =\n            [...this.paneOrder].filter(\n                (indicatorId) => {\n                    const slot =\n                        this.panesByIndicator.get(\n                            indicatorId,\n                        );\n\n                    return Boolean(\n                        slot\n                        && this.seriesManager\n                            .countLinesOnChart(\n                                slot.pane.chart,\n                            ) === 0\n                    );\n                },\n            );\n\n        for (const indicatorId of emptyPaneIds) {\n            this.removeIndicatorPane(\n                indicatorId,\n            );\n        }\n    }\n\n\n    private clearAllIndicatorPanes(): void {\n        for (\n            const indicatorId\n            of [...this.paneOrder]\n        ) {\n            const slot =\n                this.panesByIndicator.get(\n                    indicatorId,\n                );\n\n            if (!slot) {\n                continue;\n            }\n\n            this.destroyLineLegend(\n                slot.container,\n            );\n\n            this.lineDropTargetCharts.delete(\n                slot.container,\n            );\n\n            this.seriesManager\n                .unregisterPaneChart(\n                    slot.pane.chart,\n                );\n\n            this.unregisterSharedCursorChart(\n                slot.pane.chart,\n            );\n\n            slot.pane.destroy();\n\n            if (slot.usesPrimaryDom) {\n                slot.separator.style.display = \"none\";\n                slot.container.style.display = \"none\";\n                slot.container.replaceChildren();\n            } else {\n                slot.separator.remove();\n                slot.container.remove();\n            }\n        }\n\n        this.panesByIndicator.clear();\n        this.paneOrder.length = 0;\n\n        if (this.fullscreenPaneKey !== MAIN_PANE_KEY) {\n            this.fullscreenPaneKey = null;\n        }\n\n        this.rebalancePaneHeights();\n        this.refreshAllLineLegends();\n    }\n\n\n    private getOrCreateLineLegend(\n        container: HTMLElement,\n    ): IndicatorLineLegend {\n        const existing =\n            this.indicatorLineLegends.get(\n                container,\n            );\n\n        if (existing) {\n            return existing;\n        }\n\n        const legend =\n            new IndicatorLineLegend({\n                container,\n\n                onVisibilityChange: (\n                    instanceId,\n                    plotId,\n                    lineId,\n                    visible,\n                ) => {\n                    this.seriesManager\n                        .setLineVisible(\n                            instanceId,\n                            plotId,\n                            lineId,\n                            visible,\n                        );\n\n                    this.refreshAllLineLegends();\n                },\n\n                onScaleChange: (\n                    instanceId,\n                    plotId,\n                    lineId,\n                    scaleValue,\n                ) => {\n                    this.applyLineScaleSelection(\n                        instanceId,\n                        plotId,\n                        lineId,\n                        scaleValue,\n                    );\n\n                    this.refreshAllLineLegends();\n                },\n\n                onDeleteIndicator: instanceId => this.removeIndicatorInstance(instanceId),\n\n                onDownloadIndicator: (instanceId) => {\n                    this.exportIndicatorInstanceCsv(instanceId);\n                },\n\n                onLineDragStart: (\n                    instanceId,\n                    plotId,\n                    lineId,\n                    title,\n                ) => {\n                    this.beginIndicatorLineDrag({\n                        instanceId,\n                        plotId,\n                        lineId,\n                        title,\n                    });\n                },\n\n                onLineDragEnd: () => {\n                    this.endIndicatorLineDrag();\n                },\n            });\n\n        this.indicatorLineLegends.set(\n            container,\n            legend,\n        );\n\n        return legend;\n    }\n\n\n    private destroyLineLegend(\n        container: HTMLElement,\n    ): void {\n        const legend =\n            this.indicatorLineLegends.get(\n                container,\n            );\n\n        if (!legend) {\n            return;\n        }\n\n        legend.destroy();\n        this.indicatorLineLegends.delete(\n            container,\n        );\n    }\n\n\n    private containerForLineChart(\n        chart: IChartApi,\n    ): HTMLElement | null {\n        if (chart === this.chart) {\n            return this.chartContainer;\n        }\n\n        for (\n            const slot\n            of this.panesByIndicator.values()\n        ) {\n            if (slot.pane.chart === chart) {\n                return slot.container;\n            }\n        }\n\n        return null;\n    }\n\n\n    private refreshAllLineLegends(): void {\n        this.getOrCreateLineLegend(\n            this.chartContainer,\n        );\n\n        for (\n            const slot\n            of this.panesByIndicator.values()\n        ) {\n            this.getOrCreateLineLegend(\n                slot.container,\n            );\n        }\n\n        const linesByContainer =\n            new Map<\n                HTMLElement,\n                IndicatorLineLegendItem[]\n            >();\n\n        for (\n            const container\n            of this.indicatorLineLegends.keys()\n        ) {\n            linesByContainer.set(\n                container,\n                [],\n            );\n        }\n\n        for (\n            const instance\n            of this.indicatorInstances.values()\n        ) {\n            if (!instance.loaded) {\n                continue;\n            }\n\n            const instanceLabel =\n                this.indicatorInstanceLabel(\n                    instance,\n                );\n\n            for (const plot of instance.plots) {\n                for (const line of plot.lines) {\n                    if (line.drawInPane === false && line.showPriceLabel === false) continue;\n                    const chart =\n                        this.seriesManager\n                            .getLineChart(\n                                instance.instanceId,\n                                plot.id,\n                                line.id,\n                            );\n\n                    if (!chart) {\n                        continue;\n                    }\n\n                    const container =\n                        this.containerForLineChart(\n                            chart,\n                        );\n\n                    if (!container) {\n                        continue;\n                    }\n\n                    const bucket =\n                        linesByContainer.get(\n                            container,\n                        ) ?? [];\n\n                    bucket.push({\n                        instanceId:\n                            instance.instanceId,\n                        instanceLabel,\n                        plotId: plot.id,\n                        line,\n                        visible:\n                            this.seriesManager\n                                .isLineVisible(\n                                    instance.instanceId,\n                                    plot.id,\n                                    line.id,\n                                ),\n                        scaleValue:\n                            OWN_SCALE_VALUE,\n                        scaleOptions: [],\n                    });\n\n                    linesByContainer.set(\n                        container,\n                        bucket,\n                    );\n                }\n            }\n        }\n\n        for (\n            const [container, items]\n            of linesByContainer.entries()\n        ) {\n            this.decorateLineScaleOptions(\n                container,\n                items,\n            );\n        }\n\n        for (\n            const [container, legend]\n            of this.indicatorLineLegends.entries()\n        ) {\n            legend.render(\n                linesByContainer.get(\n                    container,\n                ) ?? [],\n            );\n        }\n\n        /*\n         * Core v7 pane/legend work is complete at this point. Backgrounds are\n         * optional presentation and are refreshed one frame later so they can\n         * never interrupt move/cleanup/viewport logic.\n         */\n        this.scheduleIndicatorBackgroundRefresh();\n    }\n\n\n    private scheduleIndicatorBackgroundRefresh(): void {\n        if (this.indicatorBackgroundFrame !== null) {\n            window.cancelAnimationFrame(\n                this.indicatorBackgroundFrame,\n            );\n        }\n\n        this.indicatorBackgroundFrame =\n            window.requestAnimationFrame(\n                () => {\n                    this.indicatorBackgroundFrame = null;\n\n                    try {\n                        this.refreshIndicatorBackgroundsNow();\n                    } catch (error) {\n                        console.warn(\n                            \"[Chartix background] refresh failed; core chart state is unaffected.\",\n                            error,\n                        );\n                    }\n                },\n            );\n    }\n\n\n    private refreshIndicatorBackgroundsNow(): void {\n        const entriesByChart =\n            new Map<IChartApi, IndicatorBackgroundEntry[]>();\n\n        entriesByChart.set(\n            this.chart,\n            [],\n        );\n\n        for (const slot of this.panesByIndicator.values()) {\n            entriesByChart.set(\n                slot.pane.chart,\n                [],\n            );\n        }\n\n        for (const instance of this.indicatorInstances.values()) {\n            if (!instance.loaded) {\n                continue;\n            }\n\n            for (const plot of instance.plots) {\n                for (const line of plot.lines) {\n                    if (!line.background) {\n                        continue;\n                    }\n\n                    if (\n                        !this.seriesManager.isLineVisible(\n                            instance.instanceId,\n                            plot.id,\n                            line.id,\n                        )\n                    ) {\n                        continue;\n                    }\n\n                    const chart =\n                        this.seriesManager.getLineChart(\n                            instance.instanceId,\n                            plot.id,\n                            line.id,\n                        );\n\n                    if (!chart) {\n                        continue;\n                    }\n\n                    const bucket =\n                        entriesByChart.get(chart);\n\n                    if (!bucket) {\n                        /*\n                         * The line points at a chart that has already left the\n                         * live pane set. Skip it rather than resurrecting DOM.\n                         */\n                        continue;\n                    }\n\n                    bucket.push({\n                        key:\n                            `${instance.instanceId}:`\n                            + `${plot.id}:`\n                            + line.id,\n                        background:\n                            line.background,\n                    });\n                }\n            }\n        }\n\n        const targets: IndicatorBackgroundTarget[] = [\n            {\n                chart: this.chart,\n                container: this.chartContainer,\n                entries:\n                    entriesByChart.get(this.chart)\n                    ?? [],\n            },\n        ];\n\n        for (const slot of this.panesByIndicator.values()) {\n            targets.push({\n                chart: slot.pane.chart,\n                container: slot.container,\n                entries:\n                    entriesByChart.get(slot.pane.chart)\n                    ?? [],\n            });\n        }\n\n        this.indicatorBackgroundLayer.sync(\n            targets,\n        );\n    }\n\n\n    private decorateLineScaleOptions(\n        container: HTMLElement,\n        items: IndicatorLineLegendItem[],\n    ): void {\n        const isMainChart =\n            container === this.chartContainer;\n\n        for (const item of items) {\n            const currentScaleId =\n                this.seriesManager\n                    .getLineScaleId(\n                        item.instanceId,\n                        item.plotId,\n                        item.line.id,\n                    );\n\n            const options:\n                IndicatorLineScaleOption[] = [\n                    {\n                        value: OWN_SCALE_VALUE,\n                        label: \"Own scale\",\n                    },\n                ];\n\n            if (isMainChart) {\n                options.push({\n                    value: PRICE_SCALE_VALUE,\n                    label: \"Price axis\",\n                });\n            }\n\n            let sharedWithValue: string | null = null;\n\n            for (const other of items) {\n                if (other === item) {\n                    continue;\n                }\n\n                const targetValue =\n                    this.encodeLineScaleTarget({\n                        instanceId:\n                            other.instanceId,\n                        plotId:\n                            other.plotId,\n                        lineId:\n                            other.line.id,\n                    });\n\n                options.push({\n                    value: targetValue,\n                    label:\n                        \"Share · \"\n                        + other.instanceLabel\n                        + \" · \"\n                        + other.line.title,\n                });\n\n                const otherScaleId =\n                    this.seriesManager\n                        .getLineScaleId(\n                            other.instanceId,\n                            other.plotId,\n                            other.line.id,\n                        );\n\n                if (\n                    sharedWithValue === null\n                    && currentScaleId !== null\n                    && currentScaleId\n                        === otherScaleId\n                ) {\n                    sharedWithValue =\n                        targetValue;\n                }\n            }\n\n            item.scaleOptions = options;\n\n            if (\n                isMainChart\n                && currentScaleId === \"right\"\n            ) {\n                item.scaleValue =\n                    PRICE_SCALE_VALUE;\n            } else if (sharedWithValue) {\n                item.scaleValue =\n                    sharedWithValue;\n            } else {\n                item.scaleValue =\n                    OWN_SCALE_VALUE;\n            }\n        }\n    }\n\n\n    private applyLineScaleSelection(\n        instanceId: string,\n        plotId: string,\n        lineId: string,\n        scaleValue: string,\n    ): void {\n        if (scaleValue === OWN_SCALE_VALUE) {\n            this.seriesManager\n                .separateLineScale(\n                    instanceId,\n                    plotId,\n                    lineId,\n                );\n\n            return;\n        }\n\n        if (scaleValue === PRICE_SCALE_VALUE) {\n            this.seriesManager\n                .mergeLineScaleWithPrice(\n                    instanceId,\n                    plotId,\n                    lineId,\n                );\n\n            return;\n        }\n\n        const target =\n            this.decodeLineScaleTarget(\n                scaleValue,\n            );\n\n        if (!target) {\n            return;\n        }\n\n        this.seriesManager\n            .mergeLineScaleWithLine(\n                instanceId,\n                plotId,\n                lineId,\n                target.instanceId,\n                target.plotId,\n                target.lineId,\n            );\n    }\n\n\n    private encodeLineScaleTarget(\n        target: IndicatorLineScaleTarget,\n    ): string {\n        return (\n            \"line:\"\n            + encodeURIComponent(\n                JSON.stringify(target),\n            )\n        );\n    }\n\n\n    private decodeLineScaleTarget(\n        value: string,\n    ): IndicatorLineScaleTarget | null {\n        if (!value.startsWith(\"line:\")) {\n            return null;\n        }\n\n        try {\n            const parsed = JSON.parse(\n                decodeURIComponent(\n                    value.slice(5),\n                ),\n            ) as Partial<IndicatorLineScaleTarget>;\n\n            if (\n                typeof parsed.instanceId !== \"string\"\n                || typeof parsed.plotId !== \"string\"\n                || typeof parsed.lineId !== \"string\"\n            ) {\n                return null;\n            }\n\n            return {\n                instanceId: parsed.instanceId,\n                plotId: parsed.plotId,\n                lineId: parsed.lineId,\n            };\n        } catch {\n            return null;\n        }\n    }\n\n\n    private isTimeAxisDropZone(\n        container: HTMLElement,\n        clientY: number,\n    ): boolean {\n        const rect =\n            container.getBoundingClientRect();\n\n        return (\n            clientY >= rect.bottom - TIME_AXIS_RESTORE_ZONE_PX\n            && clientY <= rect.bottom\n        );\n    }\n\n\n    private registerLineDropTarget(\n        container: HTMLElement,\n        chart: IChartApi,\n    ): void {\n        this.lineDropTargetCharts.set(\n            container,\n            chart,\n        );\n\n        container.classList.add(\n            \"chartix-line-drop-target\",\n        );\n\n        if (this.lineDropTargetBound.has(container)) {\n            return;\n        }\n\n        this.lineDropTargetBound.add(container);\n\n        container.addEventListener(\n            \"dragover\",\n            (event) => {\n                if (!this.draggedIndicatorLine) {\n                    return;\n                }\n\n                event.preventDefault();\n                event.stopPropagation();\n\n                if (event.dataTransfer) {\n                    event.dataTransfer.dropEffect = \"move\";\n                }\n\n                const onTimeAxis =\n                    this.isTimeAxisDropZone(\n                        container,\n                        event.clientY,\n                    );\n\n                container.classList.toggle(\n                    \"is-time-axis-drop-over\",\n                    onTimeAxis,\n                );\n\n                container.classList.toggle(\n                    \"is-line-drop-over\",\n                    !onTimeAxis,\n                );\n            },\n            true,\n        );\n\n        container.addEventListener(\n            \"dragleave\",\n            (event) => {\n                const related =\n                    event.relatedTarget as Node | null;\n\n                if (\n                    related\n                    && container.contains(related)\n                ) {\n                    return;\n                }\n\n                container.classList.remove(\n                    \"is-line-drop-over\",\n                    \"is-time-axis-drop-over\",\n                );\n            },\n            true,\n        );\n\n        container.addEventListener(\n            \"drop\",\n            (event) => {\n                if (!this.draggedIndicatorLine) {\n                    return;\n                }\n\n                event.preventDefault();\n                event.stopPropagation();\n\n                if (\n                    this.isTimeAxisDropZone(\n                        container,\n                        event.clientY,\n                    )\n                ) {\n                    this.restoreDraggedIndicatorLineToOwnPane();\n                    return;\n                }\n\n                const targetChart =\n                    this.lineDropTargetCharts.get(\n                        container,\n                    );\n\n                if (!targetChart) {\n                    this.endIndicatorLineDrag();\n                    return;\n                }\n\n                this.moveDraggedIndicatorLine(\n                    targetChart,\n                );\n            },\n            true,\n        );\n    }\n\n\n    private beginIndicatorLineDrag(\n        dragged: DraggedIndicatorLine,\n    ): void {\n        this.draggedIndicatorLine = dragged;\n\n        for (\n            const container\n            of this.lineDropTargetCharts.keys()\n        ) {\n            container.classList.add(\n                \"is-line-drop-available\",\n            );\n        }\n    }\n\n\n    private endIndicatorLineDrag(): void {\n        this.draggedIndicatorLine = null;\n\n        for (\n            const container\n            of this.lineDropTargetCharts.keys()\n        ) {\n            container.classList.remove(\n                \"is-line-drop-available\",\n                \"is-line-drop-over\",\n                \"is-time-axis-drop-over\",\n            );\n        }\n    }\n\n\n    private moveDraggedIndicatorLine(\n        targetChart: IChartApi,\n    ): void {\n        const dragged = this.draggedIndicatorLine;\n\n        if (!dragged) {\n            return;\n        }\n\n        const mainRange =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        const moved =\n            this.seriesManager\n                .moveIndicatorLine(\n                    dragged.instanceId,\n                    dragged.plotId,\n                    dragged.lineId,\n                    targetChart,\n                );\n\n        if (moved) {\n            this.cleanupEmptyIndicatorPanes();\n\n            if (mainRange) {\n                this.chart\n                    .timeScale()\n                    .setVisibleLogicalRange(\n                        mainRange,\n                    );\n\n                this.syncAllPanesFromMain();\n            }\n\n            this.refreshAllLineLegends();\n        }\n\n        this.endIndicatorLineDrag();\n    }\n\n\n    private restoreDraggedIndicatorLineToOwnPane(): void {\n        const dragged = this.draggedIndicatorLine;\n\n        if (!dragged) {\n            return;\n        }\n\n        const mainRange =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        /*\n         * Explicit restoration means the user wants lower panes visible again,\n         * even if they were previously hidden by double-clicking the main chart.\n         */\n        this.lowerPanesHidden = false;\n        this.fullscreenPaneKey = null;\n\n        const slot =\n            this.getOrCreateIndicatorPane(\n                dragged.instanceId,\n            );\n\n        slot.minimized = false;\n\n        const moved =\n            this.seriesManager\n                .moveIndicatorLine(\n                    dragged.instanceId,\n                    dragged.plotId,\n                    dragged.lineId,\n                    slot.pane.chart,\n                );\n\n        if (moved) {\n            this.cleanupEmptyIndicatorPanes();\n        }\n\n        this.rebalancePaneHeights();\n\n        if (mainRange) {\n            this.chart\n                .timeScale()\n                .setVisibleLogicalRange(\n                    mainRange,\n                );\n\n            this.syncAllPanesFromMain();\n        }\n\n        this.refreshAllLineLegends();\n        this.endIndicatorLineDrag();\n    }\n\n\n    private registerSharedCursorChart(\n        chart: IChartApi,\n        container: HTMLDivElement,\n    ): void {\n        if (\n            this.sharedCursorTargets.has(\n                chart,\n            )\n        ) {\n            return;\n        }\n\n        if (\n            window\n                .getComputedStyle(container)\n                .position === \"static\"\n        ) {\n            container.style.position =\n                \"relative\";\n        }\n\n        const line =\n            document.createElement(\"div\");\n\n        line.className =\n            \"chart-shared-cursor\";\n\n        Object.assign(\n            line.style,\n            {\n                position: \"absolute\",\n                top: \"0\",\n                bottom: \"0\",\n                width: \"1px\",\n                background:\n                    \"rgba(128, 128, 128, 0.65)\",\n                pointerEvents: \"none\",\n                display: \"none\",\n                zIndex: \"40\",\n            },\n        );\n\n        container.append(line);\n\n        const handler = (\n            param: MouseEventParams<Time>,\n        ) => {\n            if (\n                param.time === undefined\n            ) {\n                this.hideSharedCursor();\n                return;\n            }\n\n            this.showSharedCursor(\n                param.time,\n            );\n        };\n\n        this.sharedCursorTargets.set(\n            chart,\n            {\n                line,\n                handler,\n            },\n        );\n\n        chart.subscribeCrosshairMove(\n            handler,\n        );\n    }\n\n\n    private unregisterSharedCursorChart(\n        chart: IChartApi,\n    ): void {\n        const target =\n            this.sharedCursorTargets.get(\n                chart,\n            );\n\n        if (!target) {\n            return;\n        }\n\n        chart.unsubscribeCrosshairMove(\n            target.handler,\n        );\n\n        target.line.remove();\n\n        this.sharedCursorTargets.delete(\n            chart,\n        );\n    }\n\n\n    private showSharedCursor(\n        time: Time,\n    ): void {\n        for (\n            const [\n                chart,\n                target,\n            ]\n            of this.sharedCursorTargets\n        ) {\n            const x =\n                chart\n                    .timeScale()\n                    .timeToCoordinate(\n                        time,\n                    );\n\n            if (x === null) {\n                target.line.style.display =\n                    \"none\";\n\n                continue;\n            }\n\n            target.line.style.left =\n                `${x}px`;\n\n            target.line.style.display =\n                \"block\";\n        }\n    }\n\n\n    private hideSharedCursor(): void {\n        for (\n            const target\n            of this.sharedCursorTargets\n                .values()\n        ) {\n            target.line.style.display =\n                \"none\";\n        }\n    }\n\n\n    private relinkPaneResizeNeighbours(): void {\n        let upperContainer: HTMLElement =\n            this.chartContainer;\n\n        let upperChart: IChartApi =\n            this.chart;\n\n        for (\n            const indicatorId\n            of this.paneOrder\n        ) {\n            const slot =\n                this.panesByIndicator.get(\n                    indicatorId,\n                );\n\n            if (!slot) {\n                continue;\n            }\n\n            slot.pane.setResizeUpper(\n                upperContainer,\n                upperChart,\n            );\n\n            upperContainer =\n                slot.container;\n\n            upperChart =\n                slot.pane.chart;\n        }\n    }\n\n\n    private rebalancePaneHeights(): void {\n        const mainRangeBeforeLayout =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        const restoreRange = (): void => {\n            if (mainRangeBeforeLayout) {\n                this.chart\n                    .timeScale()\n                    .setVisibleLogicalRange(\n                        mainRangeBeforeLayout,\n                    );\n            }\n\n            this.syncAllPanesFromMain();\n        };\n\n        const showMain = (): void => {\n            this.chartContainer.style.display = \"\";\n        };\n\n        const hideMain = (): void => {\n            this.chartContainer.style.display = \"none\";\n        };\n\n        const setPaneVisible = (\n            indicatorId: string,\n            visible: boolean,\n            showSeparator = visible,\n        ): void => {\n            const slot =\n                this.panesByIndicator.get(\n                    indicatorId,\n                );\n\n            if (!slot) {\n                return;\n            }\n\n            slot.container.style.display =\n                visible ? \"\" : \"none\";\n\n            slot.separator.style.display =\n                showSeparator ? \"\" : \"none\";\n        };\n\n        /*\n         * Pane-local fullscreen: fill the entire chart stack and temporarily\n         * hide every sibling. This is intentionally an in-app maximize, so\n         * settings/watchlist remain available.\n         */\n        if (this.fullscreenPaneKey === MAIN_PANE_KEY) {\n            showMain();\n\n            for (const indicatorId of this.paneOrder) {\n                setPaneVisible(\n                    indicatorId,\n                    false,\n                    false,\n                );\n            }\n\n            this.chartStack.style.overflowY = \"hidden\";\n            this.chartContainer.style.flex = \"none\";\n            this.chartContainer.style.height = \"100%\";\n            this.chartContainer.style.minHeight = \"0px\";\n\n            this.chart.resize(\n                this.chartContainer.clientWidth,\n                this.chartContainer.clientHeight,\n            );\n\n            this.updatePaneControlStates();\n            restoreRange();\n            return;\n        }\n\n        if (\n            this.fullscreenPaneKey\n            && this.fullscreenPaneKey !== MAIN_PANE_KEY\n        ) {\n            const fullscreenSlot =\n                this.panesByIndicator.get(\n                    this.fullscreenPaneKey,\n                );\n\n            if (fullscreenSlot) {\n                hideMain();\n\n                for (const indicatorId of this.paneOrder) {\n                    setPaneVisible(\n                        indicatorId,\n                        indicatorId === this.fullscreenPaneKey,\n                        false,\n                    );\n                }\n\n                this.chartStack.style.overflowY = \"hidden\";\n                fullscreenSlot.container.style.flex = \"none\";\n                fullscreenSlot.container.style.height = \"100%\";\n                fullscreenSlot.container.style.minHeight = \"0px\";\n\n                fullscreenSlot.pane.resize();\n                this.updatePaneControlStates();\n                restoreRange();\n                return;\n            }\n\n            this.fullscreenPaneKey = null;\n        }\n\n        showMain();\n\n        const visiblePaneIds =\n            this.lowerPanesHidden\n                ? []\n                : [...this.paneOrder];\n\n        const visiblePaneSet =\n            new Set(visiblePaneIds);\n\n        for (const indicatorId of this.paneOrder) {\n            const visible =\n                visiblePaneSet.has(\n                    indicatorId,\n                );\n\n            setPaneVisible(\n                indicatorId,\n                visible,\n                visible,\n            );\n        }\n\n        /*\n         * With no visible lower panes, the price chart owns the full stack.\n         * This is also the state used by the main-chart double-click toggle.\n         */\n        if (visiblePaneIds.length === 0) {\n            this.chartStack.style.overflowY = \"hidden\";\n            this.chartContainer.style.flex = \"1 1 0\";\n            this.chartContainer.style.height = \"100%\";\n            this.chartContainer.style.minHeight = \"0px\";\n\n            this.chart.resize(\n                this.chartContainer.clientWidth,\n                this.chartContainer.clientHeight,\n            );\n\n            this.updatePaneControlStates();\n            restoreRange();\n            return;\n        }\n\n        const separatorHeight = 7;\n        const stackHeight =\n            this.chartStack.clientHeight;\n\n        const minimizedPaneIds =\n            visiblePaneIds.filter(\n                (indicatorId) => (\n                    this.panesByIndicator.get(\n                        indicatorId,\n                    )?.minimized\n                    ?? false\n                ),\n            );\n\n        const normalPaneIds =\n            visiblePaneIds.filter(\n                (indicatorId) => (\n                    !this.panesByIndicator.get(\n                        indicatorId,\n                    )?.minimized\n                ),\n            );\n\n        const fixedHeight =\n            (this.mainPaneMinimized\n                ? MINIMIZED_PANE_HEIGHT\n                : 0)\n            + minimizedPaneIds.length\n                * MINIMIZED_PANE_HEIGHT\n            + visiblePaneIds.length\n                * separatorHeight;\n\n        const flexibleHeight =\n            Math.max(\n                0,\n                stackHeight - fixedHeight,\n            );\n\n        const flexibleWeight =\n            (this.mainPaneMinimized ? 0 : 2)\n            + normalPaneIds.length;\n\n        const unitHeight =\n            flexibleWeight > 0\n                ? Math.floor(\n                    flexibleHeight\n                    / flexibleWeight,\n                )\n                : 0;\n\n        // Reserve usable space for the indicator controls before sizing the\n        // main pane. Compact chart cells can share their height without scrolling.\n        const minIndicatorHeight = 100;\n        const mainBudget = flexibleHeight - normalPaneIds.length * minIndicatorHeight;\n        const minMainHeight = Math.max(140, Math.min(220, mainBudget));\n        const mainHeight = this.mainPaneMinimized\n            ? MINIMIZED_PANE_HEIGHT\n            : Math.max(minMainHeight, Math.min(mainBudget, unitHeight * 2));\n        const indicatorBudget = flexibleHeight - (this.mainPaneMinimized ? 0 : mainHeight);\n        const normalPaneHeight = Math.max(minIndicatorHeight, Math.floor(indicatorBudget / Math.max(1, normalPaneIds.length)));\n\n        const requiredHeight =\n            mainHeight\n            + minimizedPaneIds.length\n                * MINIMIZED_PANE_HEIGHT\n            + normalPaneIds.length\n                * normalPaneHeight\n            + visiblePaneIds.length\n                * separatorHeight;\n\n        this.chartStack.style.overflowY =\n            requiredHeight > stackHeight\n                ? \"auto\"\n                : \"hidden\";\n\n        this.chartContainer.style.flex = \"none\";\n        this.chartContainer.style.height =\n            `${mainHeight}px`;\n        this.chartContainer.style.minHeight =\n            this.mainPaneMinimized\n                ? \"0px\"\n                : `${minMainHeight}px`;\n\n        for (const indicatorId of visiblePaneIds) {\n            const slot =\n                this.panesByIndicator.get(\n                    indicatorId,\n                );\n\n            if (!slot) {\n                continue;\n            }\n\n            const paneHeight =\n                slot.minimized\n                    ? MINIMIZED_PANE_HEIGHT\n                    : normalPaneHeight;\n\n            slot.container.style.flex = \"none\";\n            slot.container.style.height =\n                `${paneHeight}px`;\n            slot.container.style.minHeight =\n                slot.minimized\n                    ? \"0px\"\n                    : `${minIndicatorHeight}px`;\n        }\n\n        this.chart.resize(\n            this.chartContainer.clientWidth,\n            this.chartContainer.clientHeight,\n        );\n\n        for (const indicatorId of visiblePaneIds) {\n            this.panesByIndicator\n                .get(indicatorId)\n                ?.pane\n                .resize();\n        }\n\n        this.updatePaneControlStates();\n        restoreRange();\n    }\n\n\n    private syncAllPanesFromMain(): void {\n        for (\n            const indicatorId\n            of this.paneOrder\n        ) {\n            this.panesByIndicator\n                .get(indicatorId)\n                ?.pane\n                .copyMainVisibleRange();\n        }\n    }\n\n\n    private createIndicatorControls(): void {\n        this.indicatorControls =\n            new IndicatorControls({\n                container:\n                    this.indicatorControlsContainer,\n\n                onValueChange: () => {\n                    this.scheduleLiveIndicatorRun();\n                },\n            });\n    }\n\n\n    private createControllers(): void {\n        const barReplayButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .barReplayButtonId,\n            );\n\n        const replayControls =\n            requireElement<HTMLElement>(\n                this.options\n                    .replayControlsId,\n            );\n\n        const previousBarButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .previousBarButtonId,\n            );\n\n        const nextBarButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .nextBarButtonId,\n            );\n\n        const exitReplayButton =\n            requireElement<HTMLButtonElement>(\n                this.options\n                    .exitReplayButtonId,\n            );\n\n        const currentBarNumber =\n            requireElement<HTMLElement>(\n                this.options\n                    .currentBarNumberId,\n            );\n\n        const totalBarNumber =\n            requireElement<HTMLElement>(\n                this.options\n                    .totalBarNumberId,\n            );\n\n        const watchlistItems =\n            requireElement<HTMLElement>(\n                this.options\n                    .watchlistItemsId,\n            );\n\n        this.replay = new Replay({\n            chart: this.chart,\n            candleSeries: this.candleSeries,\n\n            barReplayButton,\n            replayControls,\n            previousBarButton,\n            nextBarButton,\n            exitReplayButton,\n            currentBarNumber,\n            totalBarNumber,\n            styleCandle: candle => {\n                const color = this.scriptBarColors.size ? this.scriptBarColors.get(chartTime(candle.time)) : undefined;\n                return color ? { ...candle, color, borderColor: color, wickColor: color } : candle;\n            },\n            onDisplayChange: () => {\n                const range = this.chart.timeScale().getVisibleLogicalRange();\n                const changed = this.seriesManager.setReplayTime(this.replay.getReplayTime());\n                if (changed && range) this.chart.timeScale().setVisibleLogicalRange(range);\n                this.syncAllPanesFromMain();\n                this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:state\", { bubbles: true }));\n            },\n        });\n\n        if (!watchlistItems.hidden) this.watchlist = new Watchlist({\n            container: watchlistItems,\n\n            onSelectSymbol: (\n                symbol,\n            ) => {\n                if (this.options.onWatchlistSelect) this.options.onWatchlistSelect(symbol);\n                else void this.loadSymbol(symbol);\n            },\n        });\n\n        this.contextMenu =\n            new ContextMenu({\n                chartContainer: this.chartStack,\n                focusTarget: this.chartContainer,\n\n                resetZoom: () => {\n                    this.chart\n                        .timeScale()\n                        .fitContent();\n\n                    this.syncAllPanesFromMain();\n                },\n\n                toggleTheme: () => {\n                    this.toggleTheme();\n                },\n\n                openSettings: () => this.openAppearanceSettings(),\n                exportCsv: () => {\n                    this.exportCsv();\n                },\n                removeAllIndicators: () => this.removeAllIndicators(),\n                removeAllObjects: () => this.options.onRemoveAllObjects?.(),\n\n                /*\n                 * Kept for compatibility with the existing\n                 * ContextMenu component.\n                 */\n                showRsi: () => {\n                    void this.setActiveIndicator(\n                        \"rsi\",\n                    );\n                },\n            });\n\n        this.replay.mount();\n        this.contextMenu.mount();\n    }\n\n\n    private bindEvents(): void {\n        window.addEventListener(\n            \"resize\",\n            () => {\n                this.resize();\n            },\n        );\n\n        this.themeToggle.addEventListener(\n            \"click\",\n            () => {\n                this.toggleTheme();\n            },\n        );\n\n        this.tickerInput.addEventListener(\n            \"keydown\",\n            (event) => {\n                if (event.key === \"Enter\") {\n                    void this.loadSymbol(\n                        this.tickerInput.value,\n                    );\n                }\n            },\n        );\n\n        this.timeframeSelect.addEventListener(\n            \"change\",\n            () => {\n                const symbol = (\n                    this.tickerInput\n                        .value\n                        .trim()\n                        .toUpperCase()\n                );\n\n                if (symbol) {\n                    void this.loadSymbol(\n                        symbol,\n                    );\n                }\n            },\n        );\n\n        this.applyIndicatorButton\n            .addEventListener(\n                \"click\",\n                () => {\n                    void this.runIndicator(\n                        false,\n                    );\n                },\n            );\n\n        this.clearIndicatorButton\n            .addEventListener(\n                \"click\",\n                () => {\n                    this.cancelIndicatorRequest();\n                    this.clearActivePlots();\n                },\n            );\n\n        this.chartContainer\n            .addEventListener(\n                \"click\",\n                () => {\n                    this.chartContainer.focus();\n                },\n            );\n\n        this.chartContainer\n            .addEventListener(\n                \"dblclick\",\n                (event) => {\n                    const target =\n                        event.target as Element | null;\n\n                    if (\n                        target?.closest(\n                            \".indicator-line-legend, .chartix-pane-controls, .drawing-layer, .chart-text-editor\",\n                        )\n                    ) {\n                        return;\n                    }\n\n                    event.preventDefault();\n                    event.stopPropagation();\n\n                    if (\n                        this.fullscreenPaneKey\n                        === MAIN_PANE_KEY\n                    ) {\n                        this.fullscreenPaneKey = null;\n                        this.lowerPanesHidden = false;\n                    } else {\n                        this.lowerPanesHidden =\n                            !this.lowerPanesHidden;\n                    }\n\n                    this.rebalancePaneHeights();\n                },\n                true,\n            );\n\n        this.chartContainer\n            .addEventListener(\n                \"keydown\",\n                (event) => {\n                    this.handleChartTyping(\n                        event,\n                    );\n                },\n            );\n\n        document.addEventListener(\n            \"click\",\n            (event) => {\n                const target =\n                    event.target as Node | null;\n\n                if (\n                    target &&\n                    !this.chartContainer.contains(\n                        target,\n                    )\n                ) {\n                    this.resetTyping();\n                }\n            },\n        );\n\n        this.chart.subscribeClick(\n            (\n                param:\n                    MouseEventParams<Time>,\n            ) => {\n                this.replay.handleChartClick(\n                    param,\n                );\n            },\n        );\n    }\n\n\n    private indicatorInstanceLabel(\n        instance: IndicatorInstanceState,\n    ): string {\n        const hashIndex =\n            instance.instanceId.lastIndexOf(\"#\");\n\n        const suffix =\n            hashIndex >= 0\n                ? instance.instanceId.slice(hashIndex + 1)\n                : instance.instanceId;\n\n        return `${instance.title} #${suffix}`;\n    }\n\n\n    private activateIndicatorInstance(\n        instanceId: string,\n    ): void {\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            return;\n        }\n\n        this.activeIndicatorInstanceId =\n            instanceId;\n        this.activeIndicatorId =\n            instance.indicatorId;\n\n        if (!instance.loaded) {\n            this.indicatorReady = false;\n            this.showIndicatorLoading(\n                \"Loading indicator…\",\n            );\n            return;\n        }\n\n        this.indicatorReady = true;\n        this.indicatorTitle.textContent =\n            this.indicatorInstanceLabel(\n                instance,\n            );\n\n        this.renderIndicatorControls(\n            instanceId,\n        );\n\n        this.refreshAllLineLegends();\n        this.syncIndicatorActionState();\n    }\n\n\n    private instanceDependsOn(\n        instanceId: string,\n        possibleAncestorId: string,\n    ): boolean {\n        let current =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        const visited = new Set<string>();\n\n        while (\n            current\n            && current.source.kind === \"indicator\"\n        ) {\n            const parentId =\n                current.source.instanceId;\n\n            if (parentId === possibleAncestorId) {\n                return true;\n            }\n\n            if (visited.has(parentId)) {\n                return true;\n            }\n\n            visited.add(parentId);\n            current =\n                this.indicatorInstances.get(\n                    parentId,\n                );\n        }\n\n        return false;\n    }\n\n\n    private getIndicatorTopologicalOrder(): string[] {\n        const temporary = new Set<string>();\n        const permanent = new Set<string>();\n        const order: string[] = [];\n\n        const visit = (instanceId: string) => {\n            if (permanent.has(instanceId)) {\n                return;\n            }\n\n            if (temporary.has(instanceId)) {\n                throw new Error(\n                    \"Indicator source cycle detected.\",\n                );\n            }\n\n            const instance =\n                this.indicatorInstances.get(\n                    instanceId,\n                );\n\n            if (!instance) {\n                throw new Error(\n                    `Indicator instance ${instanceId} no longer exists.`,\n                );\n            }\n\n            temporary.add(instanceId);\n\n            if (instance.source.kind === \"indicator\") {\n                visit(instance.source.instanceId);\n            }\n\n            temporary.delete(instanceId);\n            permanent.add(instanceId);\n            order.push(instanceId);\n        };\n\n        for (\n            const instanceId\n            of this.indicatorInstances.keys()\n        ) {\n            visit(instanceId);\n        }\n\n        return order;\n    }\n\n\n    private getIndicatorDescendantOrder(\n        rootInstanceId: string,\n    ): string[] {\n        return this.getIndicatorTopologicalOrder()\n            .filter(\n                (instanceId) => (\n                    instanceId !== rootInstanceId\n                    && this.instanceDependsOn(\n                        instanceId,\n                        rootInstanceId,\n                    )\n                ),\n            );\n    }\n\n\n    private buildIndicatorRecipe(\n        instanceId: string,\n        visiting: Set<string>,\n    ): IndicatorRecipe {\n        if (visiting.has(instanceId)) {\n            throw new Error(\n                \"Indicator source cycle detected.\",\n            );\n        }\n\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            throw new Error(\n                `Indicator source instance ${instanceId} no longer exists.`,\n            );\n        }\n\n        const nextVisiting =\n            new Set(visiting);\n\n        nextVisiting.add(instanceId);\n\n        return {\n            indicatorId: instance.indicatorId,\n            params: instance.params,\n            source:\n                this.buildIndicatorSourceRecipe(\n                    instance.source,\n                    nextVisiting,\n                ),\n        };\n    }\n\n\n    private buildIndicatorSourceRecipe(\n        source: IndicatorSourceSelection,\n        visiting: Set<string>,\n    ): IndicatorSourceRecipe {\n        if (source.kind === \"price\") {\n            return {\n                kind: \"price\",\n                field: source.field,\n            };\n        }\n\n        return {\n            kind: \"indicator\",\n            instanceId: source.instanceId,\n            plotId: source.plotId,\n            lineId: source.lineId,\n            recipe: this.buildIndicatorRecipe(\n                source.instanceId,\n                visiting,\n            ),\n        };\n    }\n\n\n    private sourceWouldCreateCycle(\n        candidateInstanceId: string,\n        activeInstanceId: string,\n    ): boolean {\n        let current =\n            this.indicatorInstances.get(\n                candidateInstanceId,\n            );\n\n        const visited = new Set<string>();\n\n        while (\n            current\n            && current.source.kind === \"indicator\"\n        ) {\n            if (\n                current.source.instanceId\n                === activeInstanceId\n            ) {\n                return true;\n            }\n\n            if (visited.has(current.instanceId)) {\n                return true;\n            }\n\n            visited.add(current.instanceId);\n\n            current =\n                this.indicatorInstances.get(\n                    current.source.instanceId,\n                );\n        }\n\n        return false;\n    }\n\n\n    private renderIndicatorInstanceControl(\n        activeInstanceId: string,\n    ): void {\n        this.indicatorControlsContainer\n            .querySelector(\n                '[data-indicator-instance-control=\"true\"]',\n            )\n            ?.remove();\n\n        const wrapper =\n            document.createElement(\"div\");\n\n        wrapper.dataset.indicatorInstanceControl =\n            \"true\";\n\n        wrapper.style.display = \"grid\";\n        wrapper.style.gridTemplateColumns =\n            \"84px minmax(0, 1fr) auto\";\n        wrapper.style.gap = \"8px\";\n        wrapper.style.alignItems = \"center\";\n        wrapper.style.marginBottom = \"8px\";\n\n        const label =\n            document.createElement(\"label\");\n\n        label.textContent = \"Applied\";\n        label.style.fontSize = \"12px\";\n\n        const select =\n            document.createElement(\"select\");\n\n        select.style.width = \"100%\";\n\n        for (\n            const instance\n            of this.indicatorInstances.values()\n        ) {\n            const option =\n                document.createElement(\"option\");\n\n            option.value = instance.instanceId;\n            option.textContent =\n                this.indicatorInstanceLabel(\n                    instance,\n                );\n            option.selected = (\n                instance.instanceId\n                === activeInstanceId\n            );\n\n            select.append(option);\n        }\n\n        select.addEventListener(\n            \"change\",\n            () => {\n                this.activateIndicatorInstance(\n                    select.value,\n                );\n            },\n        );\n\n        const addAnotherButton =\n            document.createElement(\"button\");\n\n        addAnotherButton.type = \"button\";\n        addAnotherButton.textContent = \"+ Another\";\n        const activeInstance =\n            this.indicatorInstances.get(\n                activeInstanceId,\n            );\n\n        if (!activeInstance) {\n            return;\n        }\n\n        addAnotherButton.title =\n            `Add another ${activeInstance.indicatorId} instance`;\n        addAnotherButton.style.whiteSpace = \"nowrap\";\n        addAnotherButton.hidden = isScriptPreview(activeInstance.indicatorId);\n\n        addAnotherButton.addEventListener(\n            \"click\",\n            () => {\n                void this.setActiveIndicator(\n                    activeInstance.indicatorId,\n                );\n            },\n        );\n\n        wrapper.append(\n            label,\n            select,\n            addAnotherButton,\n        );\n\n        this.indicatorControlsContainer\n            .prepend(wrapper);\n    }\n\n\n    private serializeIndicatorSourceSelection(\n        selection: IndicatorSourceSelection,\n    ): string {\n        return JSON.stringify(selection);\n    }\n\n\n    private parseIndicatorSourceSelection(\n        rawValue: IndicatorParameterValue | undefined,\n        activeInstanceId: string,\n    ): IndicatorSourceSelection {\n        if (typeof rawValue !== \"string\") {\n            throw new Error(\n                \"Source must be a valid series selection.\",\n            );\n        }\n\n        let raw: unknown;\n\n        try {\n            raw = JSON.parse(rawValue);\n        } catch {\n            throw new Error(\n                \"Source selection is invalid.\",\n            );\n        }\n\n        if (!raw || typeof raw !== \"object\") {\n            throw new Error(\n                \"Source selection is invalid.\",\n            );\n        }\n\n        const source = raw as {\n            kind?: unknown;\n            field?: unknown;\n            instanceId?: unknown;\n            plotId?: unknown;\n            lineId?: unknown;\n        };\n\n        if (source.kind === \"price\") {\n            const field = source.field;\n\n            if (\n                field !== \"open\"\n                && field !== \"high\"\n                && field !== \"low\"\n                && field !== \"close\"\n            ) {\n                throw new Error(\n                    \"Price source must be Open, High, Low, or Close.\",\n                );\n            }\n\n            return {\n                kind: \"price\",\n                field,\n            };\n        }\n\n        if (source.kind !== \"indicator\") {\n            throw new Error(\n                \"Source must be price data or an indicator output.\",\n            );\n        }\n\n        if (\n            typeof source.instanceId !== \"string\"\n            || typeof source.plotId !== \"string\"\n            || typeof source.lineId !== \"string\"\n        ) {\n            throw new Error(\n                \"Indicator source is incomplete.\",\n            );\n        }\n\n        const candidate =\n            this.indicatorInstances.get(\n                source.instanceId,\n            );\n\n        if (!candidate || !candidate.loaded || isScriptIndicator(candidate.indicatorId)) {\n            throw new Error(\n                \"The selected source indicator is no longer available.\",\n            );\n        }\n\n        if (source.instanceId === activeInstanceId) {\n            throw new Error(\n                \"An indicator cannot use itself as its source.\",\n            );\n        }\n\n        if (\n            this.sourceWouldCreateCycle(\n                source.instanceId,\n                activeInstanceId,\n            )\n        ) {\n            throw new Error(\n                \"That source would create an indicator cycle.\",\n            );\n        }\n\n        const outputExists =\n            candidate.plots.some(\n                (plot) => (\n                    plot.id === source.plotId\n                    && plot.lines.some(\n                        (line) => (\n                            line.id === source.lineId\n                        ),\n                    )\n                ),\n            );\n\n        if (!outputExists) {\n            throw new Error(\n                \"The selected indicator output no longer exists.\",\n            );\n        }\n\n        return {\n            kind: \"indicator\",\n            instanceId: source.instanceId,\n            plotId: source.plotId,\n            lineId: source.lineId,\n        };\n    }\n\n\n    private buildIndicatorSourceParameter(\n        instanceId: string,\n    ): IndicatorParameterSpec {\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            throw new Error(\n                `Indicator instance ${instanceId} no longer exists.`,\n            );\n        }\n\n        const options: NonNullable<\n            IndicatorParameterSpec[\"options\"]\n        > = [];\n\n        const addOption = (\n            label: string,\n            selection: IndicatorSourceSelection,\n        ) => {\n            options.push({\n                label,\n                value:\n                    this.serializeIndicatorSourceSelection(\n                        selection,\n                    ),\n            });\n        };\n\n        addOption(\n            \"Price · Close\",\n            { kind: \"price\", field: \"close\" },\n        );\n        addOption(\n            \"Price · Open\",\n            { kind: \"price\", field: \"open\" },\n        );\n        addOption(\n            \"Price · High\",\n            { kind: \"price\", field: \"high\" },\n        );\n        addOption(\n            \"Price · Low\",\n            { kind: \"price\", field: \"low\" },\n        );\n\n        for (\n            const candidate\n            of this.indicatorInstances.values()\n        ) {\n            if (\n                !candidate.loaded\n                || isScriptIndicator(candidate.indicatorId)\n                || candidate.instanceId === instanceId\n                || this.instanceDependsOn(\n                    candidate.instanceId,\n                    instanceId,\n                )\n            ) {\n                continue;\n            }\n\n            for (const plot of candidate.plots) {\n                for (const line of plot.lines) {\n                    const plotLabel = (\n                        plot.title\n                        && plot.title !== line.title\n                    )\n                        ? ` · ${plot.title}`\n                        : \"\";\n\n                    addOption(\n                        (\n                            `${this.indicatorInstanceLabel(candidate)}`\n                            + plotLabel\n                            + ` · ${line.title}`\n                        ),\n                        {\n                            kind: \"indicator\",\n                            instanceId:\n                                candidate.instanceId,\n                            plotId: plot.id,\n                            lineId: line.id,\n                        },\n                    );\n                }\n            }\n        }\n\n        return {\n            id: SOURCE_PARAMETER_ID,\n            label: \"Source\",\n            type: \"select\",\n            value:\n                this.serializeIndicatorSourceSelection(\n                    instance.source,\n                ),\n            options,\n            description: (\n                \"Input series for this indicator. Price fields are raw OHLC. \"\n                + \"Indicator entries use their causal calculation output; \"\n                + \"display-only Auto Center / Offset is not fed forward.\"\n            ),\n        };\n    }\n\n\n    private renderIndicatorControls(\n        instanceId: string,\n    ): void {\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            return;\n        }\n\n        const parameters = isScriptIndicator(instance.indicatorId)\n            ? instance.parameters\n            : [this.buildIndicatorSourceParameter(instanceId), ...instance.parameters];\n        this.indicatorControls.render(parameters);\n\n        // Instance selection is chart-level metadata. Source itself is now a\n        // normal first-class indicator setting rendered above all parameters.\n        this.renderIndicatorInstanceControl(\n            instanceId,\n        );\n    }\n\n\n    private async executeScript(\n        id: string,\n        params: Record<string, IndicatorParameterValue> | undefined,\n        signal: AbortSignal,\n    ) {\n        if (!this.options.loadScript) throw new Error(\"The script library is unavailable.\");\n        const script = await this.options.loadScript(id);\n        if (signal.aborted) throw new DOMException(\"Script run cancelled.\", \"AbortError\");\n        return runScript(script, id, this.candles, params, this.loadedTimeframe || this.timeframeSelect.value, this.activeSymbol);\n    }\n\n    private refreshScriptBarColors(): void {\n        const hadColors = this.scriptBarColors.size > 0;\n        this.scriptBarColors.clear();\n        for (const instance of this.indicatorInstances.values()) {\n            for (const { time, color } of instance.barColors ?? []) this.scriptBarColors.set(chartTime(time), color);\n        }\n        if (hadColors || this.scriptBarColors.size) this.replay.refreshCandleStyles();\n    }\n\n    private async fetchAndRenderIndicatorInstance(\n        instanceId: string,\n        params: Record<string, IndicatorParameterValue> | undefined,\n        signal: AbortSignal,\n        operationVersion: number,\n    ): Promise<void> {\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            throw new Error(\n                `Indicator instance ${instanceId} no longer exists.`,\n            );\n        }\n\n        const symbol = (\n            this.tickerInput\n                .value\n                .trim()\n                .toUpperCase()\n        );\n\n        const timeframe =\n            this.timeframeSelect.value;\n\n        const result = isScriptIndicator(instance.indicatorId)\n            ? await this.executeScript(instance.indicatorId, params, signal)\n            : await this.labApi.fetchIndicator({\n                indicatorId: instance.indicatorId, symbol, timeframe, params,\n                source: this.buildIndicatorSourceRecipe(instance.source, new Set([instanceId])),\n            }, signal);\n\n        if (\n            signal.aborted\n            || operationVersion !==\n                this.indicatorRequestVersion\n        ) {\n            return;\n        }\n\n        if (\n            result.indicator.id !==\n            instance.indicatorId\n        ) {\n            throw new Error(\n                `Requested ${instance.indicatorId}, `\n                + \"but backend returned \"\n                + `${result.indicator.id}.`,\n            );\n        }\n\n        instance.title = result.indicator.title;\n        instance.params = Object.fromEntries(\n            result.parameters.map(\n                (parameter) => [\n                    parameter.id,\n                    parameter.value,\n                ],\n            ),\n        );\n        instance.parameters = result.parameters;\n        instance.plots = result.plots;\n        instance.pane =\n            result.indicator.pane !== false;\n        instance.loaded = true;\n\n        let targetChart: IChartApi;\n        let targetPane: IndicatorPane | null = null;\n\n        /*\n         * Manual placement wins over the indicator's default pane preference.\n         * This prevents recalculation from recreating an empty original pane\n         * after its line has been dragged somewhere else.\n         */\n        const existingChart =\n            this.seriesManager\n                .getFirstIndicatorChart(\n                    instanceId,\n                );\n\n        if (existingChart) {\n            targetChart = existingChart;\n\n            for (const slot of this.panesByIndicator.values()) {\n                if (slot.pane.chart === existingChart) {\n                    targetPane = slot.pane;\n                    break;\n                }\n            }\n        } else if (instance.pane) {\n            const slot =\n                this.getOrCreateIndicatorPane(\n                    instanceId,\n                );\n\n            targetPane = slot.pane;\n            targetChart = slot.pane.chart;\n        } else {\n            targetChart = this.chart;\n        }\n\n        const mainRangeBeforeUpdate =\n            this.chart\n                .timeScale()\n                .getVisibleLogicalRange();\n\n        const updatePlots = () => {\n            this.seriesManager.setPlots(\n                instanceId,\n                result.plots,\n                targetChart,\n            );\n        };\n\n        if (targetPane) {\n            targetPane\n                .updateIndicatorWithoutMovingMain(\n                    updatePlots,\n                );\n        } else {\n            updatePlots();\n        }\n\n        if (mainRangeBeforeUpdate) {\n            this.chart\n                .timeScale()\n                .setVisibleLogicalRange(\n                    mainRangeBeforeUpdate,\n                );\n\n            this.syncAllPanesFromMain();\n        }\n\n        this.cleanupEmptyIndicatorPanes();\n\n        if (instance.barColors?.length || result.barColors?.length) {\n            instance.barColors = result.barColors;\n            this.refreshScriptBarColors();\n        }\n\n        if (\n            this.activeIndicatorInstanceId\n            === instanceId\n        ) {\n            this.activeIndicatorId =\n                instance.indicatorId;\n            this.indicatorTitle.textContent =\n                this.indicatorInstanceLabel(\n                    instance,\n                );\n\n            this.renderIndicatorControls(\n                instanceId,\n            );\n\n            this.indicatorReady = true;\n        }\n\n        this.refreshAllLineLegends();\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:state\", { bubbles: true }));\n\n        console.log(\n            `${this.indicatorInstanceLabel(instance)} metrics:`,\n            result.metrics,\n        );\n    }\n\n\n    private async executeIndicatorInstances(\n        order: string[],\n        options?: {\n            rootInstanceId?: string;\n            rootParams?: Record<string, IndicatorParameterValue>;\n            rootUsesBackendDefaults?: boolean;\n        },\n    ): Promise<void> {\n        if (order.length === 0) {\n            return;\n        }\n\n        this.cancelIndicatorRequest();\n\n        const operationVersion =\n            ++this.indicatorRequestVersion;\n\n        const abortController =\n            new AbortController();\n\n        this.indicatorAbortController =\n            abortController;\n        this.indicatorBusy = true;\n        this.syncIndicatorActionState();\n\n        let currentInstanceId: string | null = null;\n\n        try {\n            for (const instanceId of order) {\n                if (\n                    operationVersion !==\n                        this.indicatorRequestVersion\n                    || abortController.signal.aborted\n                ) {\n                    return;\n                }\n\n                currentInstanceId = instanceId;\n\n                const instance =\n                    this.indicatorInstances.get(\n                        instanceId,\n                    );\n\n                if (!instance) {\n                    continue;\n                }\n\n                let params = instance.params;\n\n                if (\n                    instanceId ===\n                    options?.rootInstanceId\n                ) {\n                    params = (\n                        options.rootUsesBackendDefaults\n                            ? undefined\n                            : options.rootParams\n                    );\n                }\n\n                await this.fetchAndRenderIndicatorInstance(\n                    instanceId,\n                    params,\n                    abortController.signal,\n                    operationVersion,\n                );\n            }\n        } catch (error) {\n            if (!isAbortError(error)) {\n                console.error(\n                    \"Indicator graph calculation failed:\",\n                    error,\n                );\n\n                if (\n                    currentInstanceId !== null\n                    && currentInstanceId ===\n                        this.activeIndicatorInstanceId\n                ) {\n                    this.indicatorReady = false;\n                    this.indicatorTitle.textContent =\n                        \"Indicator failed\";\n\n                    const message = (\n                        error instanceof Error\n                            ? error.message\n                            : \"The indicator could not be loaded.\"\n                    );\n\n                    if (isScriptPreview(this.indicatorInstances.get(currentInstanceId)?.indicatorId ?? \"\")) {\n                        this.previewError = message;\n                    }\n                    this.showIndicatorMessage(message);\n                }\n            }\n        } finally {\n            if (\n                operationVersion ===\n                this.indicatorRequestVersion\n            ) {\n                this.indicatorBusy = false;\n\n                if (\n                    this.indicatorAbortController\n                    === abortController\n                ) {\n                    this.indicatorAbortController =\n                        null;\n                }\n\n                this.syncIndicatorActionState();\n            }\n        }\n    }\n\n\n    private async recalculateAllIndicatorInstances(): Promise<void> {\n        if (this.indicatorInstances.size === 0) {\n            return;\n        }\n\n        const order =\n            this.getIndicatorTopologicalOrder();\n\n        await this.executeIndicatorInstances(\n            order,\n        );\n    }\n\n\n    private async runIndicator(\n        useBackendDefaults: boolean,\n    ): Promise<void> {\n        const instanceId =\n            this.activeIndicatorInstanceId;\n\n        if (!instanceId) {\n            return;\n        }\n\n        const instance =\n            this.indicatorInstances.get(\n                instanceId,\n            );\n\n        if (!instance) {\n            return;\n        }\n\n        if (this.candles.length === 0) {\n            return;\n        }\n\n        let params:\n            Record<string, IndicatorParameterValue>\n            | undefined;\n\n        if (!useBackendDefaults) {\n            try {\n                const values =\n                    this.indicatorControls\n                        .getValues();\n\n                const sourceValue =\n                    values[SOURCE_PARAMETER_ID];\n\n                if (!isScriptIndicator(instance.indicatorId)) {\n                    instance.source = this.parseIndicatorSourceSelection(sourceValue, instanceId);\n                    delete values[SOURCE_PARAMETER_ID];\n                }\n                params = values;\n            } catch (error) {\n                console.error(\n                    \"Invalid indicator parameters:\",\n                    error,\n                );\n                return;\n            }\n        }\n\n        const order = [\n            instanceId,\n            ...this.getIndicatorDescendantOrder(\n                instanceId,\n            ),\n        ];\n\n        await this.executeIndicatorInstances(\n            order,\n            {\n                rootInstanceId: instanceId,\n                rootParams: params,\n                rootUsesBackendDefaults:\n                    useBackendDefaults,\n            },\n        );\n    }\n\n\n    private scheduleLiveIndicatorRun(): void {\n        if (\n            !this.activeIndicatorId ||\n            !this.indicatorReady ||\n            !this.indicatorLiveInput.checked\n        ) {\n            return;\n        }\n\n        if (this.indicatorTimer !== null) {\n            window.clearTimeout(\n                this.indicatorTimer,\n            );\n        }\n\n        this.indicatorTimer =\n            window.setTimeout(\n                () => {\n                    this.indicatorTimer = null;\n\n                    void this.runIndicator(\n                        false,\n                    );\n                },\n                250,\n            );\n    }\n\n\n    private cancelIndicatorRequest(): void {\n        if (this.indicatorTimer !== null) {\n            window.clearTimeout(\n                this.indicatorTimer,\n            );\n\n            this.indicatorTimer = null;\n        }\n\n        this.indicatorRequestVersion += 1;\n\n        this.indicatorAbortController\n            ?.abort();\n\n        this.indicatorAbortController =\n            null;\n\n        this.indicatorBusy = false;\n\n        this.syncIndicatorActionState();\n    }\n\n\n    public removeAllIndicators(): void {\n        if (!this.indicatorInstances.size) { this.notify(\"There are no indicators to remove.\"); return; }\n        const logical = this.chart.timeScale().getVisibleLogicalRange();\n        const priceScale = this.candleSeries.priceScale();\n        const manualPriceRange = priceScale.options().autoScale ? null : priceScale.getVisibleRange();\n        this.cancelIndicatorRequest();\n        this.seriesManager.clearAllIndicators();\n        this.indicatorInstances.clear();\n        if (this.scriptBarColors.size) this.refreshScriptBarColors();\n        this.activeIndicatorId = null;\n        this.activeIndicatorInstanceId = null;\n        this.indicatorReady = false;\n        this.clearAllIndicatorPanes();\n        this.showNoIndicatorSelected();\n        if (logical) this.chart.timeScale().setVisibleLogicalRange(logical);\n        if (manualPriceRange) priceScale.setVisibleRange(manualPriceRange);\n        this.syncAllPanesFromMain();\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:state\", { bubbles: true }));\n        this.notify(\"All indicators removed from this chart.\");\n    }\n\n    private clearActivePlots(): void {\n        if (this.activeIndicatorInstanceId) this.removeIndicatorInstance(this.activeIndicatorInstanceId);\n    }\n\n    private removeIndicatorInstance(rootInstanceId: string): void {\n        const removed = this.indicatorInstances.get(rootInstanceId);\n        if (!removed) return;\n        const logicalRange = this.chart.timeScale().getVisibleLogicalRange();\n        const priceScale = this.candleSeries.priceScale();\n        const manualPriceRange = priceScale.options().autoScale ? null : priceScale.getVisibleRange();\n\n        this.cancelIndicatorRequest();\n\n        // A child cannot remain meaningful after its source disappears.\n        // Remove the selected node and all descendants, children first.\n        const toRemove =\n            this.getIndicatorTopologicalOrder()\n                .filter(\n                    (instanceId) => (\n                        instanceId === rootInstanceId\n                        || this.instanceDependsOn(\n                            instanceId,\n                            rootInstanceId,\n                        )\n                    ),\n                )\n                .reverse();\n\n        for (const instanceId of toRemove) {\n            const paneSlot =\n                this.panesByIndicator.get(\n                    instanceId,\n                );\n\n            if (paneSlot) {\n                paneSlot.pane\n                    .updateIndicatorWithoutMovingMain(\n                        () => {\n                            this.seriesManager\n                                .clearIndicator(\n                                    instanceId,\n                                );\n                        },\n                    );\n            } else {\n                this.seriesManager\n                    .clearIndicator(\n                        instanceId,\n                    );\n            }\n\n            this.removeIndicatorPane(\n                instanceId,\n            );\n\n            this.indicatorInstances.delete(\n                instanceId,\n            );\n        }\n\n        if (this.scriptBarColors.size) this.refreshScriptBarColors();\n        this.refreshAllLineLegends();\n\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:state\", { bubbles: true }));\n        const remaining =\n            [...this.indicatorInstances.keys()];\n\n        const nextInstanceId = this.activeIndicatorInstanceId && this.indicatorInstances.has(this.activeIndicatorInstanceId)\n            ? this.activeIndicatorInstanceId\n            : remaining[remaining.length - 1];\n\n        if (nextInstanceId) {\n            this.activateIndicatorInstance(\n                nextInstanceId,\n            );\n        } else {\n            this.activeIndicatorInstanceId = null;\n            this.activeIndicatorId = null;\n            this.showNoIndicatorSelected();\n        }\n        if (logicalRange) this.chart.timeScale().setVisibleLogicalRange(logicalRange);\n        if (manualPriceRange) priceScale.setVisibleRange(manualPriceRange);\n        this.syncAllPanesFromMain();\n        const dependents = toRemove.length - 1;\n        this.notify(dependents ? `Deleted ${removed.title} and ${dependents} dependent indicator(s).` : `Deleted ${removed.title}.`);\n    }\n\n\n    private showNoIndicatorSelected(): void {\n        this.indicatorReady = false;\n\n        this.indicatorTitle.textContent =\n            \"Choose Indicator\";\n\n        this.refreshAllLineLegends();\n\n        this.showIndicatorMessage(\n            \"Select an available indicator above.\",\n        );\n\n        this.syncIndicatorActionState();\n    }\n\n\n    private showIndicatorLoading(\n        message: string,\n    ): void {\n        this.indicatorTitle.textContent =\n            \"Loading indicator…\";\n\n        this.showIndicatorMessage(\n            message,\n        );\n\n        this.syncIndicatorActionState();\n    }\n\n\n    private showIndicatorMessage(\n        message: string,\n    ): void {\n        this.indicatorControls.clear();\n\n        const element =\n            document.createElement(\"div\");\n\n        element.className =\n            \"indicator-controls-empty\";\n\n        element.textContent = message;\n\n        this.indicatorControlsContainer.append(\n            element,\n        );\n    }\n\n\n    private syncIndicatorActionState(): void {\n        const hasIndicator =\n            this.activeIndicatorId !== null;\n\n        const hasCandles =\n            this.candles.length > 0;\n\n        const canRequest = (\n            hasIndicator &&\n            hasCandles\n        );\n\n        this.applyIndicatorButton.disabled = (\n            !canRequest ||\n            this.indicatorBusy\n        );\n\n        this.clearIndicatorButton.disabled = (\n            !hasIndicator ||\n            this.indicatorBusy\n        );\n\n        this.indicatorLiveInput.disabled = (\n            !canRequest ||\n            !this.indicatorReady ||\n            this.indicatorBusy\n        );\n\n        this.indicatorControls.setDisabled(\n            !this.indicatorReady ||\n            this.indicatorBusy,\n        );\n    }\n\n\n    public toggleTheme(): void {\n        const theme = this.activeTheme === \"dark\" ? \"light\" : \"dark\";\n        this.setTheme(theme);\n        this.chartContainer.dispatchEvent(new CustomEvent(\"chartix:theme\", { bubbles: true, detail: theme }));\n    }\n\n\n    private createTypingOverlay(): void {\n        this.chartContainer.tabIndex = 0;\n\n        this.chartContainer.style.position =\n            \"relative\";\n\n        this.chartContainer.style.outline =\n            \"none\";\n\n        this.typingBox =\n            document.createElement(\"div\");\n\n        Object.assign(\n            this.typingBox.style,\n            {\n                position: \"absolute\",\n                top: \"50%\",\n                left: \"50%\",\n\n                transform:\n                    \"translate(-50%, -50%)\",\n\n                minWidth: \"220px\",\n\n                padding: \"14px 20px\",\n\n                background:\n                    \"rgba(28, 32, 58, 1)\",\n\n                color: \"#fff\",\n                fontSize: \"18px\",\n                fontFamily: \"monospace\",\n\n                borderRadius: \"8px\",\n                textAlign: \"center\",\n\n                display: \"none\",\n                pointerEvents: \"none\",\n\n                zIndex: \"50\",\n            },\n        );\n\n        this.chartContainer.appendChild(\n            this.typingBox,\n        );\n    }\n\n\n    private handleChartTyping(\n        event: KeyboardEvent,\n    ): void {\n        if (event.ctrlKey || event.metaKey || event.altKey) return;\n        if (\n            event.key === \"Escape\" &&\n            this.isTyping\n        ) {\n            this.resetTyping();\n            event.preventDefault();\n            return;\n        }\n\n        if (\n            event.key === \"Enter\" &&\n            this.isTyping\n        ) {\n            const symbol =\n                this.typingBuffer.trim();\n\n            if (symbol) {\n                void this.loadSymbol(\n                    symbol.toUpperCase(),\n                );\n            }\n\n            this.resetTyping();\n\n            event.preventDefault();\n            return;\n        }\n\n        if (\n            event.key === \"Backspace\" &&\n            this.isTyping\n        ) {\n            this.typingBuffer =\n                this.typingBuffer.slice(\n                    0,\n                    -1,\n                );\n\n            this.typingBox.textContent =\n                this.typingBuffer || \"\";\n\n            event.preventDefault();\n            return;\n        }\n\n        if (\n            event.key.length === 1 &&\n            /^[a-zA-Z0-9._-]$/.test(\n                event.key,\n            )\n        ) {\n            if (!this.isTyping) {\n                this.isTyping = true;\n\n                this.typingBox.style.display =\n                    \"block\";\n            }\n\n            this.typingBuffer += event.key;\n\n            this.typingBox.textContent =\n                this.typingBuffer;\n        }\n    }\n\n\n    private resetTyping(): void {\n        this.typingBuffer = \"\";\n        this.isTyping = false;\n\n        this.typingBox.textContent = \"\";\n\n        this.typingBox.style.display =\n            \"none\";\n    }\n}\n","import { toolIcon, type ToolIcon } from \"./workspace/ToolIcons\";\r\nexport interface IndicatorSettingsPanelIds {\r\n    title: string;\r\n    controls: string;\r\n    liveInput: string;\r\n    applyButton: string;\r\n    clearButton: string;\r\n}\r\n\r\nexport interface IndicatorSettingsPanelOptions {\r\n    mountId: string;\r\n    initialTitle?: string;\r\n    ids?: Partial<IndicatorSettingsPanelIds>;\r\n}\r\n\r\nconst DEFAULT_IDS: IndicatorSettingsPanelIds = {\r\n    title: \"indicatorTitle\",\r\n    controls: \"indicatorControls\",\r\n    liveInput: \"blackmanLive\",\r\n    applyButton: \"applyBlackmanBtn\",\r\n    clearButton: \"clearBlackmanBtn\",\r\n};\r\n\r\nconst STYLE_ELEMENT_ID = \"indicator-settings-panel-styles\";\r\n\r\nfunction requireElement<T extends HTMLElement>(\r\n    id: string,\r\n): T {\r\n    const element = document.getElementById(id);\r\n\r\n    if (!element) {\r\n        throw new Error(\r\n            `Missing required element: #${id}`,\r\n        );\r\n    }\r\n\r\n    return element as T;\r\n}\r\n\r\nfunction createElement<\r\n    K extends keyof HTMLElementTagNameMap\r\n>(\r\n    tagName: K,\r\n    className?: string,\r\n    textContent?: string,\r\n): HTMLElementTagNameMap[K] {\r\n    const element = document.createElement(tagName);\r\n\r\n    if (className) {\r\n        element.className = className;\r\n    }\r\n\r\n    if (textContent !== undefined) {\r\n        element.textContent = textContent;\r\n    }\r\n\r\n    return element;\r\n}\r\n\r\nfunction appendIcon(parent: HTMLElement, name: ToolIcon): void {\r\n    const icon = createElement(\"span\", \"indicator-local-icon\");\r\n    icon.innerHTML = toolIcon(name);\r\n    parent.append(icon);\r\n}\r\n\r\nfunction injectStyles(): void {\r\n    if (\r\n        document.getElementById(\r\n            STYLE_ELEMENT_ID,\r\n        )\r\n    ) {\r\n        return;\r\n    }\r\n\r\n    const style = document.createElement(\"style\");\r\n\r\n    style.id = STYLE_ELEMENT_ID;\r\n\r\n    style.textContent = `\r\n        .indicator-menu {\r\n            position: relative;\r\n            flex: none;\r\n        }\r\n\r\n        .indicator-menu > summary {\r\n            list-style: none;\r\n        }\r\n\r\n        .indicator-menu > summary::-webkit-details-marker {\r\n            display: none;\r\n        }\r\n\r\n        /* =========================================================\r\n           Toolbar button\r\n           ========================================================= */\r\n\r\n        .indicator-menu-button {\r\n            min-width: 190px;\r\n            height: 46px;\r\n\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 10px;\r\n\r\n            padding: 0 13px;\r\n\r\n            border: 1px solid hsl(var(--bc) / 0.12);\r\n            border-radius: 11px;\r\n\r\n            background: hsl(var(--b1));\r\n            color: hsl(var(--bc));\r\n\r\n            box-shadow:\r\n                0 1px 3px rgba(0, 0, 0, 0.05),\r\n                0 4px 12px rgba(0, 0, 0, 0.06);\r\n\r\n            cursor: pointer;\r\n\r\n            transition:\r\n                border-color 150ms ease,\r\n                box-shadow 150ms ease,\r\n                transform 150ms ease;\r\n        }\r\n\r\n        .indicator-menu-button:hover {\r\n            border-color: hsl(var(--p) / 0.45);\r\n\r\n            box-shadow:\r\n                0 3px 8px rgba(0, 0, 0, 0.07),\r\n                0 8px 20px rgba(0, 0, 0, 0.09);\r\n\r\n            transform: translateY(-1px);\r\n        }\r\n\r\n        .indicator-menu-button:active {\r\n            transform: translateY(0);\r\n        }\r\n\r\n        .indicator-button-icon {\r\n            width: 32px;\r\n            height: 32px;\r\n            flex: none;\r\n\r\n            display: grid;\r\n            place-items: center;\r\n\r\n            border-radius: 8px;\r\n\r\n            background: hsl(var(--p) / 0.12);\r\n            color: hsl(var(--p));\r\n\r\n            font-size: 14px;\r\n        }\r\n\r\n        .indicator-button-copy {\r\n            min-width: 0;\r\n            flex: 1;\r\n\r\n            display: flex;\r\n            flex-direction: column;\r\n            align-items: flex-start;\r\n\r\n            line-height: 1.08;\r\n        }\r\n\r\n        .indicator-button-label {\r\n            margin-bottom: 3px;\r\n\r\n            font-size: 9.5px;\r\n            font-weight: 700;\r\n            letter-spacing: 0.08em;\r\n            text-transform: uppercase;\r\n\r\n            opacity: 0.52;\r\n        }\r\n\r\n        .indicator-menu-title {\r\n            max-width: 116px;\r\n\r\n            overflow: hidden;\r\n\r\n            font-size: 13.5px;\r\n            font-weight: 750;\r\n\r\n            text-overflow: ellipsis;\r\n            white-space: nowrap;\r\n        }\r\n\r\n        .indicator-chevron {\r\n            flex: none;\r\n\r\n            font-size: 9.5px;\r\n\r\n            opacity: 0.48;\r\n\r\n            transition: transform 180ms ease;\r\n        }\r\n\r\n        .indicator-menu[open] .indicator-chevron {\r\n            transform: rotate(180deg);\r\n        }\r\n\r\n        /* =========================================================\r\n           Floating panel\r\n           ========================================================= */\r\n\r\n        .indicator-settings-panel {\r\n            position: absolute;\r\n            top: calc(100% + 9px);\r\n            right: 0;\r\n            z-index: 1000;\r\n\r\n            width: 450px;\r\n            max-width: calc(100vw - 32px);\r\n\r\n            height: min(\r\n                720px,\r\n                calc(100vh - 140px)\r\n            );\r\n\r\n            max-height: calc(100vh - 140px);\r\n\r\n            display: flex;\r\n            flex-direction: column;\r\n\r\n            overflow: hidden;\r\n\r\n            border: 1px solid hsl(var(--bc) / 0.12);\r\n            border-radius: 15px;\r\n\r\n            background: hsl(var(--b1));\r\n\r\n            box-shadow:\r\n                0 22px 58px rgba(0, 0, 0, 0.21),\r\n                0 5px 16px rgba(0, 0, 0, 0.09);\r\n\r\n            transform-origin: top right;\r\n\r\n            animation: indicator-panel-open 140ms ease-out;\r\n        }\r\n\r\n        @keyframes indicator-panel-open {\r\n            from {\r\n                opacity: 0;\r\n\r\n                transform:\r\n                    translateY(-5px)\r\n                    scale(0.988);\r\n            }\r\n\r\n            to {\r\n                opacity: 1;\r\n\r\n                transform:\r\n                    translateY(0)\r\n                    scale(1);\r\n            }\r\n        }\r\n\r\n        /* =========================================================\r\n           Header\r\n           ========================================================= */\r\n\r\n        .indicator-panel-header {\r\n            flex: none;\r\n\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 11px;\r\n\r\n            padding: 12px 16px;\r\n\r\n            border-bottom:\r\n                1px solid\r\n                hsl(var(--bc) / 0.075);\r\n\r\n            background:\r\n                linear-gradient(\r\n                    135deg,\r\n                    hsl(var(--p) / 0.09),\r\n                    hsl(var(--p) / 0.015) 55%,\r\n                    transparent\r\n                );\r\n        }\r\n\r\n        .indicator-panel-header-icon {\r\n            width: 34px;\r\n            height: 34px;\r\n            flex: none;\r\n\r\n            display: grid;\r\n            place-items: center;\r\n\r\n            border-radius: 9px;\r\n\r\n            background: hsl(var(--p));\r\n            color: hsl(var(--pc));\r\n\r\n            font-size: 14px;\r\n\r\n            box-shadow:\r\n                0 5px 14px\r\n                hsl(var(--p) / 0.18);\r\n        }\r\n\r\n        .indicator-panel-header-copy {\r\n            min-width: 0;\r\n            flex: 1;\r\n        }\r\n\r\n        .indicator-panel-title {\r\n            margin: 0;\r\n\r\n            font-size: 15px;\r\n            font-weight: 800;\r\n            line-height: 1.15;\r\n        }\r\n\r\n        .indicator-panel-description {\r\n            margin-top: 3px;\r\n\r\n            font-size: 8.5px;\r\n            font-weight: 500;\r\n            line-height: 1.25;\r\n\r\n            opacity: 0.48;\r\n        }\r\n\r\n        .indicator-backend-badge {\r\n            flex: none;\r\n\r\n            padding: 4px 8px;\r\n\r\n            border:\r\n                1px solid\r\n                hsl(var(--su) / 0.22);\r\n\r\n            border-radius: 999px;\r\n\r\n            background:\r\n                hsl(var(--su) / 0.07);\r\n\r\n            color: hsl(var(--su));\r\n\r\n            font-size: 8px;\r\n            font-weight: 800;\r\n            letter-spacing: 0.06em;\r\n            text-transform: uppercase;\r\n        }\r\n\r\n        /* =========================================================\r\n           Always-visible action area\r\n           ========================================================= */\r\n\r\n        .indicator-panel-actions-bar {\r\n            position: relative;\r\n            z-index: 20;\r\n\r\n            flex: none;\r\n\r\n            padding: 9px 16px 10px;\r\n\r\n            border-bottom:\r\n                1px solid\r\n                hsl(var(--bc) / 0.09);\r\n\r\n            background:\r\n                hsl(var(--b1));\r\n\r\n            box-shadow:\r\n                0 8px 18px\r\n                rgba(0, 0, 0, 0.05);\r\n        }\r\n\r\n        .indicator-actions {\r\n            display: grid;\r\n            grid-template-columns: 1fr 1fr;\r\n            gap: 8px;\r\n        }\r\n\r\n        .indicator-actions .btn {\r\n            height: 36px;\r\n            min-height: 36px;\r\n\r\n            border-radius: 8px;\r\n\r\n            font-size: 11.5px;\r\n        }\r\n\r\n        .indicator-live-row {\r\n            display: flex;\r\n            align-items: center;\r\n            justify-content: space-between;\r\n            gap: 14px;\r\n\r\n            margin-top: 8px;\r\n            padding: 6px 9px;\r\n\r\n            border:\r\n                1px solid\r\n                hsl(var(--bc) / 0.075);\r\n\r\n            border-radius: 8px;\r\n\r\n            background:\r\n                hsl(var(--b2) / 0.28);\r\n\r\n            cursor: pointer;\r\n\r\n            transition:\r\n                border-color 150ms ease,\r\n                background-color 150ms ease;\r\n        }\r\n\r\n        .indicator-live-row:hover {\r\n            border-color:\r\n                hsl(var(--p) / 0.20);\r\n        }\r\n\r\n        .indicator-live-copy {\r\n            min-width: 0;\r\n        }\r\n\r\n        .indicator-live-title {\r\n            display: block;\r\n\r\n            font-size: 10.5px;\r\n            font-weight: 800;\r\n            line-height: 1.15;\r\n        }\r\n\r\n        .indicator-live-description {\r\n            display: block;\r\n\r\n            margin-top: 2px;\r\n\r\n            font-size: 7.5px;\r\n            font-weight: 500;\r\n            line-height: 1.15;\r\n\r\n            opacity: 0.44;\r\n        }\r\n\r\n        .indicator-live-row .toggle {\r\n            width: 38px;\r\n            height: 21px;\r\n            min-height: 21px;\r\n        }\r\n\r\n        /* =========================================================\r\n           Scrollable parameter body\r\n           ========================================================= */\r\n\r\n        .indicator-panel-body {\r\n            flex: 1 1 auto;\r\n            min-height: 0;\r\n\r\n            overflow-y: auto;\r\n            overflow-x: hidden;\r\n            overscroll-behavior: contain;\r\n\r\n            padding: 10px 16px 14px;\r\n\r\n            scrollbar-width: thin;\r\n\r\n            scrollbar-color:\r\n                hsl(var(--bc) / 0.18)\r\n                transparent;\r\n        }\r\n\r\n        .indicator-panel-body::-webkit-scrollbar {\r\n            width: 5px;\r\n        }\r\n\r\n        .indicator-panel-body::-webkit-scrollbar-track {\r\n            background: transparent;\r\n        }\r\n\r\n        .indicator-panel-body::-webkit-scrollbar-thumb {\r\n            border-radius: 999px;\r\n\r\n            background:\r\n                hsl(var(--bc) / 0.15);\r\n        }\r\n\r\n        .indicator-section-label {\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 7px;\r\n\r\n            margin-bottom: 3px;\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.50);\r\n\r\n            font-size: 8.5px;\r\n            font-weight: 800;\r\n            letter-spacing: 0.09em;\r\n            text-transform: uppercase;\r\n        }\r\n\r\n        .indicator-section-label::after {\r\n            content: \"\";\r\n\r\n            height: 1px;\r\n            flex: 1;\r\n\r\n            background:\r\n                hsl(var(--bc) / 0.07);\r\n        }\r\n\r\n        .indicator-controls-container {\r\n            width: 100%;\r\n\r\n            display: flex;\r\n            flex-direction: column;\r\n\r\n            gap: 0;\r\n        }\r\n\r\n        .indicator-controls-empty {\r\n            padding: 15px;\r\n\r\n            border:\r\n                1px dashed\r\n                hsl(var(--bc) / 0.13);\r\n\r\n            border-radius: 9px;\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.43);\r\n\r\n            font-size: 9.5px;\r\n            text-align: center;\r\n        }\r\n\r\n        /* =========================================================\r\n           Parameter rows\r\n           ========================================================= */\r\n\r\n        .indicator-param-row {\r\n            display: grid;\r\n\r\n            grid-template-columns:\r\n                104px\r\n                minmax(0, 1fr);\r\n\r\n            grid-template-areas:\r\n                \"label control\"\r\n                \". description\";\r\n\r\n            align-items: center;\r\n\r\n            column-gap: 13px;\r\n            row-gap: 2px;\r\n\r\n            min-width: 0;\r\n\r\n            padding: 7px 3px 8px;\r\n\r\n            border: 0;\r\n\r\n            border-bottom:\r\n                1px solid\r\n                hsl(var(--bc) / 0.065);\r\n\r\n            border-radius: 0;\r\n\r\n            background: transparent;\r\n\r\n            transition:\r\n                background-color 140ms ease,\r\n                padding-left 140ms ease,\r\n                padding-right 140ms ease;\r\n        }\r\n\r\n        .indicator-param-row:last-child {\r\n            border-bottom: 0;\r\n        }\r\n\r\n        .indicator-param-row:hover {\r\n            margin-left: -5px;\r\n            margin-right: -5px;\r\n\r\n            padding-left: 8px;\r\n            padding-right: 8px;\r\n\r\n            border-radius: 7px;\r\n\r\n            background:\r\n                hsl(var(--b2) / 0.42);\r\n        }\r\n\r\n        .indicator-param-label {\r\n            grid-area: label;\r\n\r\n            min-width: 0;\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.76);\r\n\r\n            font-size: 11.5px;\r\n            font-weight: 730;\r\n            line-height: 1.2;\r\n        }\r\n\r\n        /* =========================================================\r\n           Inputs and selections\r\n           ========================================================= */\r\n\r\n        .indicator-param-row\r\n        > input:not([type=\"checkbox\"]),\r\n        .indicator-param-row\r\n        > select {\r\n            grid-area: control;\r\n\r\n            width: 100%;\r\n            height: 34px;\r\n            min-height: 34px;\r\n\r\n            padding: 0 10px;\r\n\r\n            border:\r\n                1px solid\r\n                hsl(var(--bc) / 0.14);\r\n\r\n            border-radius: 8px;\r\n\r\n            background: hsl(var(--b1));\r\n            color: hsl(var(--bc));\r\n\r\n            font-size: 12px;\r\n            font-weight: 650;\r\n\r\n            outline: none;\r\n\r\n            transition:\r\n                border-color 140ms ease,\r\n                box-shadow 140ms ease,\r\n                background-color 140ms ease;\r\n        }\r\n\r\n        .indicator-param-row\r\n        > input:not([type=\"checkbox\"]):hover,\r\n        .indicator-param-row\r\n        > select:hover {\r\n            border-color:\r\n                hsl(var(--bc) / 0.23);\r\n        }\r\n\r\n        .indicator-param-row\r\n        > input:not([type=\"checkbox\"]):focus,\r\n        .indicator-param-row\r\n        > select:focus {\r\n            border-color:\r\n                hsl(var(--p));\r\n\r\n            box-shadow:\r\n                0 0 0 2px\r\n                hsl(var(--p) / 0.10);\r\n        }\r\n\r\n        /* =========================================================\r\n           Descriptions\r\n           ========================================================= */\r\n\r\n        .indicator-param-description {\r\n            grid-area: description;\r\n\r\n            position: relative;\r\n\r\n            margin: 0;\r\n            padding-left: 11px;\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.40);\r\n\r\n            font-size: 8px;\r\n            font-weight: 500;\r\n            line-height: 1.2;\r\n        }\r\n\r\n        .indicator-param-description::before {\r\n            content: \"\\\\f05a\";\r\n\r\n            position: absolute;\r\n            top: 1px;\r\n            left: 0;\r\n\r\n            color:\r\n                hsl(var(--p) / 0.52);\r\n\r\n            font-family:\r\n                \"Font Awesome 6 Free\";\r\n\r\n            font-size: 7.5px;\r\n            font-weight: 900;\r\n        }\r\n\r\n        /* =========================================================\r\n           Boolean controls\r\n           ========================================================= */\r\n\r\n        .indicator-param-row\r\n        > input[type=\"checkbox\"] {\r\n            grid-area: control;\r\n\r\n            justify-self: end;\r\n\r\n            width: 18px;\r\n            height: 18px;\r\n\r\n            margin-right: 3px;\r\n\r\n            accent-color:\r\n                hsl(var(--p));\r\n\r\n            cursor: pointer;\r\n        }\r\n\r\n        .indicator-param-row:has(\r\n            > input[type=\"checkbox\"]\r\n        ) {\r\n            min-height: 43px;\r\n        }\r\n\r\n        /* =========================================================\r\n           Responsive layout\r\n           ========================================================= */\r\n\r\n        @media (max-width: 780px) {\r\n            .indicator-menu {\r\n                width: 100%;\r\n            }\r\n\r\n            .indicator-menu-button {\r\n                width: 100%;\r\n            }\r\n\r\n            .indicator-settings-panel {\r\n                position: fixed;\r\n\r\n                top: 68px;\r\n                right: 14px;\r\n                left: 14px;\r\n\r\n                width: auto;\r\n                max-width: none;\r\n\r\n                height:\r\n                    calc(100vh - 84px);\r\n\r\n                max-height:\r\n                    calc(100vh - 84px);\r\n\r\n                transform-origin:\r\n                    top center;\r\n            }\r\n        }\r\n\r\n        @media (max-width: 540px) {\r\n            .indicator-panel-header {\r\n                padding: 11px 14px;\r\n            }\r\n\r\n            .indicator-panel-actions-bar {\r\n                padding: 8px 14px 9px;\r\n            }\r\n\r\n            .indicator-panel-body {\r\n                padding: 9px 14px 12px;\r\n            }\r\n\r\n            .indicator-backend-badge {\r\n                display: none;\r\n            }\r\n\r\n            .indicator-param-row {\r\n                grid-template-columns: 1fr;\r\n\r\n                grid-template-areas:\r\n                    \"label\"\r\n                    \"control\"\r\n                    \"description\";\r\n\r\n                row-gap: 4px;\r\n\r\n                padding: 7px 2px 8px;\r\n            }\r\n\r\n            .indicator-param-row:hover {\r\n                margin-left: -4px;\r\n                margin-right: -4px;\r\n\r\n                padding-left: 6px;\r\n                padding-right: 6px;\r\n            }\r\n\r\n            .indicator-param-row\r\n            > input[type=\"checkbox\"] {\r\n                justify-self: start;\r\n            }\r\n        }\r\n    `;\r\n\r\n    document.head.append(style);\r\n}\r\n\r\nexport class IndicatorSettingsPanel {\r\n    private readonly options:\r\n        IndicatorSettingsPanelOptions;\r\n\r\n    private readonly ids:\r\n        IndicatorSettingsPanelIds;\r\n\r\n    private mountElement:\r\n        HTMLElement | null = null;\r\n\r\n    private rootElement:\r\n        HTMLDetailsElement | null = null;\r\n\r\n    private readonly handleDocumentPointerDown = (\r\n        event: PointerEvent,\r\n    ): void => {\r\n        if (!this.rootElement?.open) {\r\n            return;\r\n        }\r\n\r\n        const target = event.target;\r\n\r\n        if (!(target instanceof Node)) {\r\n            return;\r\n        }\r\n\r\n        if (!this.rootElement.contains(target)) {\r\n            this.rootElement.open = false;\r\n        }\r\n    };\r\n\r\n    private readonly handleDocumentKeyDown = (\r\n        event: KeyboardEvent,\r\n    ): void => {\r\n        if (\r\n            event.key === \"Escape\" &&\r\n            this.rootElement?.open\r\n        ) {\r\n            this.rootElement.open = false;\r\n        }\r\n    };\r\n\r\n    constructor(\r\n        options: IndicatorSettingsPanelOptions,\r\n    ) {\r\n        this.options = options;\r\n\r\n        this.ids = {\r\n            ...DEFAULT_IDS,\r\n            ...options.ids,\r\n        };\r\n    }\r\n\r\n    public mount(): void {\r\n        if (this.rootElement) {\r\n            return;\r\n        }\r\n\r\n        injectStyles();\r\n\r\n        this.mountElement =\r\n            requireElement<HTMLElement>(\r\n                this.options.mountId,\r\n            );\r\n\r\n        this.mountElement.replaceChildren();\r\n\r\n        const root = createElement(\r\n            \"details\",\r\n            \"indicator-menu\",\r\n        );\r\n\r\n        const summary =\r\n            this.createSummary();\r\n\r\n        const panel =\r\n            this.createPanel();\r\n\r\n        root.append(\r\n            summary,\r\n            panel,\r\n        );\r\n\r\n        this.mountElement.append(root);\r\n\r\n        this.rootElement = root;\r\n\r\n        document.addEventListener(\r\n            \"pointerdown\",\r\n            this.handleDocumentPointerDown,\r\n        );\r\n\r\n        document.addEventListener(\r\n            \"keydown\",\r\n            this.handleDocumentKeyDown,\r\n        );\r\n    }\r\n\r\n    public destroy(): void {\r\n        document.removeEventListener(\r\n            \"pointerdown\",\r\n            this.handleDocumentPointerDown,\r\n        );\r\n\r\n        document.removeEventListener(\r\n            \"keydown\",\r\n            this.handleDocumentKeyDown,\r\n        );\r\n\r\n        this.mountElement?.replaceChildren();\r\n\r\n        this.rootElement = null;\r\n        this.mountElement = null;\r\n    }\r\n\r\n    public open(): void {\r\n        if (this.rootElement) {\r\n            this.rootElement.open = true;\r\n        }\r\n    }\r\n\r\n    public close(): void {\r\n        if (this.rootElement) {\r\n            this.rootElement.open = false;\r\n        }\r\n    }\r\n\r\n    private createSummary(): HTMLElement {\r\n        const summary = createElement(\r\n            \"summary\",\r\n            \"indicator-menu-button\",\r\n        );\r\n\r\n        summary.setAttribute(\r\n            \"aria-label\",\r\n            \"Open indicator settings\",\r\n        );\r\n\r\n        const iconWrapper = createElement(\r\n            \"span\",\r\n            \"indicator-button-icon\",\r\n        );\r\n\r\n        iconWrapper.innerHTML = toolIcon(\"sliders\");\r\n\r\n        const copy = createElement(\r\n            \"span\",\r\n            \"indicator-button-copy\",\r\n        );\r\n\r\n        const label = createElement(\r\n            \"span\",\r\n            \"indicator-button-label\",\r\n            \"Indicators\",\r\n        );\r\n\r\n        const title = createElement(\r\n            \"span\",\r\n            \"indicator-menu-title\",\r\n            this.options.initialTitle ??\r\n                \"Loading Indicator...\",\r\n        );\r\n\r\n        title.id = this.ids.title;\r\n        summary.setAttribute(\"aria-describedby\", title.id);\r\n        const showFullTitle = () => { summary.title = title.textContent ?? \"\"; };\r\n        summary.addEventListener(\"pointerenter\", showFullTitle);\r\n        summary.addEventListener(\"focus\", showFullTitle);\r\n\r\n        copy.append(\r\n            label,\r\n            title,\r\n        );\r\n\r\n        const chevron = createElement(\"span\", \"indicator-chevron\");\r\n        chevron.innerHTML = toolIcon(\"down\");\r\n\r\n        chevron.setAttribute(\r\n            \"aria-hidden\",\r\n            \"true\",\r\n        );\r\n\r\n        summary.append(\r\n            iconWrapper,\r\n            copy,\r\n            chevron,\r\n        );\r\n\r\n        return summary;\r\n    }\r\n\r\n    private createPanel(): HTMLElement {\r\n        const panel = createElement(\r\n            \"div\",\r\n            \"indicator-settings-panel\",\r\n        );\r\n\r\n        panel.append(\r\n            this.createHeader(),\r\n            this.createActionsBar(),\r\n            this.createBody(),\r\n        );\r\n\r\n        return panel;\r\n    }\r\n\r\n    private createHeader(): HTMLElement {\r\n        const header = createElement(\r\n            \"div\",\r\n            \"indicator-panel-header\",\r\n        );\r\n\r\n        const iconWrapper = createElement(\r\n            \"div\",\r\n            \"indicator-panel-header-icon\",\r\n        );\r\n\r\n        appendIcon(\r\n            iconWrapper,\r\n            \"activity\",\r\n        );\r\n\r\n        const copy = createElement(\r\n            \"div\",\r\n            \"indicator-panel-header-copy\",\r\n        );\r\n\r\n        const title = createElement(\r\n            \"h2\",\r\n            \"indicator-panel-title\",\r\n            \"Indicator Settings\",\r\n        );\r\n\r\n        const description = createElement(\r\n            \"div\",\r\n            \"indicator-panel-description\",\r\n            \"Choose an indicator, then adjust its settings.\",\r\n        );\r\n\r\n        copy.append(\r\n            title,\r\n            description,\r\n        );\r\n\r\n        const close = createElement(\"button\", \"workspace-button indicator-panel-close\");\r\n        close.type = \"button\";\r\n        close.setAttribute(\"aria-label\", \"Close indicator settings\");\r\n        close.innerHTML = toolIcon(\"close\");\r\n        close.addEventListener(\"click\", () => {\r\n            this.close();\r\n            this.rootElement?.querySelector(\"summary\")?.focus({ preventScroll: true });\r\n        });\r\n        header.append(iconWrapper, copy, close);\r\n\r\n        return header;\r\n    }\r\n\r\n    private createActionsBar(): HTMLElement {\r\n        const actionBar = createElement(\r\n            \"div\",\r\n            \"indicator-panel-actions-bar\",\r\n        );\r\n\r\n        const actions = createElement(\r\n            \"div\",\r\n            \"indicator-actions\",\r\n        );\r\n\r\n        const applyButton = createElement(\r\n            \"button\",\r\n            \"btn btn-primary\",\r\n        );\r\n\r\n        applyButton.id =\r\n            this.ids.applyButton;\r\n\r\n        applyButton.type = \"button\";\r\n\r\n        appendIcon(\r\n            applyButton,\r\n            \"check\",\r\n        );\r\n\r\n        applyButton.append(\r\n            document.createTextNode(\r\n                \"Apply\",\r\n            ),\r\n        );\r\n\r\n        const clearButton = createElement(\r\n            \"button\",\r\n            \"btn btn-ghost\",\r\n        );\r\n\r\n        clearButton.id =\r\n            this.ids.clearButton;\r\n\r\n        clearButton.type = \"button\";\r\n\r\n        appendIcon(\r\n            clearButton,\r\n            \"clear\",\r\n        );\r\n\r\n        clearButton.append(\r\n            document.createTextNode(\r\n                \"Clear\",\r\n            ),\r\n        );\r\n\r\n        actions.append(\r\n            applyButton,\r\n            clearButton,\r\n        );\r\n\r\n        const liveRow = createElement(\r\n            \"label\",\r\n            \"indicator-live-row\",\r\n        );\r\n\r\n        const liveCopy = createElement(\r\n            \"span\",\r\n            \"indicator-live-copy\",\r\n        );\r\n\r\n        const liveTitle = createElement(\r\n            \"span\",\r\n            \"indicator-live-title\",\r\n            \"Live recalculation\",\r\n        );\r\n\r\n        const liveDescription = createElement(\r\n            \"span\",\r\n            \"indicator-live-description\",\r\n            \"Recalculate after parameter values change\",\r\n        );\r\n\r\n        liveCopy.append(\r\n            liveTitle,\r\n            liveDescription,\r\n        );\r\n\r\n        const liveInput = createElement(\r\n            \"input\",\r\n            \"toggle toggle-secondary\",\r\n        );\r\n\r\n        liveInput.id =\r\n            this.ids.liveInput;\r\n\r\n        liveInput.type =\r\n            \"checkbox\";\r\n\r\n        liveInput.checked =\r\n            false;\r\n\r\n        liveRow.append(\r\n            liveCopy,\r\n            liveInput,\r\n        );\r\n\r\n        actionBar.append(\r\n            actions,\r\n            liveRow,\r\n        );\r\n\r\n        return actionBar;\r\n    }\r\n\r\n    private createBody(): HTMLElement {\r\n        const body = createElement(\r\n            \"div\",\r\n            \"indicator-panel-body\",\r\n        );\r\n\r\n        const sectionLabel = createElement(\r\n            \"div\",\r\n            \"indicator-section-label\",\r\n            \"Parameters\",\r\n        );\r\n\r\n        const controls = createElement(\r\n            \"div\",\r\n            \"indicator-controls-container\",\r\n        );\r\n\r\n        controls.id =\r\n            this.ids.controls;\r\n\r\n        const emptyState = createElement(\r\n            \"div\",\r\n            \"indicator-controls-empty\",\r\n            \"Parameters will appear after the backend response.\",\r\n        );\r\n\r\n        controls.append(\r\n            emptyState,\r\n        );\r\n\r\n        body.append(\r\n            sectionLabel,\r\n            controls,\r\n        );\r\n\r\n        return body;\r\n    }\r\n}","import { toolIcon } from \"./workspace/ToolIcons\";\r\nexport interface IndicatorCatalogItem {\r\n    id: string;\r\n    title: string;\r\n    parameterCount: number;\r\n}\r\n\r\n\r\ninterface IndicatorCatalogResponse {\r\n    indicators: IndicatorCatalogItem[];\r\n}\r\n\r\n\r\nexport interface IndicatorListOptions {\r\n    beforeElementId: string;\r\n    titleElementId: string;\r\n\r\n    catalogUrl: string;\r\n    localCatalog?: () => readonly IndicatorCatalogItem[];\r\n\r\n    /*\r\n     * Null means that the application starts with no\r\n     * selected indicator.\r\n     */\r\n    activeIndicatorId?: string | null;\r\n\r\n    onSelect: (\r\n        indicatorId: string,\r\n    ) => void | Promise<void>;\r\n}\r\n\r\n\r\nconst STYLE_ELEMENT_ID =\r\n    \"indicator-list-styles\";\r\n\r\n\r\nfunction requireElement<T extends HTMLElement>(\r\n    id: string,\r\n): T {\r\n    const element =\r\n        document.getElementById(id);\r\n\r\n    if (!element) {\r\n        throw new Error(\r\n            `Missing required element: #${id}`,\r\n        );\r\n    }\r\n\r\n    return element as T;\r\n}\r\n\r\n\r\nfunction isCatalogItem(\r\n    value: unknown,\r\n): value is IndicatorCatalogItem {\r\n    if (\r\n        !value ||\r\n        typeof value !== \"object\"\r\n    ) {\r\n        return false;\r\n    }\r\n\r\n    const item =\r\n        value as Partial<\r\n            IndicatorCatalogItem\r\n        >;\r\n\r\n    return (\r\n        typeof item.id === \"string\" &&\r\n        item.id.trim().length > 0 &&\r\n\r\n        typeof item.title === \"string\" &&\r\n        item.title.trim().length > 0 &&\r\n\r\n        typeof item.parameterCount ===\r\n            \"number\" &&\r\n\r\n        Number.isInteger(\r\n            item.parameterCount,\r\n        ) &&\r\n\r\n        item.parameterCount >= 0\r\n    );\r\n}\r\n\r\n\r\nfunction parseCatalog(\r\n    value: unknown,\r\n): IndicatorCatalogResponse {\r\n    if (\r\n        !value ||\r\n        typeof value !== \"object\"\r\n    ) {\r\n        throw new Error(\r\n            \"Indicator catalog response \" +\r\n            \"is not an object.\",\r\n        );\r\n    }\r\n\r\n    const payload =\r\n        value as Partial<\r\n            IndicatorCatalogResponse\r\n        >;\r\n\r\n    if (\r\n        !Array.isArray(\r\n            payload.indicators,\r\n        )\r\n    ) {\r\n        throw new Error(\r\n            \"Indicator catalog is missing \" +\r\n            \"its indicators array.\",\r\n        );\r\n    }\r\n\r\n    if (\r\n        !payload.indicators.every(\r\n            isCatalogItem,\r\n        )\r\n    ) {\r\n        throw new Error(\r\n            \"Indicator catalog contains \" +\r\n            \"an invalid item.\",\r\n        );\r\n    }\r\n\r\n    const seenIds =\r\n        new Set<string>();\r\n\r\n    for (\r\n        const item\r\n        of payload.indicators\r\n    ) {\r\n        if (seenIds.has(item.id)) {\r\n            throw new Error(\r\n                \"Duplicate indicator ID in \" +\r\n                `catalog: ${item.id}`,\r\n            );\r\n        }\r\n\r\n        seenIds.add(\r\n            item.id,\r\n        );\r\n    }\r\n\r\n    return {\r\n        indicators:\r\n            payload.indicators,\r\n    };\r\n}\r\n\r\n\r\nfunction injectStyles(): void {\r\n    if (\r\n        document.getElementById(\r\n            STYLE_ELEMENT_ID,\r\n        )\r\n    ) {\r\n        return;\r\n    }\r\n\r\n    const style =\r\n        document.createElement(\"style\");\r\n\r\n    style.id = STYLE_ELEMENT_ID;\r\n\r\n    style.textContent = `\r\n        .indicator-list-section {\r\n            margin-bottom: 10px;\r\n        }\r\n\r\n        .indicator-list-grid {\r\n            display: grid;\r\n            grid-template-columns:\r\n                repeat(2, minmax(0, 1fr));\r\n\r\n            gap: 6px;\r\n        }\r\n\r\n        .indicator-list-button {\r\n            min-width: 0;\r\n            height: 43px;\r\n\r\n            display: flex;\r\n            align-items: center;\r\n            gap: 8px;\r\n\r\n            padding: 6px 9px;\r\n\r\n            border:\r\n                1px solid\r\n                hsl(var(--bc) / 0.09);\r\n\r\n            border-radius: 8px;\r\n\r\n            background:\r\n                hsl(var(--b2) / 0.28);\r\n\r\n            color: hsl(var(--bc));\r\n\r\n            text-align: left;\r\n            cursor: pointer;\r\n\r\n            transition:\r\n                border-color 130ms ease,\r\n                background-color 130ms ease,\r\n                transform 130ms ease,\r\n                box-shadow 130ms ease;\r\n        }\r\n\r\n        .indicator-list-button:hover:not(:disabled) {\r\n            border-color:\r\n                hsl(var(--p) / 0.30);\r\n\r\n            background:\r\n                hsl(var(--p) / 0.06);\r\n\r\n            box-shadow:\r\n                0 3px 10px\r\n                rgba(0, 0, 0, 0.04);\r\n\r\n            transform:\r\n                translateY(-1px);\r\n        }\r\n\r\n        .indicator-list-button:active:not(:disabled) {\r\n            transform:\r\n                translateY(0);\r\n        }\r\n\r\n        .indicator-list-button.is-active {\r\n            border-color:\r\n                hsl(var(--p) / 0.38);\r\n\r\n            background:\r\n                hsl(var(--p) / 0.10);\r\n        }\r\n\r\n        .indicator-list-button.is-pending {\r\n            cursor: progress;\r\n        }\r\n\r\n        .indicator-list-button:disabled {\r\n            opacity: 0.68;\r\n        }\r\n\r\n        .indicator-list-icon {\r\n            width: 27px;\r\n            height: 27px;\r\n            flex: none;\r\n\r\n            display: grid;\r\n            place-items: center;\r\n\r\n            border-radius: 7px;\r\n\r\n            background:\r\n                hsl(var(--bc) / 0.06);\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.55);\r\n\r\n            font-size: 11px;\r\n        }\r\n\r\n        .indicator-list-button.is-active\r\n        .indicator-list-icon {\r\n            background:\r\n                hsl(var(--p));\r\n\r\n            color:\r\n                hsl(var(--pc));\r\n        }\r\n\r\n        .indicator-list-copy {\r\n            min-width: 0;\r\n            flex: 1;\r\n        }\r\n\r\n        .indicator-list-title {\r\n            display: block;\r\n            overflow: hidden;\r\n\r\n            font-size: 10.5px;\r\n            font-weight: 750;\r\n            line-height: 1.15;\r\n\r\n            text-overflow: ellipsis;\r\n            white-space: nowrap;\r\n        }\r\n\r\n        .indicator-list-meta {\r\n            display: block;\r\n\r\n            margin-top: 3px;\r\n\r\n            font-size: 7.5px;\r\n            font-weight: 500;\r\n            line-height: 1;\r\n\r\n            opacity: 0.45;\r\n        }\r\n\r\n        .indicator-list-state {\r\n            padding: 12px;\r\n\r\n            border:\r\n                1px dashed\r\n                hsl(var(--bc) / 0.12);\r\n\r\n            border-radius: 8px;\r\n\r\n            color:\r\n                hsl(var(--bc) / 0.48);\r\n\r\n            font-size: 9px;\r\n            text-align: center;\r\n        }\r\n\r\n        .indicator-list-state.is-error {\r\n            border-color:\r\n                hsl(var(--er) / 0.22);\r\n\r\n            color:\r\n                hsl(var(--er));\r\n        }\r\n\r\n        @media (max-width: 540px) {\r\n            .indicator-list-grid {\r\n                grid-template-columns: 1fr;\r\n            }\r\n        }\r\n    `;\r\n\r\n    document.head.append(\r\n        style,\r\n    );\r\n}\r\n\r\n\r\nexport class IndicatorList {\r\n    private readonly options:\r\n        IndicatorListOptions;\r\n\r\n    private activeIndicatorId:\r\n        string | null;\r\n\r\n    private pendingIndicatorId:\r\n        string | null = null;\r\n\r\n    private items:\r\n        IndicatorCatalogItem[] = [];\r\n\r\n    private rootElement:\r\n        HTMLElement | null = null;\r\n\r\n    private listElement:\r\n        HTMLElement | null = null;\r\n\r\n    private titleElement:\r\n        HTMLElement | null = null;\r\n\r\n    private titleObserver:\r\n        MutationObserver | null = null;\r\n\r\n\r\n    constructor(\r\n        options: IndicatorListOptions,\r\n    ) {\r\n        this.options = options;\r\n\r\n        this.activeIndicatorId = (\r\n            options.activeIndicatorId\r\n            ?? null\r\n        );\r\n    }\r\n\r\n\r\n    public mount(): void {\r\n        if (this.rootElement) {\r\n            return;\r\n        }\r\n\r\n        injectStyles();\r\n\r\n        const controlsElement =\r\n            requireElement<HTMLElement>(\r\n                this.options.beforeElementId,\r\n            );\r\n\r\n        const parent =\r\n            controlsElement.parentElement;\r\n\r\n        if (!parent) {\r\n            throw new Error(\r\n                \"Indicator controls do not \" +\r\n                \"have a parent element.\",\r\n            );\r\n        }\r\n\r\n        const parameterSectionLabel =\r\n            controlsElement\r\n                .previousElementSibling;\r\n\r\n        const section =\r\n            document.createElement(\r\n                \"section\",\r\n            );\r\n\r\n        section.className =\r\n            \"indicator-list-section\";\r\n\r\n        const heading =\r\n            document.createElement(\r\n                \"div\",\r\n            );\r\n\r\n        heading.className =\r\n            \"indicator-section-label\";\r\n\r\n        heading.textContent =\r\n            \"Available indicators\";\r\n\r\n        const list =\r\n            document.createElement(\r\n                \"div\",\r\n            );\r\n\r\n        list.className =\r\n            \"indicator-list-grid\";\r\n\r\n        section.append(\r\n            heading,\r\n            list,\r\n        );\r\n\r\n        parent.insertBefore(\r\n            section,\r\n\r\n            parameterSectionLabel\r\n            ?? controlsElement,\r\n        );\r\n\r\n        this.rootElement = section;\r\n        this.listElement = list;\r\n\r\n        this.titleElement =\r\n            requireElement<HTMLElement>(\r\n                this.options\r\n                    .titleElementId,\r\n            );\r\n\r\n        this.titleObserver =\r\n            new MutationObserver(\r\n                () => {\r\n                    this.syncFromDisplayedTitle();\r\n                },\r\n            );\r\n\r\n        this.titleObserver.observe(\r\n            this.titleElement,\r\n            {\r\n                childList: true,\r\n                characterData: true,\r\n                subtree: true,\r\n            },\r\n        );\r\n\r\n        this.showState(\r\n            \"Loading indicators…\",\r\n        );\r\n    }\r\n\r\n\r\n    public async load(): Promise<void> {\r\n        if (!this.listElement) {\r\n            throw new Error(\r\n                \"IndicatorList must be mounted \" +\r\n                \"before loading.\",\r\n            );\r\n        }\r\n\r\n        this.showState(\r\n            \"Loading indicators…\",\r\n        );\r\n\r\n        try {\r\n            const response = await fetch(\r\n                this.options.catalogUrl,\r\n                {\r\n                    method: \"GET\",\r\n\r\n                    credentials:\r\n                        \"same-origin\",\r\n\r\n                    headers: {\r\n                        Accept:\r\n                            \"application/json\",\r\n                    },\r\n                },\r\n            );\r\n\r\n            let payload: unknown;\r\n\r\n            try {\r\n                payload =\r\n                    await response.json();\r\n            } catch {\r\n                throw new Error(\r\n                    \"Indicator catalog response \" +\r\n                    \"was not JSON.\",\r\n                );\r\n            }\r\n\r\n            if (!response.ok) {\r\n                const message = (\r\n                    payload &&\r\n                    typeof payload === \"object\" &&\r\n                    \"error\" in payload &&\r\n                    typeof payload.error === \"string\"\r\n                )\r\n                    ? payload.error\r\n                    : (\r\n                        \"Indicator catalog request \" +\r\n                        \"failed with HTTP \" +\r\n                        `${response.status}.`\r\n                    );\r\n\r\n                throw new Error(\r\n                    message,\r\n                );\r\n            }\r\n\r\n            const catalog =\r\n                parseCatalog(payload);\r\n\r\n            this.items =\r\n                catalog.indicators;\r\n\r\n            if (this.items.length === 0 && !this.options.localCatalog?.().length) {\r\n                this.showState(\r\n                    \"No indicators are registered.\",\r\n                );\r\n\r\n                return;\r\n            }\r\n\r\n            this.render();\r\n        } catch (error) {\r\n            const message = (\r\n                error instanceof Error\r\n                    ? error.message\r\n                    : (\r\n                        \"Failed to load \" +\r\n                        \"indicators.\"\r\n                    )\r\n            );\r\n\r\n            if (this.options.localCatalog?.().length) this.render();\r\n            else this.showState(message, true);\r\n\r\n            console.error(\r\n                \"Indicator catalog failed:\",\r\n                error,\r\n            );\r\n        }\r\n    }\r\n\r\n\r\n    public setActive(\r\n        indicatorId: string | null,\r\n    ): void {\r\n        this.activeIndicatorId =\r\n            indicatorId;\r\n\r\n        this.render();\r\n    }\r\n\r\n\r\n    public destroy(): void {\r\n        this.titleObserver?.disconnect();\r\n\r\n        this.titleObserver = null;\r\n\r\n        this.rootElement?.remove();\r\n\r\n        this.rootElement = null;\r\n        this.listElement = null;\r\n        this.titleElement = null;\r\n\r\n        this.items = [];\r\n    }\r\n\r\n\r\n    public refreshLocalCatalog(): void {\r\n        this.render();\r\n    }\r\n\r\n    private render(): void {\r\n        if (!this.listElement) return;\r\n        const fragment = document.createDocumentFragment();\r\n        for (const item of this.items) fragment.append(this.createButton(item));\r\n        const scripts = this.options.localCatalog?.() ?? [];\r\n        if (scripts.length) {\r\n            const heading = document.createElement(\"div\");\r\n            heading.className = \"indicator-section-label\";\r\n            heading.style.gridColumn = \"1 / -1\";\r\n            heading.textContent = \"My scripts\";\r\n            fragment.append(heading);\r\n            for (const item of scripts) fragment.append(this.createButton(item));\r\n        }\r\n        this.listElement.replaceChildren(fragment);\r\n    }\r\n\r\n\r\n    private createButton(\r\n        item: IndicatorCatalogItem,\r\n    ): HTMLButtonElement {\r\n        const button =\r\n            document.createElement(\r\n                \"button\",\r\n            );\r\n\r\n        button.type = \"button\";\r\n\r\n        button.className =\r\n            \"indicator-list-button\";\r\n\r\n        button.dataset.indicatorId =\r\n            item.id;\r\n\r\n        const isActive = (\r\n            item.id ===\r\n            this.activeIndicatorId\r\n        );\r\n\r\n        const isPending = (\r\n            item.id ===\r\n            this.pendingIndicatorId\r\n        );\r\n\r\n        button.classList.toggle(\r\n            \"is-active\",\r\n            isActive,\r\n        );\r\n\r\n        button.classList.toggle(\r\n            \"is-pending\",\r\n            isPending,\r\n        );\r\n\r\n        /*\r\n         * The active indicator is not disabled.\r\n         *\r\n         * Clicking it again reloads its defaults.\r\n         * Only an active network request disables the list.\r\n         */\r\n        button.disabled = (\r\n            this.pendingIndicatorId\r\n            !== null\r\n        );\r\n\r\n        const icon =\r\n            document.createElement(\r\n                \"span\",\r\n            );\r\n\r\n        icon.className =\r\n            \"indicator-list-icon\";\r\n\r\n        icon.innerHTML = toolIcon(isPending ? \"loader\" : isActive ? \"check\" : \"activity\");\r\n        icon.classList.toggle(\"is-pending\", isPending);\r\n\r\n        const copy =\r\n            document.createElement(\r\n                \"span\",\r\n            );\r\n\r\n        copy.className =\r\n            \"indicator-list-copy\";\r\n\r\n        const title =\r\n            document.createElement(\r\n                \"span\",\r\n            );\r\n\r\n        title.className =\r\n            \"indicator-list-title\";\r\n\r\n        title.textContent =\r\n            item.title;\r\n\r\n        const meta =\r\n            document.createElement(\r\n                \"span\",\r\n            );\r\n\r\n        meta.className =\r\n            \"indicator-list-meta\";\r\n\r\n        if (isActive) {\r\n            meta.textContent =\r\n                \"Click to reload defaults\";\r\n        } else {\r\n            const parameterWord = (\r\n                item.parameterCount === 1\r\n                    ? \"parameter\"\r\n                    : \"parameters\"\r\n            );\r\n\r\n            meta.textContent = (\r\n                `${item.parameterCount} ` +\r\n                parameterWord\r\n            );\r\n        }\r\n\r\n        copy.append(\r\n            title,\r\n            meta,\r\n        );\r\n\r\n        button.append(\r\n            icon,\r\n            copy,\r\n        );\r\n\r\n        button.addEventListener(\r\n            \"click\",\r\n            () => {\r\n                void this.selectIndicator(\r\n                    item.id,\r\n                );\r\n            },\r\n        );\r\n\r\n        return button;\r\n    }\r\n\r\n\r\n    private async selectIndicator(\r\n        indicatorId: string,\r\n    ): Promise<void> {\r\n        if (\r\n            this.pendingIndicatorId\r\n            !== null\r\n        ) {\r\n            return;\r\n        }\r\n\r\n        const previousIndicatorId =\r\n            this.activeIndicatorId;\r\n\r\n        this.pendingIndicatorId =\r\n            indicatorId;\r\n\r\n        this.render();\r\n\r\n        try {\r\n            await this.options.onSelect(\r\n                indicatorId,\r\n            );\r\n\r\n            this.activeIndicatorId =\r\n                indicatorId;\r\n        } catch (error) {\r\n            this.activeIndicatorId =\r\n                previousIndicatorId;\r\n\r\n            console.error(\r\n                \"Failed to select indicator \" +\r\n                `${indicatorId}:`,\r\n                error,\r\n            );\r\n        } finally {\r\n            this.pendingIndicatorId =\r\n                null;\r\n\r\n            this.render();\r\n        }\r\n    }\r\n\r\n\r\n    private syncFromDisplayedTitle(): void {\r\n        const displayedTitle = (\r\n            this.titleElement\r\n                ?.textContent\r\n            ?? \"\"\r\n        ).trim();\r\n\r\n        if (!displayedTitle) {\r\n            return;\r\n        }\r\n\r\n        const matchingItem =\r\n            [...this.items, ...(this.options.localCatalog?.() ?? [])].find(\r\n                (item) => {\r\n                    return (\r\n                        item.title ===\r\n                        displayedTitle\r\n                    );\r\n                },\r\n            );\r\n\r\n        if (\r\n            matchingItem &&\r\n            matchingItem.id !==\r\n                this.activeIndicatorId\r\n        ) {\r\n            this.activeIndicatorId =\r\n                matchingItem.id;\r\n\r\n            this.render();\r\n        }\r\n    }\r\n\r\n\r\n    private showState(\r\n        message: string,\r\n        isError = false,\r\n    ): void {\r\n        if (!this.listElement) {\r\n            return;\r\n        }\r\n\r\n        const state =\r\n            document.createElement(\r\n                \"div\",\r\n            );\r\n\r\n        state.className = (\r\n            \"indicator-list-state\" +\r\n            (\r\n                isError\r\n                    ? \" is-error\"\r\n                    : \"\"\r\n            )\r\n        );\r\n\r\n        state.textContent =\r\n            message;\r\n\r\n        this.listElement.replaceChildren(\r\n            state,\r\n        );\r\n    }\r\n}","import { toolIcon } from \"./ToolIcons\";\nimport { drawingDefinition, type DrawingTool } from \"./DrawingCatalog.ts\";\nexport type { DrawingTool } from \"./DrawingCatalog.ts\";\nimport { createId } from \"./ids\";\nimport type { IChartApi, ISeriesApi, Time } from \"lightweight-charts\";\nimport type { Candle } from \"../ChartApi\";\n\nexport interface Anchor { time: Time; price: number; }\nexport interface Drawing {\n    id: string;\n    tool: Exclude<DrawingTool, \"select\">;\n    anchors: Anchor[];\n    color: string;\n    width: number;\n    text?: string;\n}\nexport interface DrawingStyle { color: string; width: number; text: string; magnet: boolean; }\nconst NS = \"http://www.w3.org/2000/svg\";\nconst copy = <T>(value: T): T => JSON.parse(JSON.stringify(value));\nfunction svg<K extends keyof SVGElementTagNameMap>(tag: K, attrs: Record<string, string | number> = {}): SVGElementTagNameMap[K] {\n    const el = document.createElementNS(NS, tag);\n    for (const [key, value] of Object.entries(attrs)) el.setAttribute(key, String(value));\n    return el;\n}\n\n/** Drawings use public time/price APIs and never add fake bars to a price series. */\nexport class DrawingLayer {\n    private readonly overlay = svg(\"svg\", { class: \"drawing-layer\", \"aria-label\": \"Chart drawings\" });\n    private readonly deleteButton = document.createElement(\"button\");\n    private drawings: Drawing[] = [];\n    private undoStack: Drawing[][] = [];\n    private redoStack: Drawing[][] = [];\n    private selected: string | null = null;\n    private draft: Drawing | null = null;\n    private first: Anchor | null = null;\n    private placed = 0;\n    private brushing = false;\n    private drag: { drawing: Drawing; start: { x: number; y: number }; endpoint: number | null; moved: boolean } | null = null;\n    private tool: DrawingTool = \"select\";\n    private active = false;\n    private hidden = false;\n    private locked = false;\n    private frame = 0;\n    private visible = true;\n    private readonly rendered = new Map<string, { signature: string; node: SVGGElement }>();\n    private editing: { element: HTMLTextAreaElement; anchor: Anchor; id: string | null; color: string; width: number } | null = null;\n    public style: DrawingStyle = { color: \"#6366f1\", width: 2, text: \"Note\", magnet: false };\n    public onChange: () => void = () => {};\n    public onToolChange: (tool: DrawingTool) => void = () => {};\n\n    constructor(private readonly container: HTMLElement, private readonly chart: IChartApi,\n        private readonly series: ISeriesApi<\"Candlestick\">, private readonly candles: () => readonly Candle[]) {\n        container.style.position = \"relative\";\n        this.deleteButton.type = \"button\";\n        this.deleteButton.className = \"chart-drawing-delete chartix-delete-button\";\n        this.deleteButton.hidden = true;\n        this.deleteButton.innerHTML = toolIcon(\"delete\");\n        this.deleteButton.addEventListener(\"pointerdown\", event => event.stopPropagation());\n        this.deleteButton.addEventListener(\"click\", event => {\n            event.stopPropagation();\n            this.deleteSelected();\n            this.container.focus({ preventScroll: true });\n        });\n        container.append(this.overlay, this.deleteButton);\n        chart.timeScale().subscribeVisibleLogicalRangeChange(() => this.refresh());\n        chart.timeScale().subscribeSizeChange(() => this.refresh());\n        new ResizeObserver(() => this.refresh()).observe(container);\n        // Hover only moves the native crosshair. Reproject drawings only while\n        // an actual pan/price-scale gesture is in progress.\n        container.addEventListener(\"pointermove\", event => { if (event.buttons) this.refresh(); });\n        container.addEventListener(\"pointerup\", () => this.refresh());\n        container.addEventListener(\"wheel\", () => this.refresh(), { passive: true });\n        container.addEventListener(\"pointerdown\", event => {\n            if (this.editing && !(event.target as Element).closest(\".chart-text-editor\")) this.finishText(true);\n        }, true);\n        container.addEventListener(\"click\", event => {\n            // Opening the editor happens on pointerdown. Preserve its focus\n            // through the corresponding canvas click instead of letting the\n            // existing chart click-to-focus handler immediately blur it.\n            if (this.editing && !(event.target as Element).closest(\".chart-text-editor\")) {\n                event.stopImmediatePropagation(); this.editing.element.focus();\n            }\n        }, true);\n        this.overlay.addEventListener(\"pointerdown\", this.pointerDown);\n        this.overlay.addEventListener(\"pointermove\", this.pointerMove);\n        this.overlay.addEventListener(\"pointerup\", this.pointerUp);\n        this.overlay.addEventListener(\"pointercancel\", this.pointerCancel);\n        this.overlay.addEventListener(\"dblclick\", e => {\n            e.stopPropagation(); e.preventDefault();\n            if (this.locked || this.tool !== \"select\") return;\n            // Pointer capture retargets clicks to the overlay during selection.\n            const id = (e.target as Element).closest(\"[data-drawing]\")?.getAttribute(\"data-drawing\")\n                ?? (e.target === this.overlay ? this.selected : null);\n            const drawing = this.drawings.find(d => d.id === id && d.tool === \"text\");\n            if (drawing) this.editText(drawing.anchors[0], drawing);\n        });\n        document.addEventListener(\"keydown\", e => {\n            if (!this.active || !this.visible || (e.target instanceof Element && e.target.closest(\"input,textarea,select,[contenteditable],dialog\"))) return;\n            if (e.key === \"Escape\") { this.setTool(\"select\"); this.selected = null; this.refresh(); }\n            if ((e.key === \"Delete\" || e.key === \"Backspace\") && this.selected) { e.preventDefault(); this.deleteSelected(); }\n            if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === \"z\") { e.preventDefault(); e.shiftKey ? this.redo() : this.undo(); }\n        });\n    }\n    public snapshot(): Drawing[] { return copy(this.drawings); }\n    public restore(drawings: Drawing[]): void {\n        this.finishText(false);\n        this.drawings = copy(drawings); this.undoStack = []; this.redoStack = [];\n        this.selected = null; this.first = null; this.draft = null; this.setTool(\"select\"); this.refresh();\n    }\n    public setActive(active: boolean): void {\n        if (this.active === active) return;\n        this.active = active;\n        if (!active) { this.finishText(true); this.setTool(\"select\"); }\n        else this.refresh();\n    }\n    public setVisible(visible: boolean): void {\n        if (this.visible === visible) return;\n        this.visible = visible;\n        if (!visible) {\n            this.deleteButton.hidden = true;\n            this.finishText(true);\n            if (this.frame) cancelAnimationFrame(this.frame);\n            this.frame = 0;\n        } else this.refresh();\n    }\n    public setTool(tool: DrawingTool): void {\n        this.finishText(true);\n        this.tool = tool; this.first = null; this.draft = null; this.placed = 0; this.brushing = false;\n        this.overlay.style.pointerEvents = tool === \"select\" || this.hidden || this.locked ? \"none\" : \"auto\";\n        this.overlay.style.cursor = tool === \"select\" ? \"default\" : \"crosshair\";\n        this.onToolChange(tool); this.refresh();\n    }\n    public setHidden(hidden: boolean): void { this.hidden = hidden; this.overlay.style.visibility = hidden ? \"hidden\" : \"visible\"; this.setTool(\"select\"); }\n    public setLocked(locked: boolean): void { this.locked = locked; this.selected = null; this.setTool(\"select\"); }\n    public applyStyle(): void {\n        const drawing = this.drawings.find(d => d.id === this.selected);\n        if (!drawing || this.locked) return;\n        this.checkpoint(); drawing.color = this.style.color; drawing.width = this.style.width;\n        this.changed();\n    }\n    public deleteSelected(): void {\n        if (!this.selected || this.locked) return;\n        this.checkpoint(); this.drawings = this.drawings.filter(d => d.id !== this.selected); this.selected = null;\n        this.deleteButton.hidden = true; this.changed();\n    }\n    public clear(): boolean {\n        if (this.locked) return false;\n        this.finishText(true); this.setTool(\"select\");\n        if (!this.drawings.length) return false;\n        this.checkpoint(); this.drawings = []; this.selected = null; this.changed();\n        return true;\n    }\n    public undo(): void {\n        if (this.locked || !this.undoStack.length) return;\n        this.setTool(\"select\"); this.redoStack.push(this.snapshot()); this.drawings = this.undoStack.pop()!; this.selected = null; this.changed();\n    }\n    public redo(): void {\n        if (this.locked || !this.redoStack.length) return;\n        this.setTool(\"select\"); this.undoStack.push(this.snapshot()); this.drawings = this.redoStack.pop()!; this.selected = null; this.changed();\n    }\n    private checkpoint(): void { this.undoStack.push(this.snapshot()); if (this.undoStack.length > 100) this.undoStack.shift(); this.redoStack = []; }\n    private changed(): void { this.refresh(); this.onChange(); }\n    public refresh(): void {\n        if (!this.visible || this.frame || (this.tool === \"select\" && !this.drawings.length && !this.draft && !this.editing && !this.rendered.size)) return;\n        this.frame = requestAnimationFrame(() => { this.frame = 0; if (this.visible) this.render(); });\n    }\n    private point(e: PointerEvent): { x: number; y: number } {\n        const rect = this.overlay.getBoundingClientRect(); return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n    }\n    private anchor(x: number, y: number): Anchor | null {\n        const time = this.chart.timeScale().coordinateToTime(x);\n        let price = this.series.coordinateToPrice(y);\n        if (time === null || price === null || !Number.isFinite(price)) return null;\n        if (this.style.magnet) {\n            const index = Math.round(this.chart.timeScale().coordinateToLogical(x) ?? -1);\n            const candle = this.candles()[index];\n            if (candle) price = [candle.open, candle.high, candle.low, candle.close].reduce((a, b) => Math.abs(a - price!) < Math.abs(b - price!) ? a : b) as typeof price;\n        }\n        return { time, price };\n    }\n    private pointerDown = (e: PointerEvent): void => {\n        if (e.button !== 0 || this.locked || this.hidden) return;\n        const p = this.point(e); const a = this.anchor(p.x, p.y); if (!a) return;\n        const target = e.target as Element;\n        const id = target.closest(\"[data-drawing]\")?.getAttribute(\"data-drawing\");\n        if (this.tool === \"select\") {\n            if (!id) return;\n            e.stopPropagation(); e.preventDefault();\n            this.selected = id;\n            const drawing = this.drawings.find(d => d.id === id)!;\n            const endpoint = target.getAttribute(\"data-endpoint\");\n            this.drag = { drawing: copy(drawing), start: p, endpoint: endpoint === null ? null : Number(endpoint), moved: false };\n            this.overlay.setPointerCapture(e.pointerId); this.refresh(); return;\n        }\n        e.stopPropagation(); e.preventDefault();\n        if (this.tool === \"text\") { this.editText(a); return; }\n        if (this.tool === \"brush\") {\n            this.first = a; this.brushing = true;\n            this.draft = { id: createId(), tool: \"brush\", anchors: [a, a], color: this.style.color, width: this.style.width };\n            this.overlay.setPointerCapture(e.pointerId);\n        } else if (!this.first) {\n            this.first = a; this.placed = 1;\n            const count = drawingDefinition(this.tool)?.points ?? 2;\n            this.draft = { id: createId(), tool: this.tool, anchors: Array.from({ length: count }, () => a), color: this.style.color, width: this.style.width };\n            if (count === 1) this.commit();\n        } else if (this.draft) {\n            this.draft.anchors[this.placed++] = a;\n            if (this.placed === this.draft.anchors.length) this.commit();\n            else for (let i = this.placed; i < this.draft.anchors.length; i++) this.draft.anchors[i] = a;\n        }\n        this.refresh();\n    };\n    private pointerMove = (e: PointerEvent): void => {\n        if (!this.drag && !this.draft) return;\n        const p = this.point(e);\n        if (this.drag) {\n            e.stopPropagation();\n            const drawing = this.drawings.find(d => d.id === this.selected); if (!drawing) return;\n            const dx = p.x - this.drag.start.x, dy = p.y - this.drag.start.y;\n            if (!this.drag.moved && Math.hypot(dx, dy) < 2) return;\n            if (!this.drag.moved) { this.checkpoint(); this.drag.moved = true; }\n            drawing.anchors = this.drag.drawing.anchors.map((a, i) => {\n                if (this.drag!.endpoint !== null && this.drag!.endpoint !== i) return a;\n                const x = this.chart.timeScale().timeToCoordinate(a.time), y = this.series.priceToCoordinate(a.price);\n                return x === null || y === null ? a : this.anchor(x + dx, y + dy) ?? a;\n            });\n            this.refresh();\n        } else if (this.draft && this.first) {\n            const a = this.anchor(p.x, p.y);\n            if (a && this.brushing) {\n                const previous = this.draft.anchors[this.draft.anchors.length - 1];\n                const x = this.chart.timeScale().timeToCoordinate(previous.time), y = this.series.priceToCoordinate(previous.price);\n                if (x !== null && y !== null && Math.hypot(x - p.x, y - p.y) >= 3) {\n                    if (this.draft.anchors.length >= 300) this.draft.anchors = this.draft.anchors.filter((_, i) => i % 2 === 0);\n                    this.draft.anchors.push(a);\n                }\n            } else if (a) this.draft.anchors[this.placed] = a;\n            this.refresh();\n        }\n    };\n    private pointerUp = (e: PointerEvent): void => {\n        if (this.brushing) {\n            e.stopPropagation();\n            if (this.overlay.hasPointerCapture(e.pointerId)) this.overlay.releasePointerCapture(e.pointerId);\n            this.commit(); return;\n        }\n        if (!this.drag) return;\n        e.stopPropagation(); const moved = this.drag.moved; this.drag = null;\n        if (this.overlay.hasPointerCapture(e.pointerId)) this.overlay.releasePointerCapture(e.pointerId);\n        if (moved) this.changed(); else this.refresh();\n    };\n    private pointerCancel = (e: PointerEvent): void => {\n        if (this.drag) { const moved = this.drag.moved; this.drag = null; if (moved) this.undo(); }\n        this.first = null; this.draft = null; this.placed = 0; this.brushing = false; this.refresh();\n    };\n    private commit(): void {\n        if (!this.draft) return;\n        this.checkpoint(); this.drawings.push(this.draft); this.selected = this.draft.id;\n        this.setTool(\"select\"); this.changed();\n    }\n    private editText(anchor: Anchor, existing?: Drawing): void {\n        this.setTool(\"select\");\n        const element = document.createElement(\"textarea\");\n        element.className = \"chart-text-editor\";\n        element.setAttribute(\"aria-label\", \"Chart text label\");\n        element.placeholder = \"Type text…\";\n        element.maxLength = 500;\n        element.rows = 1;\n        element.value = existing?.text ?? \"\";\n        this.editing = { element, anchor, id: existing?.id ?? null, color: existing?.color ?? this.style.color, width: existing?.width ?? this.style.width };\n        element.style.color = this.editing.color;\n        element.addEventListener(\"pointerdown\", e => e.stopPropagation());\n        element.addEventListener(\"click\", e => e.stopPropagation());\n        element.addEventListener(\"dblclick\", e => e.stopPropagation());\n        element.addEventListener(\"keydown\", e => {\n            e.stopPropagation();\n            if (e.key === \"Escape\") { e.preventDefault(); this.finishText(false); this.container.focus(); }\n            if (e.key === \"Enter\" && !e.shiftKey && !e.isComposing) { e.preventDefault(); this.finishText(true); this.container.focus(); }\n        });\n        element.addEventListener(\"blur\", () => this.finishText(true));\n        element.addEventListener(\"input\", () => {\n            element.style.height = \"auto\";\n            element.style.height = `${Math.max(30, Math.min(180, element.scrollHeight))}px`;\n        });\n        this.container.append(element);\n        this.positionEditor(); this.refresh();\n        // The price-chart click handler focuses the canvas after pointerdown.\n        // Focus the editor once that click has completed, without a modal.\n        requestAnimationFrame(() => { if (this.editing?.element === element) { element.focus(); if (existing) element.select(); } });\n    }\n    private finishText(commit: boolean): void {\n        const editing = this.editing; if (!editing) return;\n        this.editing = null; // Removing a focused editor can synchronously blur it.\n        const text = editing.element.value.trim().slice(0, 500);\n        editing.element.remove();\n        if (commit) {\n            const previous = this.drawings.find(d => d.id === editing.id);\n            if (previous ? previous.text !== text : !!text) {\n                this.checkpoint();\n                if (previous) {\n                    if (text) previous.text = text;\n                    else this.drawings = this.drawings.filter(d => d.id !== previous.id);\n                    this.selected = text ? previous.id : null;\n                } else {\n                    const drawing: Drawing = { id: createId(), tool: \"text\", anchors: [editing.anchor], text, color: editing.color, width: editing.width };\n                    this.drawings.push(drawing); this.selected = drawing.id;\n                }\n                this.changed(); return;\n            }\n        }\n        this.refresh();\n    }\n    private positionEditor(): void {\n        if (!this.editing) return;\n        const x = this.chart.timeScale().timeToCoordinate(this.editing.anchor.time);\n        const y = this.series.priceToCoordinate(this.editing.anchor.price);\n        const { width, height } = this.chart.paneSize();\n        const editor = this.editing.element;\n        editor.style.left = `${this.chart.priceScale(\"left\").width() + Math.max(0, Math.min(width - 80, x ?? 0))}px`;\n        editor.style.top = `${Math.max(0, Math.min(height - 32, (y ?? 0) - 18))}px`;\n        editor.style.maxWidth = `${Math.max(80, width - Math.max(0, x ?? 0))}px`;\n    }\n    private render(): void {\n        const { width, height } = this.chart.paneSize();\n        const left = this.chart.priceScale(\"left\").width();\n        this.overlay.style.left = `${left}px`;\n        if (this.overlay.getAttribute(\"width\") !== String(width)) this.overlay.setAttribute(\"width\", String(width));\n        if (this.overlay.getAttribute(\"height\") !== String(height)) this.overlay.setAttribute(\"height\", String(height));\n        this.positionEditor();\n        this.deleteButton.hidden = true;\n        const live = new Set<string>();\n        for (const d of [...this.drawings, ...(this.draft ? [this.draft] : [])]) {\n            if (d.id === this.editing?.id) continue;\n            const points = d.anchors.map(a => ({ x: this.chart.timeScale().timeToCoordinate(a.time), y: this.series.priceToCoordinate(a.price) }));\n            if (points.some(p => p.x === null || p.y === null)) continue;\n            const a = points[0] as { x: number; y: number }, b = (points[1] ?? points[0]) as { x: number; y: number };\n            if (d.id === this.selected && this.active && !this.hidden && !this.locked && this.tool === \"select\") {\n                const anchor = points.find(p => p.x! >= 0 && p.x! <= width && p.y! >= 0 && p.y! <= height);\n                if (anchor && width >= 30 && height >= 30) {\n                    this.deleteButton.style.left = `${left + Math.min(width - 28, Math.max(2, anchor.x! + 9))}px`;\n                    this.deleteButton.style.top = `${Math.min(height - 28, Math.max(2, anchor.y! - 30))}px`;\n                    this.deleteButton.title = `Delete ${drawingDefinition(d.tool)?.name ?? \"drawing\"}`;\n                    this.deleteButton.setAttribute(\"aria-label\", this.deleteButton.title);\n                    this.deleteButton.hidden = false;\n                }\n            }\n            live.add(d.id);\n            const signature = JSON.stringify([points, width, height, d.tool, d.color, d.width, d.text, d.id === this.selected, this.locked, this.tool]);\n            if (this.rendered.get(d.id)?.signature === signature) continue;\n            const previous = this.rendered.get(d.id);\n            const group = previous?.node ?? svg(\"g\", { \"data-drawing\": d.id, fill: \"none\" });\n            if (group.getAttribute(\"stroke\") !== d.color) group.setAttribute(\"stroke\", d.color);\n            if (group.getAttribute(\"stroke-width\") !== String(d.width)) group.setAttribute(\"stroke-width\", String(d.width));\n            let childIndex = 0;\n            // Retain shape elements while panning/zooming. Only coordinates and\n            // changed styles are patched; pointer capture and text nodes survive.\n            const child = <K extends keyof SVGElementTagNameMap>(tag: K, attrs: Record<string, string | number>): SVGElementTagNameMap[K] => {\n                let node = group.children[childIndex] as SVGElementTagNameMap[K] | undefined;\n                if (!node || node.tagName.toLowerCase() !== tag) {\n                    const replacement = svg(tag);\n                    group.insertBefore(replacement, node ?? null);\n                    node = replacement;\n                }\n                childIndex++;\n                for (const [name, value] of Object.entries(attrs)) if (node.getAttribute(name) !== String(value)) node.setAttribute(name, String(value));\n                return node;\n            };\n            const line = (x1: number, y1: number, x2: number, y2: number, dashed = false) => {\n                const attrs = { x1, y1, x2, y2 };\n                child(\"line\", { ...attrs, stroke: \"transparent\", \"stroke-width\": 14, \"pointer-events\": this.tool === \"select\" && !this.locked ? \"stroke\" : \"none\" });\n                child(\"line\", { ...attrs, \"stroke-dasharray\": dashed ? \"5 4\" : \"none\", \"pointer-events\": \"none\" });\n            };\n            const label = (x: number, y: number, text: string) => {\n                const t = child(\"text\", { x: Math.max(4, Math.min(width - 110, x)), y: Math.max(16, Math.min(height - 6, y)), fill: d.color, stroke: \"none\", \"font-size\": 12, \"font-family\": \"system-ui\", \"pointer-events\": this.tool === \"select\" && !this.locked ? \"all\" : \"none\", \"paint-order\": \"stroke\", \"stroke-width\": 3 });\n                if (t.textContent !== text) t.textContent = text;\n            };\n            const interactive = this.tool === \"select\" && !this.locked ? \"all\" : \"none\";\n            const area = { fill: d.color, \"fill-opacity\": .09, \"pointer-events\": interactive };\n            const arrowHead = (start: { x: number; y: number }, end: { x: number; y: number }) => {\n                const angle = Math.atan2(end.y - start.y, end.x - start.x), size = 10 + d.width;\n                line(end.x, end.y, end.x - size * Math.cos(angle - .45), end.y - size * Math.sin(angle - .45));\n                line(end.x, end.y, end.x - size * Math.cos(angle + .45), end.y - size * Math.sin(angle + .45));\n            };\n            if (d.tool === \"brush\") {\n                const path = points.map((p, i) => `${i ? \"L\" : \"M\"}${p.x},${p.y}`).join(\" \");\n                child(\"path\", { d: path, stroke: \"transparent\", \"stroke-width\": 14, \"pointer-events\": interactive === \"all\" ? \"stroke\" : \"none\" });\n                child(\"path\", { d: path, \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\", \"pointer-events\": \"none\" });\n            }\n            else if (d.tool === \"triangle\") {\n                child(\"polygon\", { points: points.map(p => `${p.x},${p.y}`).join(\" \"), ...area });\n            }\n            else if (d.tool === \"ellipse\") {\n                child(\"ellipse\", { cx: (a.x + b.x) / 2, cy: (a.y + b.y) / 2, rx: Math.abs(b.x - a.x) / 2, ry: Math.abs(b.y - a.y) / 2, ...area });\n            }\n            else if (d.tool === \"channel\") {\n                const c = points[2] as { x: number; y: number };\n                const vertical = Math.abs(b.x - a.x) < .01;\n                const dx = vertical ? c.x - a.x : 0;\n                const dy = vertical ? 0 : c.y - (a.y + (b.y - a.y) * (c.x - a.x) / (b.x - a.x));\n                child(\"polygon\", { points: `${a.x},${a.y} ${b.x},${b.y} ${b.x + dx},${b.y + dy} ${a.x + dx},${a.y + dy}`, ...area });\n                line(a.x, a.y, b.x, b.y); line(a.x + dx, a.y + dy, b.x + dx, b.y + dy);\n                line(a.x + dx / 2, a.y + dy / 2, b.x + dx / 2, b.y + dy / 2, true);\n            }\n            else if (d.tool === \"arrowUp\" || d.tool === \"arrowDown\") {\n                const sign = d.tool === \"arrowUp\" ? -1 : 1;\n                const start = { x: a.x, y: a.y - sign * 24 };\n                line(start.x, start.y, a.x, a.y); arrowHead(start, a);\n            }\n            else if (d.tool === \"markerCircle\") child(\"circle\", { cx: a.x, cy: a.y, r: 6 + d.width, fill: d.color, \"pointer-events\": interactive });\n            else if (d.tool === \"markerSquare\") child(\"rect\", { x: a.x - 7, y: a.y - 7, width: 14, height: 14, fill: d.color, \"pointer-events\": interactive });\n            else if (d.tool === \"horizontalRay\") { line(a.x, a.y, width, a.y); label(a.x + 7, a.y - 7, d.anchors[0].price.toFixed(5)); }\n            else if (d.tool === \"crossline\") { line(0, a.y, width, a.y); line(a.x, 0, a.x, height); }\n            else if (d.tool === \"fibFan\") {\n                line(a.x, a.y, b.x, b.y, true);\n                for (const ratio of [.382, .5, .618]) {\n                    const y = a.y + (b.y - a.y) * ratio;\n                    const endX = b.x >= a.x ? width : 0;\n                    const endY = Math.abs(b.x - a.x) < .01 ? y : a.y + (y - a.y) * (endX - a.x) / (b.x - a.x);\n                    line(a.x, a.y, endX, endY); label(b.x + 6, y - 4, String(ratio));\n                }\n            }\n            else if (d.tool === \"fibExtension\") {\n                const c = points[2] as { x: number; y: number };\n                line(a.x, a.y, b.x, b.y, true); line(b.x, b.y, c.x, c.y, true);\n                for (const ratio of [0, .618, 1, 1.618, 2.618]) {\n                    const y = c.y + (b.y - a.y) * ratio;\n                    const price = d.anchors[2].price + (d.anchors[1].price - d.anchors[0].price) * ratio;\n                    line(Math.min(a.x, b.x, c.x), y, Math.max(a.x, b.x, c.x), y);\n                    label(Math.max(a.x, b.x, c.x) + 6, y - 4, `${ratio} · ${price.toFixed(5)}`);\n                }\n            }\n            else if (d.tool === \"horizontal\") { line(0, a.y, width, a.y); label(8, a.y - 7, d.anchors[0].price.toFixed(5)); }\n            else if (d.tool === \"vertical\") line(a.x, 0, a.x, height);\n            else if (d.tool === \"text\") {\n                const t = child(\"text\", { x: a.x, y: a.y, fill: d.color, stroke: \"none\", \"font-size\": 13, \"font-family\": \"system-ui\", \"pointer-events\": this.tool === \"select\" && !this.locked ? \"all\" : \"none\", cursor: \"text\" });\n                const lines = (d.text || \"\").split(\"\\n\");\n                lines.forEach((line, i) => {\n                    const span = t.children[i] as SVGTSpanElement | undefined ?? svg(\"tspan\");\n                    if (span.getAttribute(\"x\") !== String(a.x)) span.setAttribute(\"x\", String(a.x));\n                    span.setAttribute(\"dy\", String(i === 0 ? 0 : 18));\n                    if (span.textContent !== line) span.textContent = line;\n                    if (span.parentNode !== t) t.append(span);\n                });\n                while (t.children.length > lines.length) t.lastElementChild?.remove();\n            }\n            else if (d.tool === \"rectangle\") {\n                child(\"rect\", { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y), width: Math.abs(b.x - a.x), height: Math.abs(b.y - a.y), fill: d.color, \"fill-opacity\": 0.09, \"pointer-events\": this.tool === \"select\" && !this.locked ? \"all\" : \"none\" });\n            } else if (d.tool === \"fib\") {\n                line(a.x, a.y, b.x, b.y, true);\n                for (const ratio of [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]) {\n                    const y = b.y + (a.y - b.y) * ratio;\n                    line(Math.min(a.x, b.x), y, Math.max(a.x, b.x), y);\n                    const price = d.anchors[1].price + (d.anchors[0].price - d.anchors[1].price) * ratio;\n                    label(Math.max(a.x, b.x) + 6, y - 4, `${ratio} · ${price.toFixed(5)}`);\n                }\n            } else {\n                let end = b;\n                if ((d.tool === \"ray\" || d.tool === \"extended\") && Math.abs(b.x - a.x) > 0.01) {\n                    const x = b.x >= a.x ? width : 0;\n                    end = { x, y: a.y + (b.y - a.y) * (x - a.x) / (b.x - a.x) };\n                }\n                let start = a;\n                if (d.tool === \"extended\") {\n                    if (Math.abs(b.x - a.x) < .01) { start = { x: a.x, y: 0 }; end = { x: a.x, y: height }; }\n                    else { const x = b.x >= a.x ? 0 : width; start = { x, y: a.y + (b.y - a.y) * (x - a.x) / (b.x - a.x) }; }\n                } else if (d.tool === \"ray\" && Math.abs(b.x - a.x) < .01) end = { x: a.x, y: b.y >= a.y ? height : 0 };\n                if ([\"measure\", \"priceRange\", \"dateRange\"].includes(d.tool)) {\n                    child(\"rect\", { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y), width: Math.abs(b.x - a.x), height: Math.abs(b.y - a.y), ...area });\n                    if (d.tool === \"priceRange\") end = { x: a.x, y: b.y };\n                    if (d.tool === \"dateRange\") end = { x: b.x, y: a.y };\n                }\n                line(start.x, start.y, end.x, end.y);\n                if (d.tool === \"arrow\") arrowHead(a, b);\n                if ([\"measure\", \"priceRange\", \"dateRange\"].includes(d.tool)) {\n                    const delta = d.anchors[1].price - d.anchors[0].price;\n                    const percent = d.anchors[0].price === 0 ? 0 : delta / d.anchors[0].price * 100;\n                    const from = this.chart.timeScale().coordinateToLogical(a.x) ?? 0;\n                    const to = this.chart.timeScale().coordinateToLogical(b.x) ?? 0;\n                    const priceLabel = `${delta.toFixed(5)} (${percent.toFixed(2)}%)`, dateLabel = `${Math.round(Math.abs(to - from))} bars`;\n                    label(Math.min(a.x, b.x), Math.min(a.y, b.y) - 9, d.tool === \"priceRange\" ? priceLabel : d.tool === \"dateRange\" ? dateLabel : `${priceLabel} · ${dateLabel}`);\n                }\n            }\n            if (d.id === this.selected && !this.locked && d.tool !== \"brush\") points.forEach((p, i) => child(\"circle\", { cx: p.x!, cy: p.y!, r: 5, fill: \"white\", \"data-endpoint\": i, \"pointer-events\": \"all\", cursor: \"move\" }));\n            while (group.children.length > childIndex) group.lastElementChild?.remove();\n            if (!previous) this.overlay.append(group);\n            this.rendered.set(d.id, { signature, node: group });\n        }\n        for (const [id, entry] of this.rendered) {\n            if (!live.has(id)) { entry.node.remove(); this.rendered.delete(id); }\n        }\n    }\n}\n","import { ChartApi, chartTime as timeNumber, type Candle, type DataUrlBuilder } from \"../ChartApi\";\nimport { TECHNICALS_BAR_LIMIT } from \"../Technicals.ts\";\nimport { TechnicalsView } from \"../TechnicalsView\";\nimport { applyWorkspaceTheme, CHART_PALETTES, type ChartPalette } from \"../ChartAppearance.ts\";\nimport { DrawingToolbox } from \"./DrawingToolbox\";\nimport { toolIcon, type ToolIcon } from \"./ToolIcons\";\nimport { FrameTask } from \"./FrameTask\";\nimport { createId } from \"./ids\";\nimport type { Time } from \"lightweight-charts\";\nimport { ScriptLibrary } from \"../../zero/ScriptLibrary\";\nimport { ScriptDock } from \"../../zero/main\";\nimport { ChartApp } from \"../ChartApp\";\nimport { IndicatorSettingsPanel } from \"../IndicatorSettingsPanel\";\nimport { IndicatorList } from \"../IndicatorList\";\nimport { DrawingLayer, type DrawingTool, type Drawing } from \"./DrawingLayer\";\nimport { WorkspaceStore, parseWorkspace, validDrawings, TIMEFRAMES, type Layout, type WorkspaceState, type ViewState, type SavedTemplate } from \"./WorkspaceState\";\nconst el = <T extends HTMLElement = HTMLElement>(id: string): T => document.getElementById(id) as T;\nconst candleUrl: DataUrlBuilder = (symbol, timeframe) => `/charts/api/${encodeURIComponent(symbol)}/data/?timeframe=${encodeURIComponent(timeframe)}`;\ninterface View { app: ChartApp; cell: HTMLElement; drawings: DrawingLayer; list: IndicatorList; key: string; error: HTMLElement; }\n\nexport class ChartWorkspace {\n    private readonly views: View[] = [];\n    private technicals!: TechnicalsView;\n    private scripts!: ScriptLibrary;\n    private scriptDock!: ScriptDock;\n    private active = 0;\n    private layout: Layout = \"single\";\n    private theme: \"light\" | \"dark\" = \"light\";\n    private syncing = false;\n    private palette?: ChartPalette;\n    private busy = false;\n    private maximized = false;\n    private saveTimer = 0;\n    private saveIdle: number | null = null;\n    private activationInitialized = false;\n    private readonly rangeFrame = new FrameTask();\n    private readonly cursorFrame = new FrameTask();\n    private readonly resizeFrame = new FrameTask();\n    private lastCursorKey = \"\";\n    private readonly targetCursorKeys = new Map<View, string>();\n    private readonly targetRangeKeys = new Map<View, string>();\n    private readonly pendingDrawingWrites = new Map<string, Drawing[]>();\n    private readonly store = new WorkspaceStore(message => this.status(message));\n    private readonly drawingCache = new Map<string, Drawing[]>();\n    private toolbox: DrawingToolbox | null = null;\n    private toolbarTool: DrawingTool = \"select\";\n    private hiddenDrawings = false;\n    private lockedDrawings = false;\n    private color = \"#6366f1\";\n    private width = 2;\n    private magnet = false;\n\n    public mount(): void {\n        document.querySelector<HTMLElement>(\".brand-mark\")!.innerHTML = toolIcon(\"logo\");\n        document.querySelector<HTMLElement>(\".layout-mark\")!.innerHTML = toolIcon(\"layout\");\n        el(\"templates-button\").innerHTML = toolIcon(\"templates\") + \"Templates\";\n        el(\"template-close\").innerHTML = toolIcon(\"close\");\n        el(\"watchlist-toggle\").innerHTML = toolIcon(\"watchlist\") + \"Watchlist\";\n        this.updateThemeButton();\n        this.mountProfile();\n        this.mountToolbar(); this.mountTemplates();\n        const form = el<HTMLFormElement>(\"zero-form\");\n        const csrf = form.querySelector<HTMLInputElement>(\"[name=csrfmiddlewaretoken]\")!.value;\n        this.scripts = new ScriptLibrary(this.store, form.dataset.compileUrl!, csrf);\n        const refreshPickers = () => { for (const view of this.views) view.list.refreshLocalCatalog(); };\n        this.scriptDock = new ScriptDock(this.scripts, () => {\n            const index = this.active;\n            const app = this.views[index]?.app;\n            return async program => {\n                if (!app || this.busy || app.isWorking() || !app.getCandles().length) {\n                    throw new Error(\"Wait for the selected chart to finish loading.\");\n                }\n                const id = `script:preview:${index}`;\n                this.scripts.setPreview(id, program);\n                await app.previewScript(id);\n            };\n        }, refreshPickers, () => this.resizeAll());\n        if (new URLSearchParams(location.search).get(\"editor\") === \"zero\") this.scriptDock.setOpen(true);\n        window.addEventListener(\"storage\", event => {\n            if (event.key !== \"chartix.workspace.v1.scripts\" && event.key !== null) return;\n            this.scripts.refresh();\n            this.scriptDock.refreshCatalog();\n            refreshPickers();\n        });\n        const charts = el(\"workspace-charts\");\n        this.technicals = new TechnicalsView(el(\"workspace-technicals\"), el<HTMLButtonElement>(\"technicals-button\"),\n            new ChartApi(candleUrl), () => {\n                const app = this.views[this.active]?.app;\n                if (!app || this.busy) {\n                    this.status(\"Wait for the chart workspace to finish loading.\");\n                    return;\n                }\n                const { symbol, timeframe } = app.getTemplateState();\n                const candles = app.getCandleSeries().data().slice(-TECHNICALS_BAR_LIMIT).filter((item): item is Candle => \"close\" in item);\n                return { symbol, timeframe, candles, replaying: app.isReplaying() };\n            }, open => {\n                charts.hidden = open;\n                charts.parentElement!.dataset.view = open ? \"technicals\" : \"charts\";\n                if (open) {\n                    for (const menu of charts.querySelectorAll<HTMLDetailsElement>(\".indicator-menu[open]\")) menu.open = false;\n                    for (const view of this.views) view.drawings.setVisible(false);\n                } else this.applyVisibility();\n            });\n        el<HTMLSelectElement>(\"workspace-layout\").addEventListener(\"change\", () => {\n            this.setLayout(el<HTMLSelectElement>(\"workspace-layout\").value as Layout); this.scheduleSave();\n        });\n        el(\"workspace-theme\").addEventListener(\"click\", () => this.setTheme(this.theme === \"dark\" ? \"light\" : \"dark\"));\n        const watchlist = el(\"workspace-watchlist\");\n        const watchlistToggle = el(\"watchlist-toggle\");\n        if (window.innerWidth < 1100) watchlist.hidden = true;\n        watchlistToggle.setAttribute(\"aria-pressed\", String(!watchlist.hidden));\n        watchlistToggle.addEventListener(\"click\", () => {\n            watchlist.hidden = !watchlist.hidden;\n            watchlistToggle.setAttribute(\"aria-pressed\", String(!watchlist.hidden));\n            this.resizeAll();\n        });\n        for (const id of [\"link-time\", \"link-cursor\"]) el(id).addEventListener(\"change\", () => {\n            if (id === \"link-cursor\") {\n                this.cursorFrame.cancel(); this.lastCursorKey = \"\"; this.targetCursorKeys.clear();\n                if (!this.linkCursor) for (const view of this.views) view.app.getChart().clearCrosshairPosition();\n            }\n            if (id === \"link-time\" && this.linkTime) this.syncRange(this.active);\n            this.scheduleSave();\n        });\n        window.addEventListener(\"pagehide\", () => this.saveNow());\n        document.addEventListener(\"visibilitychange\", () => { if (document.hidden) this.saveNow(); });\n        const saved = this.store.read<unknown>(\"last\", null);\n        if (saved) {\n            try { void this.restore(parseWorkspace(saved)); return; }\n            catch { this.status(\"The last workspace could not be restored. Starting a clean chart.\"); }\n        }\n        this.setLayout(\"single\"); this.activate(0);\n    }\n    private get linkTime(): boolean { return el<HTMLInputElement>(\"link-time\").checked; }\n    private get linkCursor(): boolean { return el<HTMLInputElement>(\"link-cursor\").checked; }\n    private get count(): number { return this.layout === \"single\" ? 1 : this.layout === \"quad\" ? 4 : 2; }\n    private status(message: string, undo?: () => void): void {\n        const targets = [el(\"workspace-status\")];\n        const feedback = document.getElementById(\"template-feedback\");\n        if (feedback && el<HTMLDialogElement>(\"template-dialog\").open) targets.push(feedback);\n        for (const target of targets) {\n            target.textContent = message;\n            if (undo) {\n                const button = document.createElement(\"button\");\n                button.className = \"notice-undo\"; button.textContent = \"Undo\";\n                button.addEventListener(\"click\", () => { undo(); this.status(\"Action undone\"); }, { once: true });\n                target.append(button);\n            }\n        }\n    }\n    private createView(index: number, autoLoad = true): View {\n        const prefix = `view-${index}-`;\n        const id = (name: string) => prefix + name;\n        const cell = document.createElement(\"section\");\n        cell.className = \"chart-cell\"; cell.setAttribute(\"aria-label\", `Chart ${index + 1}`);\n        const initialTimeframe = [\"1d\", \"1h\", \"4h\", \"15m\"][index];\n        cell.innerHTML = `\n            <div class=\"chart-cell-toolbar\">\n                <div class=\"chart-market-controls\">\n                    <span class=\"chart-number\">0${index + 1}</span>\n                    <input id=\"${id(\"ticker\")}\" class=\"symbol-input\" value=\"EURUSD\" aria-label=\"Chart ${index + 1} symbol\" title=\"Symbol · press Enter to load\">\n                    <select id=\"${id(\"timeframe\")}\" class=\"interval-select\" aria-label=\"Chart ${index + 1} interval\">${TIMEFRAMES.map(t => `<option value=\"${t}\" ${t === initialTimeframe ? \"selected\" : \"\"}>${t}</option>`).join(\"\")}</select>\n                </div>\n                <div class=\"chart-indicator-mount\" id=\"${id(\"settings\")}\"></div>\n                <div class=\"chart-cell-actions\">\n                    <button id=\"${id(\"replay\")}\" class=\"workspace-button cell-replay\" title=\"Bar replay\" aria-label=\"Replay chart ${index + 1}\">${toolIcon(\"play\")}</button>\n                    <button class=\"workspace-button cell-fit\" title=\"Fit all data\" aria-label=\"Fit chart ${index + 1}\">${toolIcon(\"fit\")}</button>\n                    <button class=\"workspace-button cell-appearance\" title=\"Chart settings\" aria-label=\"Chart ${index + 1} settings\">${toolIcon(\"settings\")}</button>\n                    <button class=\"workspace-button cell-maximize\" title=\"Maximize / restore chart\" aria-label=\"Maximize chart ${index + 1}\">${toolIcon(\"maximize\")}</button>\n                </div>\n            </div>\n            <div id=\"${id(\"replayControls\")}\" class=\"cell-replay-controls hidden\">\n                <span>Bar <span id=\"${id(\"current\")}\">0</span> / <span id=\"${id(\"total\")}\">0</span></span>\n                <button id=\"${id(\"prev\")}\" class=\"workspace-button\">${toolIcon(\"back\")} Previous</button><button id=\"${id(\"next\")}\" class=\"workspace-button\">Next ${toolIcon(\"next\")}</button><button id=\"${id(\"exit\")}\" class=\"workspace-button\">Exit replay</button>\n            </div>\n            <div class=\"chart-stack\">\n                <div id=\"${id(\"chart\")}\" class=\"chart-container\" style=\"height:100%;min-height:220px\"></div>\n                <div id=\"${id(\"separator\")}\" class=\"chart-separator\"></div>\n                <div id=\"${id(\"indicator\")}\" class=\"chart-container\" style=\"height:0\"></div>\n            </div>\n            <div class=\"chart-cell-error\" role=\"alert\"></div>\n            <button id=\"${id(\"theme\")}\" hidden></button><div id=\"${id(\"watchlist\")}\" hidden></div>`;\n        el(\"workspace-grid\").append(cell);\n        new IndicatorSettingsPanel({ mountId: id(\"settings\"), initialTitle: \"Indicators\", ids: {\n            title: id(\"indicatorTitle\"), controls: id(\"indicatorControls\"), liveInput: id(\"live\"), applyButton: id(\"apply\"), clearButton: id(\"clear\"),\n        } }).mount();\n        const app = new ChartApp({\n            chartContainerId: id(\"chart\"), indicatorContainerId: id(\"indicator\"), separatorId: id(\"separator\"),\n            tickerInputId: id(\"ticker\"), timeframeSelectId: id(\"timeframe\"), themeToggleId: id(\"theme\"),\n            barReplayButtonId: id(\"replay\"), replayControlsId: id(\"replayControls\"), previousBarButtonId: id(\"prev\"), nextBarButtonId: id(\"next\"), exitReplayButtonId: id(\"exit\"), currentBarNumberId: id(\"current\"), totalBarNumberId: id(\"total\"),\n            watchlistItemsId: index === 0 ? \"watchlistItems\" : id(\"watchlist\"), indicatorTitleId: id(\"indicatorTitle\"), indicatorControlsContainerId: id(\"indicatorControls\"), applyIndicatorButtonId: id(\"apply\"), clearIndicatorButtonId: id(\"clear\"), indicatorLiveInputId: id(\"live\"),\n            dataUrlBuilder: candleUrl,\n            indicatorUrlBuilder: indicator => `/charts/indicators/${encodeURIComponent(indicator)}/`,\n            loadScript: id => this.scripts.load(id),\n            initialTimeframe,\n            onWatchlistSelect: symbol => { void this.views[this.active].app.loadSymbol(symbol); },\n            onRemoveAllObjects: () => this.removeAllObjects(index),\n            onSelectPalette: palette => this.setTheme(palette.scheme, palette, true),\n        });\n        const error = cell.querySelector<HTMLElement>(\".chart-cell-error\")!;\n        cell.addEventListener(\"chartix:error\", ((event: CustomEvent<string>) => { cell.removeAttribute(\"aria-busy\"); error.textContent = `${event.detail} Check the symbol and available CSV timeframe.`; error.classList.add(\"visible\"); this.status(`Chart ${index + 1}: data unavailable`); }) as EventListener);\n        app.mount(false);\n        const drawings = new DrawingLayer(app.getContainer(), app.getChart(), app.getCandleSeries(), () => app.getCandles());\n        const list = new IndicatorList({\n            beforeElementId: id(\"indicatorControls\"), titleElementId: id(\"indicatorTitle\"), catalogUrl: \"/charts/indicators/\",\n            localCatalog: () => this.scripts.catalog(), onSelect: indicator => app.setActiveIndicator(indicator),\n        });\n        const view: View = { app, cell, drawings, list, key: `${index}:EURUSD:${initialTimeframe}`, error };\n        this.views.push(view);\n        drawings.setHidden(this.hiddenDrawings); drawings.setLocked(this.lockedDrawings);\n        const menu = cell.querySelector<HTMLDetailsElement>(\".indicator-menu\")!;\n        const summary = menu.querySelector(\"summary\")!;\n        const panel = menu.querySelector<HTMLElement>(\".indicator-settings-panel\")!;\n        const positionPanel = () => {\n            const rect = summary.getBoundingClientRect();\n            const below = window.innerHeight - rect.bottom - 16;\n            const above = rect.top - 16;\n            const opensAbove = below < 360 && above > below;\n            const panelHeight = Math.min(650, Math.max(120, opensAbove ? above : below));\n            const top = opensAbove ? rect.top - panelHeight - 8 : rect.bottom + 8;\n            panel.style.position = \"fixed\";\n            panel.style.height = `${panelHeight}px`;\n            panel.style.maxHeight = `${panelHeight}px`;\n            panel.style.left = `${Math.max(8, Math.min(window.innerWidth - Math.min(450, window.innerWidth - 32) - 8, rect.left))}px`;\n            panel.style.right = \"auto\";\n            panel.style.top = `${Math.max(8, Math.min(window.innerHeight - panelHeight - 8, top))}px`;\n        };\n        summary.addEventListener(\"click\", () => { if (!menu.open) positionPanel(); });\n        const positionOpenPanel = () => { if (menu.open) positionPanel(); };\n        menu.addEventListener(\"toggle\", positionOpenPanel);\n        window.addEventListener(\"resize\", positionOpenPanel);\n        list.mount(); void list.load();\n        cell.addEventListener(\"pointerdown\", () => this.activate(index), true);\n        cell.addEventListener(\"focusin\", () => this.activate(index));\n        cell.addEventListener(\"chartix:notice\", ((event: CustomEvent<string>) => this.status(event.detail)) as EventListener);\n        cell.addEventListener(\"chartix:data\", ((event: CustomEvent<{ symbol: string; timeframe: string }>) => {\n            if (index === this.active) this.scriptDock.setTarget(`${event.detail.symbol} · ${event.detail.timeframe}`);\n            this.lastCursorKey = \"\"; this.targetCursorKeys.delete(view); this.targetRangeKeys.delete(view);\n            this.drawingCache.set(view.key, drawings.snapshot());\n            view.key = `${index}:${event.detail.symbol}:${event.detail.timeframe}`;\n            const stored = this.drawingCache.get(view.key) ?? this.store.read<unknown>(`drawings.${view.key}`, []);\n            drawings.restore(validDrawings(stored) ? stored : []);\n        }) as EventListener);\n        cell.addEventListener(\"chartix:loading\", () => { cell.setAttribute(\"aria-busy\", \"true\"); this.status(`Loading chart ${index + 1}…`); });\n        cell.addEventListener(\"chartix:ready\", () => {\n            cell.removeAttribute(\"aria-busy\");\n            error.classList.remove(\"visible\"); drawings.refresh(); this.scheduleSave();\n            if (!this.busy) requestAnimationFrame(() => this.syncRange(this.active));\n            this.status(`Chart ${index + 1} · ${app.getTemplateState().symbol} ${app.getTemplateState().timeframe} · ${app.getCandles().length.toLocaleString()} bars`);\n        });\n        cell.addEventListener(\"chartix:state\", () => { drawings.refresh(); this.scheduleSave(); });\n        cell.addEventListener(\"chartix:theme\", ((event: CustomEvent<\"light\" | \"dark\">) => {\n            this.setTheme(event.detail);\n        }) as EventListener);\n        drawings.onChange = () => {\n            const snapshot = drawings.snapshot(); this.drawingCache.set(view.key, snapshot);\n            this.pendingDrawingWrites.set(view.key, snapshot); this.scheduleSave();\n        };\n        drawings.onToolChange = tool => { if (this.active === index) { this.toolbarTool = tool; this.updateToolbar(); } };\n        const scale = app.getChart().timeScale();\n        scale.subscribeVisibleTimeRangeChange(() => { this.syncRange(index); this.scheduleSave(); });\n        app.getChart().subscribeCrosshairMove(param => {\n            if (index !== this.active || this.syncing || !this.linkCursor || this.busy || this.visibleViews().length < 2) return;\n            const time = param.point ? param.time ?? null : null;\n            this.cursorFrame.schedule(() => this.syncCursor(index, time));\n        });\n        cell.querySelector(\".cell-appearance\")!.addEventListener(\"click\", () => { this.activate(index); app.openAppearanceSettings(); });\n        cell.querySelector(\".cell-fit\")!.addEventListener(\"click\", () => { this.activate(index); app.getChart().timeScale().fitContent(); });\n        cell.querySelector(\".cell-maximize\")!.addEventListener(\"click\", () => { this.activate(index); this.maximized = !this.maximized; this.applyVisibility(); });\n        new ResizeObserver(() => { if (!cell.hidden) this.resizeAll(); }).observe(cell.querySelector(\".chart-stack\")!);\n        app.setTheme(this.theme, this.palette);\n        if (autoLoad) void app.loadSymbol(\"EURUSD\");\n        return view;\n    }\n    private visibleViews(): View[] { return this.views.filter(v => !v.cell.hidden); }\n    private setLayout(layout: Layout, autoLoad = true): void {\n        this.layout = layout; this.maximized = false;\n        while (this.views.length < this.count) this.createView(this.views.length, autoLoad);\n        if (this.active >= this.count) this.activate(0);\n        el<HTMLSelectElement>(\"workspace-layout\").value = layout;\n        this.applyVisibility();\n    }\n    private applyVisibility(): void {\n        el(\"workspace-grid\").dataset.layout = this.maximized ? \"single\" : this.layout;\n        this.views.forEach((view, i) => {\n            view.cell.hidden = i >= this.count || (this.maximized && i !== this.active);\n            view.drawings.setVisible(!view.cell.hidden && !this.technicals.isOpen);\n        });\n        this.lastCursorKey = \"\"; this.targetCursorKeys.clear(); this.targetRangeKeys.clear();\n        this.resizeAll();\n    }\n    private resizeAll(): void {\n        this.resizeFrame.schedule(() => {\n            for (const view of this.visibleViews()) { view.app.resize(); view.drawings.refresh(); }\n        });\n    }\n    private activate(index: number): void {\n        if (!this.views[index] || (this.activationInitialized && this.active === index)) return;\n        this.activationInitialized = true;\n        this.lastCursorKey = \"\";\n        const changed = this.active !== index;\n        this.active = index;\n        const { symbol, timeframe } = this.views[index].app.getTemplateState();\n        this.scriptDock.setTarget(`${symbol} · ${timeframe}`);\n        this.views.forEach((v, i) => { v.cell.classList.toggle(\"is-active\", i === index); v.drawings.setActive(i === index); });\n        this.configureDrawing();\n        if (changed) { this.toolbarTool = \"select\"; this.updateToolbar(); this.scheduleSave(); }\n    }\n    private syncRange(index: number): void {\n        if (!this.linkTime || this.syncing || this.busy || index !== this.active || this.visibleViews().length < 2) return;\n        this.rangeFrame.schedule(() => {\n            if (!this.linkTime || this.busy || index !== this.active) return;\n            const range = this.views[index]?.app.getChart().timeScale().getVisibleRange();\n            if (!range) return;\n            const key = `${index}:${timeNumber(range.from)}:${timeNumber(range.to)}`;\n            this.syncing = true;\n            try {\n                for (const view of this.visibleViews()) {\n                    if (view === this.views[index] || !view.app.getCandles().length || this.targetRangeKeys.get(view) === key) continue;\n                    const current = view.app.getChart().timeScale().getVisibleRange();\n                    this.targetRangeKeys.set(view, key);\n                    if (current && timeNumber(current.from) === timeNumber(range.from) && timeNumber(current.to) === timeNumber(range.to)) continue;\n                    view.app.getChart().timeScale().setVisibleRange(range);\n                }\n            } finally { this.syncing = false; }\n        });\n    }\n    private syncCursor(index: number, time: Time | null): void {\n        if (index !== this.active || this.busy || !this.linkCursor) return;\n        const key = `${index}:${time === null ? \"clear\" : timeNumber(time)}`;\n        if (this.lastCursorKey === key) return;\n        this.lastCursorKey = key;\n        this.syncing = true;\n        try {\n            for (const other of this.visibleViews()) {\n                if (other === this.views[index]) continue;\n                const chart = other.app.getChart(), data = other.app.getCandles();\n                let lo = 0, hi = data.length - 1, match = -1;\n                const target = time === null ? -Infinity : timeNumber(time);\n                while (lo <= hi) {\n                    const mid = (lo + hi) >>> 1;\n                    if (timeNumber(data[mid].time) <= target) { match = mid; lo = mid + 1; } else hi = mid - 1;\n                }\n                const bar = match < 0 || target > timeNumber(data[data.length - 1].time) ? null : data[match];\n                const targetKey = bar ? `${timeNumber(bar.time)}:${bar.close}` : \"clear\";\n                if (this.targetCursorKeys.get(other) === targetKey) continue;\n                this.targetCursorKeys.set(other, targetKey);\n                if (bar) chart.setCrosshairPosition(bar.close, bar.time, other.app.getCandleSeries());\n                else chart.clearCrosshairPosition();\n            }\n        } finally { this.syncing = false; }\n    }\n    private setTheme(theme: \"light\" | \"dark\", palette?: ChartPalette, resetColors = false): void {\n        this.theme = theme;\n        this.palette = palette;\n        applyWorkspaceTheme(document.body, theme, palette);\n        this.updateThemeButton();\n        for (const view of this.views) view.app.setTheme(theme, palette, resetColors);\n        this.scheduleSave();\n    }\n    private updateThemeButton(): void {\n        const button = el(\"workspace-theme\");\n        const next = this.theme === \"dark\" ? \"light\" : \"dark\";\n        button.innerHTML = toolIcon(next === \"light\" ? \"sun\" : \"moon\");\n        button.title = `Switch to ${next} theme`;\n        button.setAttribute(\"aria-label\", button.title);\n    }\n    private configureDrawing(): void {\n        const layer = this.views[this.active]?.drawings; if (!layer) return;\n        layer.style = { color: this.color, width: this.width, text: \"\", magnet: this.magnet };\n    }\n    private mountProfile(): void {\n        const profile = el<HTMLDetailsElement>(\"workspace-profile\");\n        const trigger = profile.querySelector(\"summary\")!;\n        trigger.innerHTML = toolIcon(\"profile\");\n        document.addEventListener(\"pointerdown\", event => {\n            if (profile.open && !profile.contains(event.target as Node)) profile.open = false;\n        });\n        profile.addEventListener(\"focusout\", event => {\n            if (!profile.contains(event.relatedTarget as Node | null)) profile.open = false;\n        });\n        profile.addEventListener(\"keydown\", event => {\n            if (profile.open && event.key === \"Escape\") {\n                event.stopPropagation();\n                profile.open = false;\n                trigger.focus();\n            }\n        });\n    }\n    private mountToolbar(): void {\n        const toolbar = el(\"drawing-toolbar\");\n        this.toolbox = new DrawingToolbox(toolbar, {\n            tools: this.store.read<unknown>(\"favoriteTools\", []),\n            placement: this.store.read<unknown>(\"favoriteToolsPlacement\", null),\n            saveTools: tools => this.store.write(\"favoriteTools\", tools),\n            savePlacement: placement => this.store.write(\"favoriteToolsPlacement\", placement),\n        }, (tool, hint) => {\n            this.configureDrawing(); this.toolbarTool = tool; this.views[this.active]?.drawings.setTool(tool); this.updateToolbar();\n            this.status(hint + (tool === \"select\" ? \" · Drag a drawing or its endpoint to edit\" : \" · Esc to cancel\"));\n        });\n        this.toolbox.mount(el(\"workspace-grid\").parentElement!);\n        const divider = () => { const d = document.createElement(\"div\"); d.className = \"tool-divider\"; toolbar.append(d); };\n        divider();\n        const color = document.createElement(\"input\"); color.type = \"color\"; color.value = this.color; color.className = \"tool-color\"; color.title = \"Drawing color\"; color.setAttribute(\"aria-label\", \"Drawing color\");\n        color.addEventListener(\"change\", () => { this.color = color.value; this.configureDrawing(); this.views[this.active]?.drawings.applyStyle(); }); toolbar.append(color);\n        const width = document.createElement(\"select\"); width.className = \"tool-width\"; width.title = \"Line width\"; width.setAttribute(\"aria-label\", \"Drawing line width\");\n        for (const value of [1, 2, 3, 4]) width.add(new Option(`${value}px`, String(value), false, value === this.width));\n        width.addEventListener(\"change\", () => { this.width = Number(width.value); this.configureDrawing(); this.views[this.active]?.drawings.applyStyle(); }); toolbar.append(width);\n        divider();\n        const action = (icon: ToolIcon, title: string, callback: (button: HTMLButtonElement) => void, toggle = false) => {\n            const b = document.createElement(\"button\"); b.className = \"tool-button\"; b.innerHTML = toolIcon(icon); b.title = title; b.setAttribute(\"aria-label\", title); if (toggle) b.setAttribute(\"aria-pressed\", \"false\");\n            b.addEventListener(\"click\", () => callback(b)); toolbar.append(b);\n        };\n        action(\"magnet\", \"Magnet · snap price to nearest OHLC\", b => { this.magnet = !this.magnet; b.setAttribute(\"aria-pressed\", String(this.magnet)); this.configureDrawing(); }, true);\n        action(\"unlock\", \"Lock / unlock drawings\", b => { this.lockedDrawings = !this.lockedDrawings; b.setAttribute(\"aria-pressed\", String(this.lockedDrawings)); b.innerHTML = toolIcon(this.lockedDrawings ? \"lock\" : \"unlock\"); for (const v of this.views) v.drawings.setLocked(this.lockedDrawings); }, true);\n        action(\"eye\", \"Hide / show drawings\", b => { this.hiddenDrawings = !this.hiddenDrawings; b.setAttribute(\"aria-pressed\", String(this.hiddenDrawings)); b.innerHTML = toolIcon(this.hiddenDrawings ? \"eyeOff\" : \"eye\"); for (const v of this.views) v.drawings.setHidden(this.hiddenDrawings); }, true);\n        divider();\n        action(\"undo\", \"Undo drawing (Ctrl Z)\", () => this.views[this.active]?.drawings.undo());\n        action(\"redo\", \"Redo drawing (Ctrl Shift Z)\", () => this.views[this.active]?.drawings.redo());\n        action(\"delete\", \"Delete selected drawing\", () => this.views[this.active]?.drawings.deleteSelected());\n        action(\"clear\", \"Clear drawings on active chart\", () => this.removeAllObjects(this.active));\n        this.updateToolbar();\n    }\n    private removeAllObjects(index: number): void {\n        this.activate(index);\n        const layer = this.views[index]?.drawings;\n        if (!layer || this.lockedDrawings) { this.status(\"Unlock drawings before clearing them.\"); return; }\n        if (!layer.clear()) { this.status(\"There are no objects to remove.\"); return; }\n        this.status(\"All objects removed from this chart.\", () => layer.undo());\n    }\n    private updateToolbar(): void { this.toolbox?.setActive(this.toolbarTool); }\n    private snapshot(): WorkspaceState {\n        return { version: 1, layout: this.layout, theme: this.theme, paletteId: this.palette?.id, active: this.active,\n            linkTime: this.linkTime, linkCursor: this.linkCursor,\n            views: this.views.slice(0, this.count).map(v => ({ chart: v.app.getTemplateState(), drawings: v.drawings.snapshot(), range: v.app.getChart().timeScale().getVisibleRange() })),\n        };\n    }\n    private cancelSave(): void {\n        clearTimeout(this.saveTimer);\n        if (this.saveIdle !== null) window.cancelIdleCallback(this.saveIdle);\n        this.saveIdle = null;\n    }\n    private scheduleSave(): void {\n        if (this.busy) return;\n        this.cancelSave();\n        this.saveTimer = window.setTimeout(() => {\n            if (\"requestIdleCallback\" in window) this.saveIdle = window.requestIdleCallback(() => { this.saveIdle = null; this.saveNow(); }, { timeout: 2000 });\n            else this.saveNow();\n        }, 800);\n    }\n    private saveNow(): void {\n        this.cancelSave();\n        for (const [key, drawings] of this.pendingDrawingWrites) {\n            if (this.store.write(`drawings.${key}`, drawings)) this.pendingDrawingWrites.delete(key);\n        }\n        if (!this.busy && this.views.length && !this.visibleViews().some(v => v.app.isWorking())) this.store.write(\"last\", this.snapshot());\n    }\n    private async restore(input: WorkspaceState): Promise<void> {\n        const state = parseWorkspace(input); this.busy = true;\n        this.cancelSave(); this.status(\"Restoring workspace…\");\n        el(\"workspace-grid\").setAttribute(\"inert\", \"\");\n        try {\n            this.setTheme(state.theme, CHART_PALETTES.find(palette => palette.id === state.paletteId));\n            while (this.views.length < state.views.length) this.createView(this.views.length, false);\n            this.setLayout(state.layout, false);\n            el<HTMLInputElement>(\"link-time\").checked = state.linkTime; el<HTMLInputElement>(\"link-cursor\").checked = state.linkCursor;\n            let failures = 0;\n            // Keep expensive indicator graphs sequential, and preserve each graph's source order.\n            for (let i = 0; i < state.views.length; i++) {\n                const v = this.views[i], saved = state.views[i];\n                const ok = await v.app.restoreTemplateState(saved.chart);\n                if (!ok) failures++;\n                if (ok || v.app.getTemplateState().symbol === saved.chart.symbol && v.app.getTemplateState().timeframe === saved.chart.timeframe) {\n                    v.drawings.restore(saved.drawings); this.drawingCache.set(v.key, v.drawings.snapshot());\n                    this.pendingDrawingWrites.set(v.key, v.drawings.snapshot());\n                    if (saved.range && v.app.getCandles().length) v.app.getChart().timeScale().setVisibleRange(saved.range);\n                }\n            }\n            this.activate(state.active);\n            this.status(failures ? `Restored with ${failures} chart or indicator error(s). Check the chart messages and indicator settings.` : \"Workspace restored\");\n        } catch (error) { this.status(error instanceof Error ? error.message : \"Could not restore this workspace.\"); }\n        finally { this.busy = false; el(\"workspace-grid\").removeAttribute(\"inert\"); this.resizeAll(); requestAnimationFrame(() => this.syncRange(this.active)); this.scheduleSave(); }\n    }\n    private canSave(): boolean {\n        if (this.busy || this.visibleViews().some(v => v.app.isWorking())) {\n            this.status(\"Wait for chart data and indicator calculations to finish before saving a template.\");\n            return false;\n        }\n        return true;\n    }\n    private mountTemplates(): void {\n        const dialog = el<HTMLDialogElement>(\"template-dialog\");\n        const feedback = document.createElement(\"div\"); feedback.id = \"template-feedback\";\n        feedback.className = \"template-feedback\"; feedback.setAttribute(\"role\", \"status\");\n        el(\"template-list\").before(feedback);\n        el(\"templates-button\").addEventListener(\"click\", () => { this.renderTemplates(); dialog.showModal(); });\n        el(\"template-close\").addEventListener(\"click\", () => dialog.close());\n        el<HTMLFormElement>(\"template-save-form\").addEventListener(\"submit\", event => {\n            event.preventDefault(); if (!this.canSave()) return;\n            const name = el<HTMLInputElement>(\"template-name\").value.trim(); if (!name) return;\n            const templates = this.store.templates();\n            templates.push({ id: createId(), name, updatedAt: new Date().toISOString(), state: this.snapshot() });\n            if (this.store.write(\"templates\", templates)) { el<HTMLInputElement>(\"template-name\").value = \"\"; this.renderTemplates(); this.status(`Saved template: ${name}`); }\n        });\n        el(\"template-export\").addEventListener(\"click\", () => {\n            if (!this.canSave()) return;\n            const blob = new Blob([JSON.stringify(this.snapshot(), null, 2)], { type: \"application/json\" });\n            const url = URL.createObjectURL(blob), a = document.createElement(\"a\"); a.href = url; a.download = \"chartix-workspace.json\"; a.click(); setTimeout(() => URL.revokeObjectURL(url), 1000);\n        });\n        el<HTMLInputElement>(\"template-import\").addEventListener(\"change\", async () => {\n            const input = el<HTMLInputElement>(\"template-import\"), file = input.files?.[0]; if (!file || this.busy) return;\n            try {\n                if (file.size > 5 * 1024 * 1024) throw new Error(\"Template exceeds the 5 MB limit.\");\n                const state = parseWorkspace(JSON.parse(await file.text()));\n                const templates = this.store.templates();\n                templates.push({ id: createId(), name: file.name.replace(/\\.json$/i, \"\").slice(0, 80) || \"Imported template\", updatedAt: new Date().toISOString(), state });\n                if (this.store.write(\"templates\", templates)) { this.renderTemplates(); this.status(\"Template imported. Choose Load to open it.\"); }\n            } catch (error) { this.status(error instanceof Error ? error.message : \"Invalid template file.\"); }\n            finally { input.value = \"\"; }\n        });\n    }\n    private restoreSavedTemplate(template: SavedTemplate): void {\n        const all = this.store.templates().filter(t => t.id !== template.id);\n        all.push(template); this.store.write(\"templates\", all); this.renderTemplates();\n    }\n    private renderTemplates(): void {\n        const list = el(\"template-list\"); list.replaceChildren();\n        const starter = (name: string, layout: Layout, intervals: string[]) => {\n            const state: WorkspaceState = { version: 1, layout, theme: this.theme, paletteId: this.palette?.id, active: 0, linkTime: true, linkCursor: true,\n                views: intervals.map(timeframe => ({ chart: { symbol: \"EURUSD\", timeframe, indicators: [] }, drawings: [] })),\n            };\n            return { id: \"starter\", name, updatedAt: \"Built-in starter\", state };\n        };\n        const templates = this.store.templates();\n        for (const t of [starter(\"Clean EURUSD chart\", \"single\", [\"1d\"]), starter(\"EURUSD · multi-timeframe desk\", \"quad\", [\"1d\", \"4h\", \"1h\", \"15m\"]), ...templates]) {\n            const row = document.createElement(\"div\"); row.className = \"template-row\";\n            const copy = document.createElement(\"div\"); copy.className = \"template-row-copy\";\n            const title = document.createElement(\"strong\"); title.textContent = t.name;\n            const meta = document.createElement(\"small\"); meta.textContent = t.id === \"starter\" ? t.updatedAt : `${t.state.layout} · ${new Date(t.updatedAt).toLocaleString()}`;\n            copy.append(title, meta); row.append(copy);\n            const button = (text: string, run: () => void) => { const b = document.createElement(\"button\"); b.className = \"workspace-button\"; b.textContent = text; b.addEventListener(\"click\", run); row.append(b); };\n            button(\"Load\", () => { if (this.busy) return; el<HTMLDialogElement>(\"template-dialog\").close(); void this.restore(t.state); });\n            if (t.id !== \"starter\") {\n                button(\"Update\", () => {\n                    if (!this.canSave()) return;\n                    const all = this.store.templates().map(x => x.id === t.id ? { ...x, state: this.snapshot(), updatedAt: new Date().toISOString() } : x);\n                    if (this.store.write(\"templates\", all)) {\n                        this.renderTemplates(); this.status(`Updated template: ${t.name}`, () => this.restoreSavedTemplate(t));\n                    }\n                });\n                button(\"Delete\", () => {\n                    if (this.store.write(\"templates\", this.store.templates().filter(x => x.id !== t.id))) {\n                        this.renderTemplates(); this.status(`Deleted template: ${t.name}`, () => this.restoreSavedTemplate(t));\n                    }\n                });\n            }\n            list.append(row);\n        }\n    }\n}\n","import { ChartWorkspace } from \"./workspace/ChartWorkspace\";\nimport \"./workspace/workspace.css\";\nimport \"./technicals.css\";\nnew ChartWorkspace().mount();\n"],"mappings":"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"}