ColorWheel: replies in Claude Code Desktop drawn with the app's own HTML markdown, alert cards, and themed full-width mermaid diagrams and charts that follow…

<h1 align="center">ColorWheel</h1>
ColorWheel is a Claude Code mod. It changes two places in the desktop app: how assistant replies are drawn, and the band above the prompt.
<img src="docs/images/window-tasks.svg" alt="Claude Code Desktop with ColorWheel: under the chat, between the repository row and the prompt, the band shows Agents 2 running, Tasks 2/5, the 5-hour limit at 31% on its top edge, the 7-day limit at 64% on its bottom edge, and the context at 33%" width="100%">
One rounded frame sits inside the app's own block and is always there.
The last known limits are kept between sessions, so a new session shows them at once.
<img src="docs/images/window-idle.svg" alt="The same window at rest: the band keeps only the two limit edges and the context weather" width="100%">
> [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION]) become rounded cards in a tone that reads on both themes.xychart-beta charts draw as full-width SVG that switches with the theme. Each has Open large, a pane that zooms from 100 to 600% with panning, and Copy source.<img src="docs/images/diagram-flow.svg" alt="A flowchart drawn by ColorWheel" width="49%"> <img src="docs/images/diagram-chart.svg" alt="A bar and line chart drawn by ColorWheel" width="49%">
The terminal keeps Claude Code's own renderer and a one-line version of the band.
claude plugin marketplace add AlexeyHRDesign/colorwheel
claude plugin install colorwheel@colorwheel --scope user
Restart Claude Code after installing. From a local checkout, pass the folder path to marketplace add instead.
The installer may say that two options are not set yet; both default to on, so there is nothing to configure. ColorWheel needs a Claude Code build with mods (plugins with a hooks module).
[!NOTE] ColorWheel is tested only on Windows, in the desktop app on Claude Code 2.1.295, at one screen size and scale. It has not been tried on macOS or Linux, or at other resolutions and display scaling, where the frame may sit a few pixels off. If you run it there, an issue with a screenshot is very welcome.
ColorWheel draws the whole band above the prompt. Another mod that draws there without handing the band on will hide it; Token Weather is one, and ColorWheel replaces it.
| Command | What it does |
|---|---|
/colorwheel | Shows every element ColorWheel draws. |
/colorwheel progress | Plays a 20-second demo of agents and tasks in the band. |
/colorwheel invert | Switches the band between the share used and the share left, like the ⇆ button. |
Two settings, under the plugin's options:
| Setting | Default | |
|---|---|---|
| Enabled | on | Off hands replies back to Claude Code's own renderer. |
| Diagram hints | on | Adds a short note to each prompt so Claude knows diagrams and alerts render here. |
npm --prefix scripts install
npm --prefix scripts run build:vendor
claude plugin validate .
claude plugin test .
npx tsx scripts/readme-images.ts
npx tsx scripts/readme-gif.ts
The engine refuses modules over 1 MiB, so the vendor build bundles only beautiful-mermaid's elk-free pipelines and fails if the bundle grows past that. Flowcharts are laid out by hooks/layout.ts. The README images are drawn by the mod's own code, so they match what it draws.
ColorWheel grew out of two mods:
Made by Aleksei Druzhkov.
ArtStation · LinkedIn · GitHub
MIT. Bundles beautiful-mermaid (MIT).
hooks/register.tsx 300 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register, RenderElement } from 'claude-code'
3
4import type { DiagramView, Limit, Progress, Todo } from '../types'
5import type { Segment } from './blocks'
6import { split } from './blocks'
7import { DEMO } from './demo'
8import type { Diagram } from './diagram'
9import { PX_PER_COLUMN, crop, diagram, fit } from './diagram'
10import { ALERTS, alertColor } from './palette'
11import { frame } from './frame'
12import { EMPTY, agentQueued, agentStarted, agentStopped, drawBand, summarize, taskCompleted, taskCreated, todosWritten } from './progress'
13import { INVERT_GLYPH, INVERT_KEY, QUIET, addReading, drawWeather, pills } from './weather'
14
15const HINT = [
16 'Replies are drawn by the ColorWheel mod in the Claude Code desktop app.',
17 'Fenced ```mermaid blocks render as full-width themed diagrams: flowcharts, sequence, state, class and ER diagrams, and xychart-beta bar or line charts.',
18 'GitHub alerts (> [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING], > [!CAUTION]) render as cards.',
19 'When a numeric series or a flow is easier to see than read, add one small diagram or chart with short labels; skip diagrams for simple answers.',
20].join(' ')
21
22const VIEW = 'colorwheel-view'
23const view = atom({ plugin: 'colorwheel', key: 'view' } as const, null as DiagramView | null)
24const progress = atom({ plugin: 'colorwheel', key: 'progress' } as const, EMPTY)
25const weather = atom({ plugin: 'colorwheel', key: 'weather' } as const, QUIET)
26const inverted = atom({ plugin: 'colorwheel', key: 'inverted' } as const, false)
27const SETTLE_MS = 6000
28// One cell of the app's padding on each side is reclaimed by the band's negative margin.
29const CELL_PX = 12
30const BAND_MARGIN = 40 - 2 * CELL_PX
31const LIMITS_KEY = 'limits'
32const DEMO_STEPS = ['Read the layout code', 'Write the failing test', 'Move the elbow logic', 'Run the suite']
33const ZOOMS = [1, 1.5, 2, 3, 4, 6]
34const PAN = 0.15
35// Room kept free in the frame for the invert button, left of the weather icon.
36const SLOT_PX = 2 * PX_PER_COLUMN + 8
37// A cell of the band's own row, measured in the desktop app: wider than the transcript's PX_PER_COLUMN.
38const BUTTON_CELL_PX = 10.7
39
40type Elements = ReturnType<EngineInterface['ui']['resolve']>
41
42const openDiagram = async ($: EngineInterface, source: string) => {
43 await update($, view, () => ({ source, zoom: 1, x: 0.5, y: 0.5 }))
44 await $.ui.open({ id: VIEW, title: 'Diagram', focus: true, closeOnEscape: true })
45}
46
47const copy = ($: EngineInterface, text: string, surface: string) =>
48 $.ui.copy({ text, surface: surface as 'desktop' })
49 .then(r => $.ui.toast(r.isCopied ? 'Copied' : `Copy failed: ${r.reason}`))
50 .catch(() => $.ui.toast('Copy failed'))
51
52const drawDiagram = ($: EngineInterface, el: Elements, source: string, d: Diagram, columns: number, key: string): RenderElement => {
53 const { Box, Button } = el
54 const size = fit(d, columns)
55 return (
56 <Box key={key} flexDirection="column" width="100%" rowGap={1}>
57 {'Svg' in el ? <el.Svg source={d.svg} alt="mermaid diagram" width={size.width} height={size.height} isInteractive /> : null}
58 <Box flexDirection="row" columnGap={1}>
59 <Button key={`${key}.open`} label="Open large" onPress={() => void openDiagram($, source)} />
60 <Button key={`${key}.copy`} label="Copy source" onPress={press => void copy($, `\`\`\`mermaid\n${source}\n\`\`\``, press.surface)} />
61 </Box>
62 </Box>
63 )
64}
65
66const drawSegment = ($: EngineInterface, el: Elements, segment: Segment, columns: number, key: string): RenderElement => {
67 const { Box, Text, Markdown } = el
68 switch (segment.kind) {
69 case 'markdown':
70 return <Markdown key={key} text={segment.text} />
71 case 'code':
72 return 'Code' in el
73 ? <el.Code key={key} source={segment.source || ' '} {...(segment.lang ? { language: segment.lang } : {})} />
74 : <Markdown key={key} text={`\`\`\`${segment.lang}\n${segment.source}\n\`\`\``} />
75 case 'mermaid': {
76 const d = diagram(segment.source)
77 return d ? drawDiagram($, el, segment.source, d, columns, key) : <Markdown key={key} text={`\`\`\`mermaid\n${segment.source}\n\`\`\``} />
78 }
79 case 'alert': {
80 const color = alertColor(segment.level)
81 return (
82 <Box key={key} flexDirection="column" width="100%" borderStyle="round" borderColor={color} paddingX={2}>
83 <Text bold color={color}>{ALERTS[segment.level].title}</Text>
84 {segment.text ? <Markdown text={segment.text} /> : null}
85 </Box>
86 )
87 }
88 }
89}
90
91const drawReply = ($: EngineInterface, el: Elements, text: string, columns: number): RenderElement => (
92 <el.Box flexDirection="column" width="100%" rowGap={1}>
93 {split(text).map((segment, i) => drawSegment($, el, segment, columns, `s${i}`))}
94 </el.Box>
95)
96
97const track = async ($: EngineInterface, change: (p: Progress) => Progress) => {
98 await update($, progress, change)
99 if (!summarize(await read($, progress)).isFinished) return
100 $.clock.after(SETTLE_MS, () => {
101 void (async () => {
102 if (summarize(await read($, progress)).isFinished) await update($, progress, () => EMPTY)
103 })()
104 })
105}
106
107const takeReading = async ($: EngineInterface) => {
108 const { context, rateLimits } = await $.session.usage()
109 if (!context?.window) return
110 const tokens = context.tokens ?? 0
111 const percent = Math.round(context.percent ?? (tokens / context.window) * 100)
112 const limits = (rateLimits ?? []).map(l => ({ kind: l.kind, percentUsed: l.percentUsed, ...(l.resetsAt ? { resetsAt: l.resetsAt } : {}) }))
113 // An empty list means no fresh figures, not that the limits went away: keep the last known.
114 await update($, weather, w => ({ readings: addReading(w.readings, { tokens, window: context.window, percent }), limits: limits.length ? limits : w.limits }))
115 if (limits.length) await $.store.set(LIMITS_KEY, limits)
116}
117
118const toggleInvert = async ($: EngineInterface) => {
119 await update($, inverted, v => !v)
120 await $.store.set(INVERT_KEY, await read($, inverted))
121}
122
123// The limits are the account's, not the session's: the last known ones show at once in a new session.
124const restoreLimits = async ($: EngineInterface) => {
125 const saved = await $.store.get(LIMITS_KEY)
126 if (!Array.isArray(saved)) return
127 const now = await $.clock.now()
128 // A window that reset since it was saved starts over empty; it is not dropped, or its edge vanishes.
129 const limits = (saved as Limit[])
130 .filter(l => typeof l?.kind === 'string' && typeof l.percentUsed === 'number')
131 .map(l => (l.resetsAt && Date.parse(l.resetsAt) <= now ? { kind: l.kind, percentUsed: 0 } : l))
132 if (limits.length) await update($, weather, w => (w.limits.length ? w : { ...w, limits }))
133}
134
135export const register: Register = (on, options) => {
136 if (options.enabled === false) return
137
138 on('session.start', async ($, e, next) => {
139 const started = await next(e)
140 await restoreLimits($).catch(() => undefined)
141 if ((await $.store.get(INVERT_KEY).catch(() => undefined)) === true) await update($, inverted, () => true)
142 await takeReading($).catch(() => undefined)
143 await $.command.register({ name: 'colorwheel', description: 'Show what ColorWheel draws; progress plays a demo of the progress row; invert switches limits between used and left', argumentHint: '[progress|invert]' }).catch(() => undefined)
144 return started
145 })
146
147 on('command.run', { command: 'colorwheel' }, async ($, e) => {
148 const arg = e.args.trim().split(/\s+/)[0]
149 if (arg === 'invert') {
150 await toggleInvert($)
151 return { text: (await read($, inverted)) ? 'ColorWheel now shows what is left.' : 'ColorWheel now shows what is used.' }
152 }
153 if (arg !== 'progress') return { text: DEMO }
154 const todo = (done: number, active: string): Todo[] =>
155 DEMO_STEPS.map((content, i) => ({ content, status: i < done ? 'completed' : i === done ? 'in_progress' : 'pending', ...(i === done ? { activeForm: active } : {}) }))
156 const steps: [number, (p: Progress) => Progress][] = [
157 [0, p => agentStarted(agentStarted(agentQueued(agentQueued(todosWritten(EMPTY, todo(0, 'Reading the layout code')), 'Explore', 'Map the layout code'), 'Plan', 'Plan the refactor'), 'demo-a', 'Explore'), 'demo-b', 'Plan')],
158 [3000, p => todosWritten(p, todo(1, 'Writing the failing test'))],
159 [6000, p => agentStopped(p, 'demo-a')],
160 [8000, p => todosWritten(p, todo(2, 'Moving the elbow logic'))],
161 [11000, p => todosWritten(agentStopped(p, 'demo-b'), todo(3, 'Running the suite'))],
162 [14000, p => todosWritten(p, todo(4, ''))],
163 ]
164 for (const [at, change] of steps) {
165 $.clock.after(at, () => void track($, change).catch(err => $.ui.toast(`Progress demo failed: ${String(err)}`)))
166 }
167 return { text: 'Progress demo: watch the row above the prompt for about 20 seconds.' }
168 })
169
170 on('prompt.submit', async ($, e, next) => {
171 if (summarize(await read($, progress)).isFinished) await update($, progress, () => EMPTY)
172 if (options.diagramHints === false || (e.origin.kind !== 'composer' && e.origin.kind !== 'bridge')) return next(e)
173 return next({ ...e, context: [...(e.context ?? []), HINT] })
174 })
175
176 on('turn.complete', async ($, e, next) => {
177 const done = await next(e)
178 if (!e.agentId) await takeReading($).catch(() => undefined)
179 return done
180 })
181
182 on('tool.call', async ($, e, next) => {
183 const input = e as unknown as { tool: string; description?: string; subagent_type?: string; todos?: Todo[] }
184 if ((input.tool === 'Agent' || input.tool === 'Task') && !e.agentId) {
185 await track($, p => agentQueued(p, input.subagent_type ?? 'general-purpose', input.description ?? input.subagent_type ?? 'subagent'))
186 }
187 if (input.tool === 'TodoWrite' && Array.isArray(input.todos) && !e.agentId) await track($, p => todosWritten(p, input.todos!))
188 return next(e)
189 })
190
191 on('classic.SubagentStart', async ($, e, next) => {
192 await track($, p => agentStarted(p, e.agent_id, e.agent_type))
193 return next(e)
194 })
195
196 on('classic.SubagentStop', async ($, e, next) => {
197 await track($, p => agentStopped(p, e.agent_id))
198 return next(e)
199 })
200
201 on('classic.TaskCreated', async ($, e, next) => {
202 await track($, p => taskCreated(p, e.task_id, e.task_subject))
203 return next(e)
204 })
205
206 on('classic.TaskCompleted', async ($, e, next) => {
207 await track($, p => taskCompleted(p, e.task_id))
208 return next(e)
209 })
210
211 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
212 if (e.props.hasSurvey) return next(e)
213 const s = summarize(await read($, progress))
214 const left = await read($, inverted)
215 const metrics = pills(await read($, weather), await $.clock.now(), left)
216 const toggle = () => void toggleInvert($)
217 const hasProgress = s.isActive || s.isFinished
218 const el = $.ui.resolve(e)
219 const desktop = e.surface !== 'terminal' && 'Svg' in el
220 // The desktop frame always shows: limits and weather are worth a glance at any time.
221 if (!desktop && !hasProgress && !metrics.length) return next(e)
222 // With no hook beneath, next() rejects rather than resolving empty; the band must still draw.
223 const below = await next(e).catch(() => null)
224 const columns = e.props.bodyColumns ?? e.viewport?.columns ?? 100
225 if (desktop) {
226 const f = frame(hasProgress ? s : null, metrics, { left, slot: SLOT_PX })
227 // The Svg needs a width in px: the frame's markup stretches to whatever it gets, so
228 // a width a little under the transcript column is safe.
229 const width = Math.max(320, Math.round((e.viewport?.columns ?? 100) * PX_PER_COLUMN) - BAND_MARGIN)
230 // `below` may be the engine's own node, which the app refuses under a Box that sets width.
231 return (
232 <el.Box flexDirection="column">
233 <el.Box key="cw-band" position="relative" marginLeft={-1} marginRight={-1} marginTop={-1} marginBottom={-1}>
234 <el.Svg source={f.svg} alt={f.alt} width={width} height={f.height} isInteractive />
235 {/* The Svg takes no presses, so the invert button lies over the gap the frame keeps for it.
236 Placed from the right: the cell width is only estimated, and from the left its error grows with the band. */}
237 <el.Box position="absolute" top={0} bottom={0} right={Math.round((f.slotRight + 8) / BUTTON_CELL_PX)} flexDirection="row" alignItems="center">
238 <el.Button key={INVERT_KEY} label={INVERT_GLYPH} plain dimColor onPress={toggle} />
239 </el.Box>
240 </el.Box>
241 {below ?? null}
242 </el.Box>
243 )
244 }
245 return (
246 <el.Box flexDirection="column">
247 <el.Box flexDirection="row" width="100%" columnGap={3}>
248 <el.Box flexGrow={1} flexShrink={1}>{hasProgress ? drawBand(el, s, e.surface, columns) : null}</el.Box>
249 {drawWeather(el, await read($, weather), await $.clock.now(), left, toggle)}
250 </el.Box>
251 {below ?? null}
252 </el.Box>
253 )
254 })
255
256 on('ui.render', { component: 'AssistantMessage' }, ($, e, next) => {
257 if (e.surface === 'terminal' || !e.props.text.trim()) return next(e)
258 return drawReply($, $.ui.resolve(e), e.props.text, e.viewport?.columns ?? 96)
259 })
260
261 on('ui.render', { component: 'CommandOutput' }, ($, e, next) => {
262 if (e.surface === 'terminal' || e.props.isErrored || !e.props.text.trim()) return next(e)
263 return drawReply($, $.ui.resolve(e), e.props.text, e.viewport?.columns ?? 96)
264 })
265
266 on('ui.render', { component: 'Pane', requestId: VIEW }, async ($, e) => {
267 const el = $.ui.resolve(e)
268 const { Box, Text, Button } = el
269 const current = await read($, view)
270 const d = current ? diagram(current.source) : null
271 if (!current || !d || !('Svg' in el)) return <Text dimColor>No diagram to show.</Text>
272 const at = Math.max(0, ZOOMS.indexOf(current.zoom))
273 const set = (change: Partial<DiagramView>) => void update($, view, v => (v ? { ...v, ...change } : v))
274 const pan = (dx: number, dy: number) => {
275 const step = PAN / current.zoom
276 set({ x: Math.max(0, Math.min(1, current.x + dx * step)), y: Math.max(0, Math.min(1, current.y + dy * step)) })
277 }
278 const room = Math.max(320, Math.round((e.viewport?.columns ?? 100) * PX_PER_COLUMN) - 16)
279 const height = Math.round(Math.min((room * d.height) / d.width, Math.max(240, (e.viewport?.rows ?? 40) * 18)))
280 const width = Math.round(Math.min(room, (height * d.width) / d.height))
281 const zoomed = current.zoom > 1
282 return (
283 <Box flexDirection="column" rowGap={1} width="100%">
284 <Box flexDirection="row" columnGap={1} alignItems="center" flexWrap="wrap">
285 <Button key="zoom-out" label="−" onPress={() => set({ zoom: ZOOMS[Math.max(0, at - 1)]! })} />
286 <Text bold>{`${Math.round(current.zoom * 100)}%`}</Text>
287 <Button key="zoom-in" label="+" onPress={() => set({ zoom: ZOOMS[Math.min(ZOOMS.length - 1, at + 1)]! })} />
288 <Button key="zoom-fit" label="Fit" onPress={() => set({ zoom: 1, x: 0.5, y: 0.5 })} />
289 {zoomed && <Button key="pan-left" label="←" onPress={() => pan(-1, 0)} />}
290 {zoomed && <Button key="pan-up" label="↑" onPress={() => pan(0, -1)} />}
291 {zoomed && <Button key="pan-down" label="↓" onPress={() => pan(0, 1)} />}
292 {zoomed && <Button key="pan-right" label="→" onPress={() => pan(1, 0)} />}
293 <Button key="close" label="Close" role="dismiss" onPress={() => void $.ui.close({ id: VIEW })} />
294 </Box>
295 <el.Svg source={crop(d, current)} alt="mermaid diagram" width={width} height={height} isInteractive />
296 </Box>
297 )
298 })
299}
300hooks/blocks.ts 68 lines1export type AlertLevel = 'note' | 'tip' | 'important' | 'warning' | 'caution'
2
3export type Segment =
4 | { kind: 'markdown'; text: string }
5 | { kind: 'code'; lang: string; source: string }
6 | { kind: 'mermaid'; source: string }
7 | { kind: 'alert'; level: AlertLevel; text: string }
8
9const FENCE = /^ {0,3}(`{3,}|~{3,})\s*([^\s`]*)[^`]*$/
10const ALERT = /^ {0,3}>\s*\[!(note|tip|important|warning|caution)\]\s*$/i
11const QUOTE = /^ {0,3}>\s?(.*)$/
12const MAX_MARKDOWN = 9000
13
14const chunk = (text: string): string[] => {
15 if (text.length <= MAX_MARKDOWN) return [text]
16 const out: string[] = []
17 let current = ''
18 for (const para of text.split(/\n{2,}/)) {
19 const next = current ? `${current}\n\n${para}` : para
20 if (next.length > MAX_MARKDOWN && current) {
21 out.push(current)
22 current = para
23 } else current = next
24 }
25 if (current) out.push(current)
26 return out.flatMap(part => (part.length <= MAX_MARKDOWN ? [part] : part.match(new RegExp(`[\\s\\S]{1,${MAX_MARKDOWN}}`, 'g')) ?? []))
27}
28
29export const split = (text: string): Segment[] => {
30 const lines = text.replace(/\r\n?/g, '\n').split('\n')
31 const out: Segment[] = []
32 let prose: string[] = []
33 const flush = () => {
34 const body = prose.join('\n').replace(/^\n+|\n+$/g, '')
35 if (body.trim()) for (const part of chunk(body)) out.push({ kind: 'markdown', text: part })
36 prose = []
37 }
38 for (let i = 0; i < lines.length; i++) {
39 const line = lines[i]!
40 const fence = FENCE.exec(line)
41 if (fence) {
42 const mark = fence[1]!
43 const lang = (fence[2] ?? '').toLowerCase()
44 const body: string[] = []
45 let j = i + 1
46 while (j < lines.length && !new RegExp(`^ {0,3}${mark[0] === '`' ? '`' : '~'}{${mark.length},}\\s*$`).test(lines[j]!)) body.push(lines[j++]!)
47 flush()
48 const source = body.join('\n')
49 out.push(lang === 'mermaid' ? { kind: 'mermaid', source } : { kind: 'code', lang, source })
50 i = j
51 continue
52 }
53 const alert = ALERT.exec(line)
54 if (alert) {
55 const body: string[] = []
56 let j = i + 1
57 while (j < lines.length && QUOTE.test(lines[j]!)) body.push(QUOTE.exec(lines[j++]!)![1]!)
58 flush()
59 out.push({ kind: 'alert', level: alert[1]!.toLowerCase() as AlertLevel, text: body.join('\n').trim() })
60 i = j - 1
61 continue
62 }
63 prose.push(line)
64 }
65 flush()
66 return out
67}
68hooks/demo.ts 55 lines1const FENCE = '```'
2
3export const DEMO = [
4 '# ColorWheel',
5 '',
6 'Replies in the desktop app keep the app\'s own typography: **bold**, *italic*, `inline code`, [links](https://github.com/AlexeyHRDesign) and tables that wrap to the chat width.',
7 '',
8 '| Element | Drawn as | Theme |',
9 '|---|---|---|',
10 '| Text, lists, tables | the app\'s markdown | light and dark |',
11 '| Code | the app\'s code view | light and dark |',
12 '| Alerts | cards | one tone for both |',
13 '| Mermaid | full-width SVG | switches with the app |',
14 '',
15 '> [!NOTE]',
16 '> Diagrams have **Open large** for a zoomable view and **Copy source** for the mermaid code.',
17 '',
18 '> [!TIP]',
19 '> Ask Claude for a flow or a chart and it will reach for mermaid.',
20 '',
21 '> [!WARNING]',
22 '> The terminal keeps Claude Code\'s own renderer.',
23 '',
24 `${FENCE}ts`,
25 'export const greet = (name: string) => `hello, ${name}`',
26 FENCE,
27 '',
28 `${FENCE}mermaid`,
29 'flowchart LR',
30 ' R[Reply] --> S{Split}',
31 ' S -->|text| M[Markdown]',
32 ' S -->|code| C[Code view]',
33 ' S -->|mermaid| D[Diagram]',
34 FENCE,
35 '',
36 `${FENCE}mermaid`,
37 'sequenceDiagram',
38 ' participant U as You',
39 ' participant C as Claude',
40 ' participant W as ColorWheel',
41 ' U->>C: prompt',
42 ' C->>W: markdown',
43 ' W-->>U: themed reply',
44 FENCE,
45 '',
46 `${FENCE}mermaid`,
47 'xychart-beta',
48 ' title "Reply render time, ms"',
49 ' x-axis [Text, Table, Code, Diagram]',
50 ' y-axis "ms" 0 --> 450',
51 ' bar [410, 260, 190, 150]',
52 ' line [180, 120, 95, 80]',
53 FENCE,
54].join('\n')
55hooks/diagram.ts 98 lines1import type { Scheme } from './palette'
2import { DARK, LIGHT } from './palette'
3import { layoutFlowchart } from './layout'
4import type { Colors } from './vendor/mermaid.js'
5import {
6 layoutSequenceDiagram, layoutXYChart, parseMermaid, parseSequenceDiagram, parseXYChart,
7 renderMermaidAscii, renderSequenceSvg, renderSvg, renderXYChartSvg,
8} from './vendor/mermaid.js'
9
10export type Diagram = { svg: string; width: number; height: number }
11export type Crop = { zoom: number; x: number; y: number }
12
13const vars = (s: Scheme) =>
14 [
15 `--cw-bg:${s.bg}`, `--cw-fg:${s.fg}`, `--cw-line:${s.line}`, `--cw-accent:${s.wheel[0]}`, `--cw-muted:${s.muted}`,
16 `--cw-surface:${s.surface}`, `--cw-border:${s.border}`, ...s.wheel.map((c, i) => `--cw-s${i}:${c}`),
17 ].join(';')
18
19const THEME = `<style>svg{${vars(LIGHT)}}@media (prefers-color-scheme: dark){svg{${vars(DARK)}}}`
20 + `text{font-family:system-ui,-apple-system,'Segoe UI',sans-serif}.mono,text.mono{font-family:ui-monospace,'Cascadia Mono',Consolas,monospace}</style>`
21
22const COLORS: Colors = {
23 bg: 'var(--cw-bg)', fg: 'var(--cw-fg)', line: 'var(--cw-line)', accent: 'var(--cw-accent)',
24 muted: 'var(--cw-muted)', surface: 'var(--cw-surface)', border: 'var(--cw-border)',
25}
26const FONT = 'system-ui'
27
28const esc = (t: string) => t.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
29
30const artSvg = (art: string): string => {
31 const rows = art.split('\n')
32 const cols = Math.max(1, ...rows.map(r => [...r].length))
33 const w = Math.ceil(cols * 8.4) + 16
34 const h = rows.length * 18 + 16
35 const body = rows.map((r, i) => `<text x="8" y="${22 + i * 18}" class="mono" fill="var(--cw-fg)" xml:space="preserve">${esc(r)}</text>`).join('')
36 return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${w} ${h}" width="${w}" height="${h}" style="--bg:var(--cw-bg)"><style>text{font-size:14px;white-space:pre}</style>${body}</svg>`
37}
38
39const render = (source: string): string => {
40 const lines = source.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('%%'))
41 const head = (lines[0] ?? '').toLowerCase()
42 if (/^xychart(-beta)?\b/.test(head)) return renderXYChartSvg(layoutXYChart(parseXYChart(lines)), COLORS, FONT, true, true)
43 if (/^sequencediagram\s*$/.test(head)) return renderSequenceSvg(layoutSequenceDiagram(parseSequenceDiagram(lines)), COLORS, FONT, true)
44 if (/^(classdiagram|erdiagram)\s*$/.test(head)) return artSvg(renderMermaidAscii(source, { colorMode: 'none', paddingX: 3, paddingY: 1 }).replace(/[ \t]+$/gm, '').trimEnd())
45 if (/^(graph|flowchart|statediagram(-v2)?)\b/.test(head)) return renderSvg(layoutFlowchart(parseMermaid(lines.join('\n'))), COLORS, FONT, true)
46 throw new Error(`unsupported diagram: ${head}`)
47}
48
49export let lastError = ''
50const cache = new Map<string, Diagram | null>()
51
52export const diagram = (source: string): Diagram | null => {
53 const hit = cache.get(source)
54 if (hit !== undefined) return hit
55 let result: Diagram | null = null
56 try {
57 const raw = render(source)
58 const size = /<svg[^>]*?\swidth="([\d.]+)"[^>]*?\sheight="([\d.]+)"/.exec(raw)
59 if (size) {
60 const svg = raw
61 .replace(/@import url\([^)]*\);?/g, '')
62 .replace(/(--xychart-color-(\d+)):\s*[^;]+;/g, (_m, name: string, i: string) => `${name}: var(--cw-s${Number(i) % 6});`)
63 .replace(/(<svg[^>]*>)/, `$1${THEME}`)
64 result = { svg, width: Number(size[1]), height: Number(size[2]) }
65 }
66 } catch (err) {
67 lastError = String((err as Error)?.stack ?? err)
68 result = null
69 }
70 cache.set(source, result)
71 if (cache.size > 100) cache.delete(cache.keys().next().value!)
72 return result
73}
74
75export const PX_PER_COLUMN = 8.2
76const MAX_SCALE = 2
77const MAX_HEIGHT = 640
78
79export const fit = (d: Diagram, columns: number): { width: number; height: number } => {
80 const room = Math.max(320, Math.round(columns * PX_PER_COLUMN))
81 let width = Math.min(room, d.width * MAX_SCALE)
82 let height = (width * d.height) / d.width
83 if (height > MAX_HEIGHT) {
84 height = MAX_HEIGHT
85 width = (height * d.width) / d.height
86 }
87 return { width: Math.round(width), height: Math.round(height) }
88}
89
90export const crop = (d: Diagram, view: Crop): string => {
91 const vw = d.width / view.zoom
92 const vh = d.height / view.zoom
93 const clamp = (v: number, max: number) => Math.max(0, Math.min(max, v))
94 const x = clamp(view.x * d.width - vw / 2, d.width - vw)
95 const y = clamp(view.y * d.height - vh / 2, d.height - vh)
96 return d.svg.replace(/viewBox="[^"]*"/, `viewBox="${x.toFixed(1)} ${y.toFixed(1)} ${vw.toFixed(1)} ${vh.toFixed(1)}"`)
97}
98hooks/palette.ts 82 lines1export type Scheme = {
2 bg: string
3 fg: string
4 line: string
5 muted: string
6 surface: string
7 border: string
8 wheel: readonly string[]
9}
10
11export const LIGHT: Scheme = {
12 bg: '#ffffff',
13 fg: '#29261b',
14 line: '#a8a29e',
15 muted: '#6f6a64',
16 surface: '#f1f5fe',
17 border: '#9db8ef',
18 wheel: ['#2563eb', '#0f8a7e', '#c2410c', '#7c3aed', '#be185d', '#4d7c0f'],
19}
20
21export const DARK: Scheme = {
22 bg: '#262624',
23 fg: '#ece9e3',
24 line: '#77726b',
25 muted: '#aaa59e',
26 surface: '#28324a',
27 border: '#5677c2',
28 wheel: ['#7aa7ff', '#5fd0c4', '#f5a25d', '#b49cff', '#f38bb8', '#a5d16b'],
29}
30
31type Rgb = [number, number, number]
32
33export const toRgb = (hex: string): Rgb | null => {
34 const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex.trim())
35 return m ? [parseInt(m[1]!, 16), parseInt(m[2]!, 16), parseInt(m[3]!, 16)] : null
36}
37
38const toHex = (rgb: Rgb) => `#${rgb.map(v => Math.round(Math.max(0, Math.min(255, v))).toString(16).padStart(2, '0')).join('')}`
39
40const luminance = ([r, g, b]: Rgb) => {
41 const lin = (v: number) => {
42 const s = v / 255
43 return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4
44 }
45 return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b)
46}
47
48export const contrast = (a: Rgb, b: Rgb): number => {
49 const [x, y] = [luminance(a), luminance(b)].sort((p, q) => q - p) as [number, number]
50 return (x + 0.05) / (y + 0.05)
51}
52
53const mix = (a: Rgb, b: Rgb, t: number): Rgb => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t]
54
55export const bridge = (light: string, dark: string): string => {
56 const a = toRgb(light)!
57 const b = toRgb(dark)!
58 const lightBg = toRgb(LIGHT.bg)!
59 const darkBg = toRgb(DARK.bg)!
60 let best = a
61 let score = -1
62 for (let i = 0; i <= 40; i++) {
63 const c = mix(a, b, i / 40)
64 const s = Math.min(contrast(c, lightBg), contrast(c, darkBg))
65 if (s > score) {
66 score = s
67 best = c
68 }
69 }
70 return toHex(best)
71}
72
73export const ALERTS = {
74 note: { title: 'Note', hue: 0 },
75 tip: { title: 'Tip', hue: 1 },
76 important: { title: 'Important', hue: 3 },
77 warning: { title: 'Warning', hue: 2 },
78 caution: { title: 'Caution', hue: 4 },
79} as const
80
81export const alertColor = (level: keyof typeof ALERTS): string => bridge(LIGHT.wheel[ALERTS[level].hue]!, DARK.wheel[ALERTS[level].hue]!)
82hooks/frame.ts 183 lines1import { DARK, LIGHT } from './palette'
2import type { Summary } from './progress'
3import type { Pill } from './weather'
4
5// The desktop band: one rounded frame inside the app's own block. Its top half is the
6// 5-hour limit, its bottom half the 7-day limit; each is empty while the budget is untouched
7// and grows from the left as it is used. Tasks fill the inside from the left.
8
9const R = 11
10const PAD = 16
11const CHAR = 6.6
12const METRIC_GAP = 16
13const BASE_HEIGHT = 36
14const EDGE_INSET = 5
15// The band pulls the Svg one cell out past the app's padding; this much of it comes back on the sides.
16const SIDE_INSET = 6
17const TAG_CHAR = 5.5
18const TAG_PAD = 3
19const TAG_FONT = 9.5
20const TEXT_FADE = 28
21
22// Fixed colour per budget, so an edge keeps its identity as it wipes; context takes its forecast tone.
23const EDGE: Record<string, number> = { '5h': 0, '7d': 2 }
24export const ringOf = (p: Pill) => (p.icon ? p.tone : EDGE[p.tag] ?? 4)
25
26const esc = (s: string) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
27const textWidth = (s: string) => s.length * CHAR
28
29const tones = (wheel: readonly string[]) => wheel.map((c, i) => `.t${i}{color:${c}}`).join('')
30
31const css =
32 `svg{display:block;overflow:visible}text{font:500 12px ui-sans-serif,system-ui,sans-serif;font-variant-numeric:tabular-nums;dominant-baseline:central}` +
33 `.track{fill:none;stroke:${LIGHT.line};stroke-opacity:.28;stroke-width:1.5}` +
34 `.ring{fill:none;stroke:currentColor;stroke-width:2}` +
35 `.wash{fill:currentColor;fill-opacity:.1}` +
36 `.pace{fill:${LIGHT.fg};fill-opacity:.55}` +
37 `.edge-tag{font-size:${TAG_FONT}px;font-weight:600;fill:currentColor}` +
38 `.icon{fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}` +
39 `.fg{fill:${LIGHT.fg}}.muted{fill:${LIGHT.muted}}.bold{font-weight:650}.tone{fill:currentColor}` +
40 `.hit{fill:transparent}.metric:hover .hit{fill:${LIGHT.line};fill-opacity:.14}${tones(LIGHT.wheel)}` +
41 `@media (prefers-color-scheme:dark){.track{stroke:${DARK.line}}.pace{fill:${DARK.fg}}.fg{fill:${DARK.fg}}.muted{fill:${DARK.muted}}` +
42 `.wash{fill-opacity:.16}.metric:hover .hit{fill:${DARK.line}}${tones(DARK.wheel)}}`
43
44type Span = { text: string; cls: string; tone?: number }
45
46const spans = (s: Summary): Span[] => {
47 const out: Span[] = []
48 const tone = s.isFinished ? 1 : 0
49 if (s.agentsTotal) {
50 out.push({ text: 'Agents ', cls: 'fg bold' })
51 out.push(s.running ? { text: `${s.running} running`, cls: 'tone', tone: 0 } : { text: 'none running', cls: 'fg' })
52 out.push({ text: ` · ${s.agentsDone} done `, cls: 'muted' })
53 }
54 if (s.tasksTotal || s.agentsTotal) {
55 out.push({ text: s.isFinished ? 'All done ' : s.tasksTotal ? 'Tasks ' : 'Progress ', cls: 'fg bold' })
56 out.push({ text: s.tasksTotal ? `${s.tasksDone}/${s.tasksTotal}` : `${s.agentsDone}/${s.agentsTotal}`, cls: 'tone', tone })
57 if (s.current && !s.isFinished) out.push({ text: ` · ${s.current}`, cls: 'muted' })
58 }
59 return out
60}
61
62export const ratioOf = (s: Summary) => (s.tasksTotal ? s.tasksDone / s.tasksTotal : s.agentsTotal ? s.agentsDone / s.agentsTotal : 0)
63
64// Widths are CSS calc() against the frame's own width, so the drawing fits whatever slot the band gives it.
65const rect = (cls: string, inset: number, h: number) => {
66 const x = inset - EDGE_INSET + SIDE_INSET
67 return `<rect class="${cls}" x="${x}" y="${inset}" style="width:calc(100% - ${2 * x}px)" height="${(h - 2 * inset).toFixed(1)}" rx="${Math.max(3, R - inset + 1).toFixed(1)}"/>`
68}
69// A mask that keeps the left `ratio` of the frame and lets the cut end fade out softly.
70const FADE = 6
71// Percent of the width a label takes past the edge's end, roughly; a pace tick in it moves the label.
72const PACE_ROOM = 9
73const share = (id: string, ratio: number, y: number, h: number) => {
74 const end = ratio * 100
75 const start = Math.max(0, end - FADE)
76 return `<linearGradient id="${id}g" gradientUnits="userSpaceOnUse" x1="${start.toFixed(2)}%" y1="0" x2="${end.toFixed(2)}%" y2="0"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient>` +
77 `<mask id="${id}" maskUnits="userSpaceOnUse" x="0" y="${y}" width="100%" height="${h}"><rect x="0" y="${y}" width="100%" height="${h}" fill="url(#${id}g)"/></mask>`
78}
79
80// `left` labels the edges as the share left; `slot` keeps that many px free left of the metrics,
81// where the caller lays a control over the drawing. `slotRight` is that gap's right end, in px from the right.
82export type FrameOptions = { left?: boolean; slot?: number }
83
84export const frame = (s: Summary | null, list: readonly Pill[], opts: FrameOptions = {}): { svg: string; alt: string; height: number; slotRight: number } => {
85 const slot = opts.slot ?? 0
86 const h = BASE_HEIGHT
87 const mid = h / 2
88 const inner = SIDE_INSET
89 const defs: string[] = []
90 const body: string[] = []
91 const hasProgress = !!s && (s.isActive || s.isFinished)
92
93 // Tasks: a wash inside the frame, growing from the left.
94 if (hasProgress) {
95 defs.push(share('tasks', ratioOf(s!), 0, h))
96 body.push(`<g class="t${s!.isFinished ? 1 : 0}" mask="url(#tasks)">${rect('wash', EDGE_INSET + 1.5, h)}</g>`)
97 }
98
99 // The frame: top half the 5-hour limit, bottom half the 7-day, each drawn from the left as far as the share used.
100 // Its percent sits on the edge itself, just past where the colour ends, in a gap cut out of the line;
101 // near the right corner it flips to sit before the end.
102 const edges: string[] = [rect('track', EDGE_INSET, h)]
103 const tags: string[] = []
104 const cuts: string[] = []
105 for (const [tag, y] of [['5h', 0], ['7d', mid]] as const) {
106 const p = list.find(x => x.tag === tag)
107 if (!p) continue
108 const left = Math.max(0, Math.min(100, p.percent)) / 100
109 if (left > 0) {
110 defs.push(share(`e${tag}`, left, y, mid))
111 edges.push(`<g class="t${ringOf(p)}" mask="url(#e${tag})">${rect('ring', EDGE_INSET, h)}</g>`)
112 }
113 const label = `${tag} ${p.percent}%${opts.left ? ' left' : ''}`
114 // The label also steps to the other side of the edge's end when the pace tick sits there.
115 const near = (from: number, to: number) => p.pace !== undefined && p.pace - p.percent >= from && p.pace - p.percent <= to
116 const flip = left > 0.85 ? !near(-PACE_ROOM, 0) : near(0, PACE_ROOM)
117 const at = `${(left * 100).toFixed(2)}%`
118 const ty = y === 0 ? EDGE_INSET : h - EDGE_INSET
119 const width = label.length * TAG_CHAR + 2 * TAG_PAD
120 const from = flip ? `calc(${at} - ${(width + 4).toFixed(1)}px)` : `calc(${at} + 4px)`
121 cuts.push(`<rect y="${ty - 6}" height="12" style="x:${from};width:${width.toFixed(1)}px" fill="#000"/>`)
122 // The whole edge answers with the tooltip, not only its small label.
123 const hitY = y === 0 ? 0 : h - 2 * EDGE_INSET
124 tags.push(`<rect class="hit" x="0" y="${hitY}" width="100%" height="${2 * EDGE_INSET}"><title>${esc(p.tip.join('\n'))}</title></rect>`)
125 tags.push(
126 `<g class="t${ringOf(p)}"><title>${esc(p.tip.join('\n'))}</title><text class="edge-tag" x="${at}" dx="${flip ? -(4 + TAG_PAD) : 4 + TAG_PAD}" y="${ty}" text-anchor="${flip ? 'end' : 'start'}">${esc(label)}</text></g>`,
127 )
128 // Pace: where the edge would end if the budget were spent evenly across its window.
129 if (p.pace !== undefined) {
130 const px = Math.max(0, Math.min(100, p.pace))
131 tags.push(`<rect class="pace" y="${ty - 4}" height="8" rx="1" style="x:calc(${px.toFixed(2)}% - 1px);width:2px"><title>${esc(p.tip.join('\n'))}</title></rect>`)
132 }
133 }
134 defs.push(`<mask id="cut" maskUnits="userSpaceOnUse" x="0" y="0" width="100%" height="${h}"><rect x="0" y="0" width="100%" height="${h}" fill="#fff"/>${cuts.join('')}</mask>`)
135 body.push(`<g mask="url(#cut)">${edges.join('')}</g>`, ...tags)
136
137 // Metrics, right-aligned inside the frames, each labelled in its frame's colour.
138 let right = 0
139 const metrics: string[] = []
140 for (const p of [...list].reverse().filter(x => !(x.tag in EDGE))) {
141 const value = `${p.percent}%`
142 const ring = ringOf(p)
143 const lead = p.icon ? 18 : textWidth(p.tag) + 4
144 const mw = lead + textWidth(value)
145 const x = right - mw
146 const icon = p.icon ? `<g class="icon t${ring}" transform="translate(${x.toFixed(1)} ${mid - 7})">${p.icon}</g>` : ''
147 const tag = p.tag ? `<text class="tone t${ring}" x="${x.toFixed(1)}" y="${mid}">${esc(p.tag)}</text>` : ''
148 const valueTone = p.used >= 80 ? ` class="tone t4 bold"` : ` class="fg"`
149 metrics.push(
150 `<g class="metric"><title>${esc(p.tip.join('\n'))}</title>` +
151 `<rect class="hit" x="${(x - 6).toFixed(1)}" y="${inner + 2}" width="${(mw + 12).toFixed(1)}" height="${(h - 2 * inner - 4).toFixed(1)}" rx="5"/>` +
152 `${icon}${tag}<text${valueTone} x="${(x + lead).toFixed(1)}" y="${mid}">${value}</text></g>`,
153 )
154 right = x - METRIC_GAP
155 }
156 const metricsWidth = Math.max(0, -right - METRIC_GAP)
157 const slotRight = inner + PAD + metricsWidth + (metricsWidth ? METRIC_GAP : 0)
158 body.push(`<svg x="100%" y="0" overflow="visible"><g transform="translate(${-(inner + PAD)} 0)">${metrics.join('')}</g></svg>`)
159
160 // Progress text on the left; where it would run into the metrics it fades out rather than cutting a word.
161 if (hasProgress) {
162 const reserve = 2 * (inner + PAD) + metricsWidth + METRIC_GAP + slot
163 const solid = `calc(100% - ${(reserve + TEXT_FADE).toFixed(0)}px)`
164 defs.push(
165 `<linearGradient id="textg"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient>` +
166 `<mask id="text" maskUnits="userSpaceOnUse" x="0" y="0" width="100%" height="${h}">` +
167 `<rect x="0" y="0" style="width:${solid}" height="${h}" fill="#fff"/>` +
168 `<rect y="0" style="x:${solid};width:${TEXT_FADE}px" height="${h}" fill="url(#textg)"/></mask>`,
169 )
170 const tspans = spans(s!).map(sp => `<tspan class="${sp.cls}${sp.tone === undefined ? '' : ` t${sp.tone}`}">${esc(sp.text)}</tspan>`)
171 body.push(`<g mask="url(#text)"><text x="${inner + PAD}" y="${mid}" xml:space="preserve">${tspans.join('')}</text></g>`)
172 } else if (!list.length) {
173 body.push(`<text class="muted" x="${inner + PAD}" y="${mid}">Context and limits show after the first reply</text>`)
174 }
175
176 const alt = [
177 ...(hasProgress ? [spans(s!).map(x => x.text).join('').replace(/\s+/g, ' ').trim()] : []),
178 ...list.map(p => p.tip[0]!),
179 ].join('; ')
180 const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="${h}"><style>${css}</style><defs>${defs.join('')}</defs>${body.join('')}</svg>`
181 return { svg, alt, height: h, slotRight }
182}
183hooks/progress.tsx 105 lines1import type { ElementTable, RenderElement } from 'claude-code'
2
3import type { Progress, Todo } from '../types'
4import { DARK, LIGHT, bridge } from './palette'
5
6export const EMPTY: Progress = { agents: [], queued: [], tasks: [], todos: [] }
7
8export const agentQueued = (p: Progress, type: string, label: string): Progress => ({ ...p, queued: [...p.queued, { type, label }] })
9
10export const agentStarted = (p: Progress, id: string, type: string): Progress => {
11 if (p.agents.some(a => a.id === id)) return p
12 const at = p.queued.findIndex(q => q.type === type)
13 const label = at === -1 ? type : p.queued[at]!.label
14 return { ...p, queued: p.queued.filter((_, i) => i !== at), agents: [...p.agents, { id, type, label, isDone: false }] }
15}
16
17export const agentStopped = (p: Progress, id: string): Progress => ({ ...p, agents: p.agents.map(a => (a.id === id ? { ...a, isDone: true } : a)) })
18
19export const taskCreated = (p: Progress, id: string, subject: string): Progress =>
20 p.tasks.some(t => t.id === id) ? p : { ...p, tasks: [...p.tasks, { id, subject, isDone: false }] }
21
22export const taskCompleted = (p: Progress, id: string): Progress => ({ ...p, tasks: p.tasks.map(t => (t.id === id ? { ...t, isDone: true } : t)) })
23
24export const todosWritten = (p: Progress, todos: readonly Todo[]): Progress => ({ ...p, todos: todos.map(t => ({ content: t.content, status: t.status, ...(t.activeForm ? { activeForm: t.activeForm } : {}) })) })
25
26export type Summary = {
27 running: number
28 agentsDone: number
29 agentsTotal: number
30 tasksDone: number
31 tasksTotal: number
32 current?: string
33 isActive: boolean
34 isFinished: boolean
35}
36
37export const summarize = (p: Progress): Summary => {
38 const running = p.agents.filter(a => !a.isDone)
39 const tasksTotal = p.todos.length + p.tasks.length
40 const tasksDone = p.todos.filter(t => t.status === 'completed').length + p.tasks.filter(t => t.isDone).length
41 const doing = p.todos.find(t => t.status === 'in_progress')
42 const current = doing ? doing.activeForm ?? doing.content : p.tasks.find(t => !t.isDone)?.subject ?? running[0]?.label
43 const isActive = running.length > 0 || tasksDone < tasksTotal
44 return {
45 running: running.length,
46 agentsDone: p.agents.length - running.length,
47 agentsTotal: p.agents.length,
48 tasksDone,
49 tasksTotal,
50 ...(current ? { current } : {}),
51 isActive,
52 isFinished: !isActive && (p.agents.length > 0 || tasksTotal > 0),
53 }
54}
55
56const ACCENT = bridge(LIGHT.wheel[0]!, DARK.wheel[0]!)
57const DONE = bridge(LIGHT.wheel[1]!, DARK.wheel[1]!)
58const TRACK = '#8a857e'
59const BAR = 20
60
61const clip = (text: string, max: number) => (text.length > max ? `${text.slice(0, max - 1)}…` : text)
62
63export const drawBand = (el: ElementTable, s: Summary, surface: string, columns: number): RenderElement => {
64 const { Box, Text } = el
65 const ratio = s.tasksTotal ? s.tasksDone / s.tasksTotal : s.agentsTotal ? s.agentsDone / s.agentsTotal : 0
66 const tone = s.isFinished ? DONE : ACCENT
67 const bar = surface === 'terminal'
68 ? (
69 <Text>
70 <Text color={tone}>{'▰'.repeat(Math.round(ratio * BAR))}</Text>
71 <Text dimColor>{'▱'.repeat(BAR - Math.round(ratio * BAR))}</Text>
72 </Text>
73 )
74 : (
75 <Box width="24%" flexShrink={0} backgroundColor={TRACK}>
76 <Box width={`${Math.max(ratio > 0 ? 3 : 0, Math.round(ratio * 100))}%`} backgroundColor={tone}><Text> </Text></Box>
77 </Box>
78 )
79 const parts: RenderElement[] = []
80 if (s.agentsTotal) {
81 parts.push(
82 <Text key="agents">
83 <Text bold>Agents </Text>
84 <Text color={s.running ? ACCENT : undefined}>{s.running ? `${s.running} running` : 'none running'}</Text>
85 <Text dimColor>{` · ${s.agentsDone} done`}</Text>
86 </Text>,
87 )
88 }
89 if (s.tasksTotal || s.agentsTotal) {
90 parts.push(
91 <Box key="bar" flexDirection="row" columnGap={1} alignItems="center" flexGrow={1}>
92 <Text bold>{s.isFinished ? 'All done' : s.tasksTotal ? 'Tasks' : 'Progress'}</Text>
93 {bar}
94 <Text color={tone}>{s.tasksTotal ? `${s.tasksDone}/${s.tasksTotal}` : `${s.agentsDone}/${s.agentsTotal}`}</Text>
95 {s.current && !s.isFinished ? <Text dimColor wrap="truncate-end">{`· ${clip(s.current, Math.max(20, columns - 60))}`}</Text> : null}
96 </Box>,
97 )
98 }
99 return (
100 <Box flexDirection="row" columnGap={3} alignItems="center" width="100%">
101 {parts}
102 </Box>
103 )
104}
105hooks/weather.tsx 146 lines1import type { ElementTable, RenderElement } from 'claude-code'
2
3import type { Reading, Weather } from '../types'
4
5export const HISTORY = 12
6export const QUIET: Weather = { readings: [], limits: [] }
7
8type Forecast = { upTo: number; word: string; glyph: string; icon: string; tone: number }
9
10const CLOUD = 'M4.6 11h5.9a2.4 2.4 0 0 0 .3-4.8 3.4 3.4 0 0 0-6.5-.8A2.5 2.5 0 0 0 4.6 11z'
11const CLOUD_UP = 'M4.6 9h5.9a2.4 2.4 0 0 0 .3-4.8 3.4 3.4 0 0 0-6.5-.8A2.5 2.5 0 0 0 4.6 9z'
12const RAYS = Array.from({ length: 8 }, (_, i) => {
13 const a = (i * Math.PI) / 4
14 const p = (r: number) => `${(7 + r * Math.cos(a)).toFixed(2)} ${(7 + r * Math.sin(a)).toFixed(2)}`
15 return `M${p(4.4)}L${p(6.1)}`
16}).join('')
17
18const FORECAST: readonly Forecast[] = [
19 { upTo: 25, word: 'Clear', glyph: '☀', tone: 1, icon: `<circle cx="7" cy="7" r="2.5"/><path d="${RAYS}"/>` },
20 { upTo: 50, word: 'Cloudy', glyph: '☁', tone: 0, icon: `<path d="${CLOUD}"/>` },
21 { upTo: 75, word: 'Showers', glyph: '☂', tone: 3, icon: `<path d="${CLOUD_UP}"/><path d="M5.2 11l-.6 1.6M8 11l-.6 1.6M10.8 11l-.6 1.6"/>` },
22 { upTo: 90, word: 'Storm', glyph: '☇', tone: 2, icon: `<path d="${CLOUD_UP}"/><path d="M7.8 9.4 6.6 11.5h1.8l-1.2 2.1"/>` },
23 { upTo: Infinity, word: 'Compact soon', glyph: '↯', tone: 4, icon: `<path d="M8.2 1.5 4 8h3.3l-1.1 4.5L10.4 6H7z"/>` },
24]
25
26export const forecastFor = (percent: number): Forecast => FORECAST.find(f => percent < f.upTo) ?? FORECAST[FORECAST.length - 1]!
27
28export const addReading = (readings: readonly Reading[], r: Reading): Reading[] =>
29 [...readings.filter(x => x.tokens > 0), r].slice(-HISTORY)
30
31export const short = (n: number): string => {
32 if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(n % 1_000_000 === 0 ? 0 : 1)}M`
33 if (n >= 1_000) return `${(n / 1_000).toFixed(n % 1_000 === 0 ? 0 : 1)}k`
34 return String(n)
35}
36
37export const trend = (readings: readonly Reading[]): string => {
38 if (readings.length < 2) return ''
39 const delta = readings.at(-1)!.tokens - readings.at(-2)!.tokens
40 if (delta > 0) return `▲ ${short(delta)} last turn`
41 if (delta < 0) return `▼ ${short(-delta)} last turn`
42 return 'steady last turn'
43}
44
45const BARS = '▁▂▃▄▅▆▇█'
46
47const chart = (readings: readonly Reading[]) => {
48 const top = Math.max(...readings.map(r => r.tokens), 1)
49 return readings.map(r => BARS[Math.min(BARS.length - 1, Math.floor((r.tokens / top) * (BARS.length - 1)))]).join('')
50}
51
52const HOUR = 3_600_000
53const WINDOWS: Record<string, { tag: string; name: string; ms?: number }> = {
54 five_hour: { tag: '5h', name: '5-hour limit', ms: 5 * HOUR },
55 seven_day: { tag: '7d', name: '7-day limit', ms: 7 * 24 * HOUR },
56 spend_limit: { tag: '$', name: 'Spend limit' },
57}
58
59const limitTone = (percent: number) => (percent < 50 ? 1 : percent < 80 ? 2 : 4)
60
61export const resetsIn = (resetsAt: string | undefined, now: number): string => {
62 const at = resetsAt ? Date.parse(resetsAt) : NaN
63 if (Number.isNaN(at)) return ''
64 const minutes = Math.max(0, Math.round((at - now) / 60_000))
65 const d = Math.floor(minutes / 1440)
66 const h = Math.floor((minutes % 1440) / 60)
67 const m = minutes % 60
68 return `resets in ${d ? `${d}d ${h}h` : h ? `${h}h ${m}m` : `${m}m`}`
69}
70
71// The share of a limit's window already gone: spending at this share is spending at pace.
72export const elapsed = (resetsAt: string | undefined, ms: number | undefined, now: number): number | undefined => {
73 const at = resetsAt ? Date.parse(resetsAt) : NaN
74 if (!ms || Number.isNaN(at)) return undefined
75 return Math.round(Math.max(0, Math.min(100, 100 - ((at - now) / ms) * 100)))
76}
77
78const paceLine = (gone: number, used: number) => {
79 const d = used - gone
80 return `${gone}% of the window gone, ${d === 0 ? 'on pace' : `${Math.abs(d)} points ${d > 0 ? 'over' : 'under'} pace`}`
81}
82
83// `percent` is what the band shows: the share used, or with `left` the share left.
84// `used` is always the share used, for tones; `pace` sits on the same scale as `percent`.
85export type Pill = { tag: string; percent: number; used: number; pace?: number; tone: number; icon?: string; glyph?: string; tip: string[] }
86
87export const pills = (w: Weather, now: number, left = false): Pill[] => {
88 const shown = (used: number) => (left ? Math.max(0, 100 - used) : used)
89 const out: Pill[] = []
90 const r = w.readings.at(-1)
91 if (r) {
92 const f = forecastFor(r.percent)
93 out.push({
94 tag: '',
95 percent: shown(r.percent),
96 used: r.percent,
97 tone: f.tone,
98 icon: f.icon,
99 glyph: f.glyph,
100 tip: [
101 `${f.word} · ${r.percent}% of context`,
102 `${short(r.tokens)} of ${short(r.window)} tokens`,
103 ...(w.readings.length > 1 ? [`Last ${w.readings.length} turns ${chart(w.readings)}`] : []),
104 ...(trend(w.readings) ? [trend(w.readings)] : []),
105 ],
106 })
107 }
108 for (const l of w.limits) {
109 const known = WINDOWS[l.kind] ?? { tag: l.kind, name: l.kind }
110 const percent = Math.round(l.percentUsed)
111 const reset = resetsIn(l.resetsAt, now)
112 const gone = elapsed(l.resetsAt, known.ms, now)
113 out.push({
114 tag: known.tag,
115 percent: shown(percent),
116 used: percent,
117 ...(gone === undefined ? {} : { pace: shown(gone) }),
118 tone: limitTone(percent),
119 tip: [`${known.name} · ${percent}% used, ${Math.max(0, 100 - percent)}% left`, ...(gone === undefined ? [] : [paceLine(gone, percent)]), ...(reset ? [reset] : [])],
120 })
121 }
122 return out
123}
124
125const TERMINAL_TONES = ['blue', 'cyan', 'yellow', 'magenta', 'red', 'green']
126
127export const INVERT_KEY = 'invert'
128export const INVERT_GLYPH = '⇆'
129
130export const drawWeather = (el: ElementTable, w: Weather, now: number, left: boolean, toggle: () => void): RenderElement | null => {
131 const list = pills(w, now, left)
132 if (!list.length) return null
133 const { Box, Text, Button } = el
134 return (
135 <Box key="weather" flexShrink={0} columnGap={2} flexDirection="row">
136 <Button key={INVERT_KEY} label={INVERT_GLYPH} plain dimColor onPress={toggle} />
137 {list.map((p, i) => (
138 <Text key={`w${i}`}>
139 <Text color={TERMINAL_TONES[p.tone]}>{p.glyph ?? p.tag}</Text>
140 <Text>{` ${p.percent}%`}</Text>
141 </Text>
142 ))}
143 </Box>
144 )
145}
146hooks/layout.ts 242 lines1import type { MermaidGraph, MermaidSubgraph, Point, PositionedEdge, PositionedGraph, PositionedGroup, PositionedNode } from './vendor/mermaid.js'
2import { FONT_SIZES, FONT_WEIGHTS, NODE_PADDING, measureMultilineText } from './vendor/mermaid.js'
3
4const RANK_GAP = 56
5const NODE_GAP = 28
6const MARGIN = 24
7const GROUP_PAD = 16
8const GROUP_HEADER = 26
9const SWEEPS = 6
10const ELBOW = 18
11const WHEEL = 6
12
13type Box = { id: string; w: number; h: number; virtual: boolean; rank: number; order: number; x: number; y: number }
14
15const sizeOf = (label: string, shape: string): { w: number; h: number } => {
16 const text = measureMultilineText(label || ' ', FONT_SIZES.nodeLabel, FONT_WEIGHTS.nodeLabel)
17 let w = text.width + NODE_PADDING.horizontal * 2
18 let h = text.height + NODE_PADDING.vertical * 2
19 if (shape === 'diamond') {
20 w += NODE_PADDING.diamondExtra * 2
21 h += NODE_PADDING.diamondExtra
22 }
23 if (shape === 'circle' || shape === 'doublecircle') w = h = Math.max(w, h)
24 return { w: Math.max(w, 48), h: Math.max(h, 36) }
25}
26
27const rankNodes = (ids: string[], edges: { source: string; target: string }[]): Map<string, number> => {
28 const out = new Map<string, string[]>(ids.map(id => [id, []]))
29 const state = new Map<string, 0 | 1 | 2>()
30 const forward: { source: string; target: string }[] = []
31 const visit = (id: string) => {
32 state.set(id, 1)
33 for (const e of edges.filter(e => e.source === id)) {
34 if (e.source === e.target) continue
35 if (state.get(e.target) === 1) continue
36 forward.push(e)
37 if (!state.get(e.target)) visit(e.target)
38 }
39 state.set(id, 2)
40 }
41 for (const id of ids) if (!state.get(id)) visit(id)
42 for (const e of forward) out.get(e.source)?.push(e.target)
43 const rank = new Map<string, number>(ids.map(id => [id, 0]))
44 const indegree = new Map<string, number>(ids.map(id => [id, 0]))
45 for (const e of forward) indegree.set(e.target, (indegree.get(e.target) ?? 0) + 1)
46 const queue = ids.filter(id => indegree.get(id) === 0)
47 while (queue.length) {
48 const id = queue.shift()!
49 for (const next of out.get(id) ?? []) {
50 rank.set(next, Math.max(rank.get(next)!, rank.get(id)! + 1))
51 indegree.set(next, indegree.get(next)! - 1)
52 if (indegree.get(next) === 0) queue.push(next)
53 }
54 }
55 return rank
56}
57
58export const layoutFlowchart = (graph: MermaidGraph): PositionedGraph => {
59 const horizontal = graph.direction === 'LR' || graph.direction === 'RL'
60 const reversed = graph.direction === 'BT' || graph.direction === 'RL'
61 const ids = [...graph.nodes.keys()]
62 const rank = rankNodes(ids, graph.edges)
63 const boxes = new Map<string, Box>()
64 for (const id of ids) {
65 const node = graph.nodes.get(id)!
66 const { w, h } = sizeOf(node.label, node.shape)
67 boxes.set(id, { id, w, h, virtual: false, rank: rank.get(id)!, order: 0, x: 0, y: 0 })
68 }
69
70 const chains = new Map<number, string[]>()
71 const links: [string, string][] = []
72 graph.edges.forEach((e, i) => {
73 const a = boxes.get(e.source)
74 const b = boxes.get(e.target)
75 if (!a || !b) return
76 const [lo, hi] = a.rank <= b.rank ? [a, b] : [b, a]
77 const chain = [lo.id]
78 for (let r = lo.rank + 1; r < hi.rank; r++) {
79 const id = `__v${i}_${r}`
80 boxes.set(id, { id, w: 8, h: 8, virtual: true, rank: r, order: 0, x: 0, y: 0 })
81 chain.push(id)
82 }
83 chain.push(hi.id)
84 for (let k = 1; k < chain.length; k++) links.push([chain[k - 1]!, chain[k]!])
85 chains.set(i, a.rank <= b.rank ? chain : [...chain].reverse())
86 })
87
88 const maxRank = Math.max(0, ...[...boxes.values()].map(b => b.rank))
89 const layers: Box[][] = Array.from({ length: maxRank + 1 }, () => [])
90 for (const b of boxes.values()) layers[b.rank]!.push(b)
91 layers.forEach(layer => layer.forEach((b, i) => (b.order = i)))
92 const neighbours = (id: string, up: boolean) =>
93 links.flatMap(([s, t]) => {
94 const S = boxes.get(s)!
95 const T = boxes.get(t)!
96 if (up) return T.id === id && S.rank < T.rank ? [S] : S.id === id && T.rank < S.rank ? [T] : []
97 return S.id === id && T.rank > S.rank ? [T] : T.id === id && S.rank > T.rank ? [S] : []
98 })
99 for (let sweep = 0; sweep < SWEEPS; sweep++) {
100 const down = sweep % 2 === 0
101 const order = down ? layers.slice(1) : layers.slice(0, -1).reverse()
102 for (const layer of order) {
103 const bary = new Map(layer.map(b => {
104 const n = neighbours(b.id, down)
105 return [b.id, n.length ? n.reduce((s, x) => s + x.order, 0) / n.length : b.order]
106 }))
107 layer.sort((a, b) => bary.get(a.id)! - bary.get(b.id)! || a.order - b.order)
108 layer.forEach((b, i) => (b.order = i))
109 }
110 }
111
112 const main = (b: Box) => (horizontal ? b.w : b.h)
113 const cross = (b: Box) => (horizontal ? b.h : b.w)
114 const rankSize = layers.map(layer => Math.max(0, ...layer.map(main)))
115 const rankStart: number[] = []
116 const labelRoom = layers.map((_, r) =>
117 Math.max(0, ...graph.edges.filter(e => e.label && Math.min(boxes.get(e.source)?.rank ?? -1, boxes.get(e.target)?.rank ?? -1) === r).map(e => {
118 const m = measureMultilineText(e.label!, FONT_SIZES.edgeLabel, FONT_WEIGHTS.edgeLabel)
119 return (horizontal ? m.width : m.height) + ELBOW + 36
120 })))
121 let at = 0
122 for (let r = 0; r <= maxRank; r++) {
123 rankStart.push(at)
124 at += rankSize[r]! + Math.max(RANK_GAP, labelRoom[r]!)
125 }
126 const extent = (layer: Box[]) => layer.reduce((s, b) => s + cross(b), 0) + NODE_GAP * Math.max(0, layer.length - 1)
127 const span = Math.max(...layers.map(extent))
128 for (const layer of layers) {
129 let c = (span - extent(layer)) / 2
130 for (const b of layer) {
131 const m = rankStart[b.rank]! + (rankSize[b.rank]! - main(b)) / 2
132 if (horizontal) {
133 b.x = m
134 b.y = c
135 } else {
136 b.x = c
137 b.y = m
138 }
139 c += cross(b) + NODE_GAP
140 }
141 }
142 if (reversed) {
143 const total = at - RANK_GAP
144 for (const b of boxes.values()) {
145 if (horizontal) b.x = total - b.x - b.w
146 else b.y = total - b.y - b.h
147 }
148 }
149
150 const center = (b: Box): Point => ({ x: b.x + b.w / 2, y: b.y + b.h / 2 })
151 const port = (b: Box, toward: Point): Point => {
152 const c = center(b)
153 if (b.virtual) return c
154 if (horizontal) return { x: toward.x >= c.x ? b.x + b.w : b.x, y: c.y }
155 return { x: c.x, y: toward.y >= c.y ? b.y + b.h : b.y }
156 }
157 const edges: PositionedEdge[] = graph.edges.flatMap((e, i) => {
158 const chain = chains.get(i)
159 if (!chain) return []
160 const src = boxes.get(e.source)!
161 const dst = boxes.get(e.target)!
162 if (src === dst) {
163 const c = center(src)
164 const r = horizontal ? { x: src.x + src.w / 2, y: src.y } : { x: src.x + src.w, y: c.y }
165 const loop = horizontal
166 ? [r, { x: r.x, y: r.y - 22 }, { x: r.x + src.w / 2 + 14, y: r.y - 22 }, { x: r.x + src.w / 2 + 14, y: c.y }, { x: src.x + src.w, y: c.y }]
167 : [r, { x: r.x + 22, y: r.y }, { x: r.x + 22, y: src.y - 14 }, { x: c.x, y: src.y - 14 }, { x: c.x, y: src.y }]
168 return [{ ...e, points: loop }]
169 }
170 const stops = chain.map(id => boxes.get(id)!)
171 const points: Point[] = []
172 for (let k = 0; k < stops.length - 1; k++) {
173 const a = stops[k]!
174 const b = stops[k + 1]!
175 const p = port(a, center(b))
176 const q = port(b, center(a))
177 if (k === 0) points.push(p)
178 const elbow = (from: number, to: number) => from + Math.sign(to - from) * Math.min(ELBOW, Math.abs(to - from) / 2)
179 if (horizontal) {
180 const mx = elbow(p.x, q.x)
181 if (Math.abs(p.y - q.y) > 0.5) points.push({ x: mx, y: p.y }, { x: mx, y: q.y })
182 } else {
183 const my = elbow(p.y, q.y)
184 if (Math.abs(p.x - q.x) > 0.5) points.push({ x: p.x, y: my }, { x: q.x, y: my })
185 }
186 points.push(q)
187 }
188 const a = points[points.length - 2] ?? points[0]!
189 const b = points[points.length - 1]!
190 return [{ ...e, points, labelPosition: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 } }]
191 })
192
193 const real = [...boxes.values()].filter(b => !b.virtual)
194 const groupOf = (sg: MermaidSubgraph): PositionedGroup | null => {
195 const children = sg.children.map(groupOf).filter((g): g is PositionedGroup => g !== null)
196 const members = real.filter(b => sg.nodeIds.includes(b.id))
197 const rects = [...members.map(b => ({ x: b.x, y: b.y, w: b.w, h: b.h })), ...children.map(g => ({ x: g.x, y: g.y, w: g.width, h: g.height }))]
198 if (!rects.length) return null
199 const x = Math.min(...rects.map(r => r.x)) - GROUP_PAD
200 const y = Math.min(...rects.map(r => r.y)) - GROUP_PAD - GROUP_HEADER
201 const right = Math.max(...rects.map(r => r.x + r.w)) + GROUP_PAD
202 const bottom = Math.max(...rects.map(r => r.y + r.h)) + GROUP_PAD
203 return { id: sg.id, label: sg.label, x, y, width: right - x, height: bottom - y, children }
204 }
205 const groups = graph.subgraphs.map(groupOf).filter((g): g is PositionedGroup => g !== null)
206
207 const xs: number[] = []
208 const ys: number[] = []
209 const take = (x: number, y: number) => {
210 xs.push(x)
211 ys.push(y)
212 }
213 for (const b of real) take(b.x, b.y), take(b.x + b.w, b.y + b.h)
214 for (const e of edges) for (const p of e.points) take(p.x, p.y)
215 const walk = (g: PositionedGroup) => {
216 take(g.x, g.y)
217 take(g.x + g.width, g.y + g.height)
218 g.children.forEach(walk)
219 }
220 groups.forEach(walk)
221 const dx = MARGIN - Math.min(...xs)
222 const dy = MARGIN - Math.min(...ys)
223 const move = (p: Point): Point => ({ x: p.x + dx, y: p.y + dy })
224 const shiftGroup = (g: PositionedGroup): PositionedGroup => ({ ...g, x: g.x + dx, y: g.y + dy, children: g.children.map(shiftGroup) })
225
226 const nodes: PositionedNode[] = real.map(b => {
227 const node = graph.nodes.get(b.id)!
228 const hue = `var(--cw-s${b.rank % WHEEL})`
229 return {
230 id: b.id, label: node.label, shape: node.shape, x: b.x + dx, y: b.y + dy, width: b.w, height: b.h,
231 inlineStyle: { stroke: hue, fill: `color-mix(in srgb, ${hue} 13%, var(--cw-bg))` },
232 }
233 })
234 return {
235 width: Math.ceil(Math.max(...xs) + dx + MARGIN),
236 height: Math.ceil(Math.max(...ys) + dy + MARGIN),
237 nodes,
238 edges: edges.map(e => ({ ...e, points: e.points.map(move), ...(e.labelPosition ? { labelPosition: move(e.labelPosition) } : {}) })),
239 groups: groups.map(shiftGroup),
240 }
241}
242hooks/vendor/mermaid.js 97 lines1var Sr=new Set(["i","l","t","f","j","I","1","!","|",".",",",":",";","'"]),Rr=new Set(["W","M","w","m","@","%"]),Dr=new Set(["W","M"]),kr=new Set(["(",")","[","]","{","}","/","\\","-",'"',"`"]);function Lr(t){return t>=768&&t<=879||t>=6832&&t<=6911||t>=7616&&t<=7679||t>=8400&&t<=8447||t>=65056&&t<=65071}function Tr(t){return t>=4352&&t<=4447||t>=11904&&t<=12031||t>=12032&&t<=12255||t>=12288&&t<=12351||t>=12352&&t<=12447||t>=12448&&t<=12543||t>=12544&&t<=12591||t>=12592&&t<=12687||t>=12688&&t<=12799||t>=12800&&t<=13311||t>=13312&&t<=19903||t>=19968&&t<=40959||t>=44032&&t<=55215||t>=63744&&t<=64255||t>=65280&&t<=65376||t>=65504&&t<=65510||t>=131072}var Ir=/\p{Emoji_Presentation}|\p{Extended_Pictographic}/u;function Er(t){return Ir.test(t)}function Yr(t){let e=t.codePointAt(0);return e===void 0||Lr(e)?0:Tr(e)||Er(t)?2:t===" "?.3:Dr.has(t)?1.5:Rr.has(t)?1.2:Sr.has(t)?.4:kr.has(t)?.5:t==="r"?.8:e>=65&&e<=90?1.2:(e>=48&&e<=57,1)}function ke(t,e,n){let o=n>=600?.6:n>=500?.57:.54,s=0;for(let i of t)s+=Yr(i);let r=e*.15;return s*e*o+r}var Le=1.3;function Te(t,e,n){let o=t.split(`
2`),s=e*Le,r=0;for(let i of o){let a=i.replace(/<\/?(?:b|strong|i|em|u|s|del)\s*>/gi,""),c=ke(a,e,n);c>r&&(r=c)}return{width:r,height:o.length*s,lines:o,lineHeight:s}}function mt(t){return(t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t).replace(/<br\s*\/?>/gi,`
3`).replace(/\\n/g,`
4`).replace(/<\/?(?:sub|sup|small|mark)\s*>/gi,"").replace(/\*\*(.+?)\*\*/g,"<b>$1</b>").replace(/(?<!\*)\*([^\s*](?:[^*]*[^\s*])?)\*(?!\*)/g,"<i>$1</i>").replace(/~~(.+?)~~/g,"<s>$1</s>")}function me(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}var Ke=/<(\/)?(?:(b|strong)|(i|em)|(u)|(s|del))\s*>/gi;function Pr(t){let e=[],n=!1,o=!1,s=!1,r=!1,i=0;Ke.lastIndex=0;let a;for(;(a=Ke.exec(t))!==null;){a.index>i&&e.push({text:t.slice(i,a.index),bold:n,italic:o,underline:s,strikethrough:r}),i=a.index+a[0].length;let c=!!a[1];a[2]?n=!c:a[3]?o=!c:a[4]?s=!c:a[5]&&(r=!c)}return i<t.length&&e.push({text:t.slice(i),bold:n,italic:o,underline:s,strikethrough:r}),e}var Xr=/<\/?(?:b|strong|i|em|u|s|del)\s*>/i;function Qe(t){if(!Xr.test(t))return me(t);let e=Pr(t);return e.length===0?"":e.every(o=>!o.bold&&!o.italic&&!o.underline&&!o.strikethrough)?e.map(o=>me(o.text)).join(""):e.map(o=>{let s=me(o.text);if(!o.bold&&!o.italic&&!o.underline&&!o.strikethrough)return s;let r=[];o.bold&&r.push('font-weight="bold"'),o.italic&&r.push('font-style="italic"');let i=[];return o.underline&&i.push("underline"),o.strikethrough&&i.push("line-through"),i.length&&r.push(`text-decoration="${i.join(" ")}"`),`<tspan ${r.join(" ")}>${s}</tspan>`}).join("")}function Gt(t,e,n,o,s,r=.35){let i=t.split(`
5`);if(i.length===1){let d=o*r;return`<text x="${e}" y="${n}" ${s} dy="${d}">${Qe(t)}</text>`}let a=o*Le,c=-((i.length-1)/2)*a+o*r,l=i.map((d,h)=>`<tspan x="${e}" dy="${h===0?c:a}">${Qe(d)}</tspan>`).join("");return`<text x="${e}" y="${n}" ${s}>${l}</text>`}function Ze(t,e,n,o,s,r,i,a,c){let l=o+i*2,d=s+i*2,h=`<rect x="${e-l/2}" y="${n-d/2}" width="${l}" height="${d}" ${c} />`,f=Gt(t,e,n,r,a);return`${h}
6${f}`}function Ie(t){let e=t.split(`
7`).map(o=>o.trim()).filter(o=>o.length>0&&!o.startsWith("%%"));if(e.length===0)throw new Error("Empty mermaid diagram");let n=e[0];return/^stateDiagram(-v2)?\s*$/i.test(n)?Gr(e):Hr(e)}function Hr(t){let e=t[0].match(/^(?:graph|flowchart)\s+(TD|TB|LR|BT|RL)\s*$/i);if(!e)throw new Error(`Invalid mermaid header: "${t[0]}". Expected "graph TD", "flowchart LR", "stateDiagram-v2", etc.`);let o={direction:e[1].toUpperCase(),nodes:new Map,edges:[],subgraphs:[],classDefs:new Map,classAssignments:new Map,nodeStyles:new Map,linkStyles:new Map},s=[];for(let r=1;r<t.length;r++){let i=t[r],a=i.match(/^classDef\s+(\w+)\s+(.+)$/);if(a){let u=a[1],g=a[2],p=pe(g);o.classDefs.set(u,p);continue}let c=i.match(/^class\s+([\w,-]+)\s+(\w+)$/);if(c){let u=c[1].split(",").map(p=>p.trim()),g=c[2];for(let p of u)o.classAssignments.set(p,g);continue}let l=i.match(/^style\s+([\w,-]+)\s+(.+)$/);if(l){let u=l[1].split(",").map(p=>p.trim()),g=pe(l[2]);for(let p of u)o.nodeStyles.set(p,{...o.nodeStyles.get(p),...g});continue}let d=i.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);if(d){let u=d[1].trim(),g=pe(d[2]);if(u==="default")o.linkStyles.set("default",{...o.linkStyles.get("default"),...g});else{let p=u.split(",").map($=>parseInt($.trim(),10));for(let $ of p)isNaN($)||o.linkStyles.set($,{...o.linkStyles.get($),...g})}continue}let h=i.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);if(h&&s.length>0){s[s.length-1].direction=h[1].toUpperCase();continue}let f=i.match(/^subgraph\s+(.+)$/);if(f){let u=f[1].trim(),g=u.match(/^([\w-]+)\s*\[(.+)\]$/),p,$;g?(p=g[1],$=mt(g[2])):($=mt(u),p=u.replace(/\s+/g,"_").replace(/[^\w]/g,""));let A={id:p,label:$,nodeIds:[],children:[]};s.push(A);continue}if(i==="end"){let u=s.pop();u&&(s.length>0?s[s.length-1].children.push(u):o.subgraphs.push(u));continue}Or(i,o,s)}return o}function Gr(t){let e={direction:"TD",nodes:new Map,edges:[],subgraphs:[],classDefs:new Map,classAssignments:new Map,nodeStyles:new Map,linkStyles:new Map},n=[],o=new Set,s=0,r=0;for(let i=1;i<t.length;i++){let a=t[i],c=a.match(/^direction\s+(TD|TB|LR|BT|RL)\s*$/i);if(c){n.length>0?n[n.length-1].direction=c[1].toUpperCase():e.direction=c[1].toUpperCase();continue}let l=a.match(/^linkStyle\s+(default|[\d,\s]+)\s+(.+)$/);if(l){let g=l[1].trim(),p=pe(l[2]);if(g==="default")e.linkStyles.set("default",{...e.linkStyles.get("default"),...p});else{let $=g.split(",").map(A=>parseInt(A.trim(),10));for(let A of $)isNaN(A)||e.linkStyles.set(A,{...e.linkStyles.get(A),...p})}continue}let d=a.match(/^state\s+(?:"([^"]+)"\s+as\s+)?([\w\p{L}]+)\s*\{$/u);if(d){let g=d[1]??d[2],p=d[2],$={id:p,label:g,nodeIds:[],children:[]};n.push($),o.add(p),e.nodes.delete(p);continue}if(a==="}"){let g=n.pop();g&&(n.length>0?n[n.length-1].children.push(g):e.subgraphs.push(g));continue}let h=a.match(/^state\s+"([^"]+)"\s+as\s+([\w\p{L}]+)\s*$/u);if(h){let g=mt(h[1]),p=h[2];de(e,n,{id:p,label:g,shape:"rounded"});continue}let f=a.match(/^(\[\*\]|[\w\p{L}-]+)\s*(-->)\s*(\[\*\]|[\w\p{L}-]+)(?:\s*:\s*(.+))?$/u);if(f){let g=f[1],p=f[3],$=f[4]?.trim(),A=$?mt($):void 0;g==="[*]"?(s++,g=`_start${s>1?s:""}`,de(e,n,{id:g,label:"",shape:"state-start"})):o.has(g)||tn(e,n,g),p==="[*]"?(r++,p=`_end${r>1?r:""}`,de(e,n,{id:p,label:"",shape:"state-end"})):o.has(p)||tn(e,n,p),e.edges.push({source:g,target:p,label:A,style:"solid",hasArrowStart:!1,hasArrowEnd:!0});continue}let u=a.match(/^([\w\p{L}-]+)\s*:\s*(.+)$/u);if(u){let g=u[1],p=mt(u[2].trim());de(e,n,{id:g,label:p,shape:"rounded"});continue}}return e}function de(t,e,n){if(!t.nodes.has(n.id)&&t.nodes.set(n.id,n),e.length>0){let s=e[e.length-1];s.nodeIds.includes(n.id)||s.nodeIds.push(n.id)}}function tn(t,e,n){if(!t.nodes.has(n))de(t,e,{id:n,label:n,shape:"rounded"});else if(e.length>0){let o=e[e.length-1];o.nodeIds.includes(n)||o.nodeIds.push(n)}}function pe(t){let e=t.replace(/;\s*$/,""),n={};for(let o of e.split(",")){let s=o.indexOf(":");if(s>0){let r=o.slice(0,s).trim(),i=o.slice(s+1).trim();r&&i&&(n[r]=i)}}return n}var Wr=/^(<)?(-->|-.->|==>|---|-\.-|===)(?:\|([^|]*)\|)?/,Nr=/^(<)?(--|-\.|==)\s+(.+?)\s+(-->|---|\.\->|-\.\-|==>|===)/,Br=[{regex:/^([\w-]+)\(\(\((.+?)\)\)\)/,shape:"doublecircle"},{regex:/^([\w-]+)\(\[(.+?)\]\)/,shape:"stadium"},{regex:/^([\w-]+)\(\((.+?)\)\)/,shape:"circle"},{regex:/^([\w-]+)\[\[(.+?)\]\]/,shape:"subroutine"},{regex:/^([\w-]+)\[\((.+?)\)\]/,shape:"cylinder"},{regex:/^([\w-]+)\[\/(.+?)\\\]/,shape:"trapezoid"},{regex:/^([\w-]+)\[\\(.+?)\/\]/,shape:"trapezoid-alt"},{regex:/^([\w-]+)>(.+?)\]/,shape:"asymmetric"},{regex:/^([\w-]+)\{\{(.+?)\}\}/,shape:"hexagon"},{regex:/^([\w-]+)\[(.+?)\]/,shape:"rectangle"},{regex:/^([\w-]+)\((.+?)\)/,shape:"rounded"},{regex:/^([\w-]+)\{(.+?)\}/,shape:"diamond"}],_r=/^([\w-]+)/,zr=/^:::([\w][\w-]*)/;function Or(t,e,n){let o=t.trim(),s=en(o,e,n);if(!s||s.ids.length===0)return;o=s.remaining.trim();let r=s.ids;for(;o.length>0;){let i,a,c,l,d=o.match(Wr);if(d){i=!!d[1];let f=d[2],u=d[3]?.trim();l=u?mt(u):void 0,o=o.slice(d[0].length).trim(),a=Fr(f),c=f.endsWith(">")}else{let f=o.match(Nr);if(!f)break;i=!!f[1];let u=f[3].trim();l=u?mt(u):void 0;let g=f[2],p=f[4];o=o.slice(f[0].length).trim(),a=qr(g,p),c=p.endsWith(">")}let h=en(o,e,n);if(!h||h.ids.length===0)break;o=h.remaining.trim();for(let f of r)for(let u of h.ids)e.edges.push({source:f,target:u,label:l,style:a,hasArrowStart:i,hasArrowEnd:c});r=h.ids}}function en(t,e,n){let o=nn(t,e,n);if(!o)return null;let s=[o.id],r=o.remaining.trim();for(;r.startsWith("&");){r=r.slice(1).trim();let i=nn(r,e,n);if(!i)break;s.push(i.id),r=i.remaining.trim()}return{ids:s,remaining:r}}function nn(t,e,n){let o=null,s=t;for(let{regex:i,shape:a}of Br){let c=t.match(i);if(c){o=c[1];let l=mt(c[2]);rn(e,n,{id:o,label:l,shape:a}),s=t.slice(c[0].length);break}}if(o===null){let i=t.match(_r);i&&(o=i[1],e.nodes.has(o)||rn(e,n,{id:o,label:o,shape:"rectangle"}),s=t.slice(i[0].length))}if(o===null)return null;let r=s.match(zr);return r&&(e.classAssignments.set(o,r[1]),s=s.slice(r[0].length)),{id:o,remaining:s}}function rn(t,e,n){!t.nodes.has(n.id)&&t.nodes.set(n.id,n),jr(e,n.id)}function jr(t,e){if(t.length>0){let n=t[t.length-1];n.nodeIds.includes(e)||n.nodeIds.push(e)}}function Fr(t){return t==="-.->"||t==="-.-"?"dotted":t==="==>"||t==="==="?"thick":"solid"}function qr(t,e){return t==="-."||e===".->"||e==="-.-"?"dotted":t==="=="||e==="==>"||e==="==="?"thick":"solid"}var Wt={text:100,textSec:60,textMuted:40,textFaint:25,line:50,arrow:85,nodeFill:3,nodeStroke:20,groupHeader:5,innerStroke:12,keyBadge:10};function ie(t,e){let n=[`@import url('https://fonts.googleapis.com/css2?family=${encodeURIComponent(t)}:wght@400;500;600;700&display=swap');`,...e?["@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap');"]:[]],o=`
8 /* Derived from --bg and --fg (overridable via --line, --accent, etc.) */
9 --_text: var(--fg);
10 --_text-sec: var(--muted, color-mix(in srgb, var(--fg) ${Wt.textSec}%, var(--bg)));
11 --_text-muted: var(--muted, color-mix(in srgb, var(--fg) ${Wt.textMuted}%, var(--bg)));
12 --_text-faint: color-mix(in srgb, var(--fg) ${Wt.textFaint}%, var(--bg));
13 --_line: var(--line, color-mix(in srgb, var(--fg) ${Wt.line}%, var(--bg)));
14 --_arrow: var(--accent, color-mix(in srgb, var(--fg) ${Wt.arrow}%, var(--bg)));
15 --_node-fill: var(--surface, color-mix(in srgb, var(--fg) ${Wt.nodeFill}%, var(--bg)));
16 --_node-stroke: var(--border, color-mix(in srgb, var(--fg) ${Wt.nodeStroke}%, var(--bg)));
17 --_group-fill: var(--bg);
18 --_group-hdr: color-mix(in srgb, var(--fg) ${Wt.groupHeader}%, var(--bg));
19 --_inner-stroke: color-mix(in srgb, var(--fg) ${Wt.innerStroke}%, var(--bg));
20 --_key-badge: color-mix(in srgb, var(--fg) ${Wt.keyBadge}%, var(--bg));`;return["<style>",` ${n.join(`
21 `)}`,` text { font-family: '${t}', system-ui, sans-serif; }`,...e?[" .mono { font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', ui-monospace, monospace; }"]:[],` svg {${o}`," }","</style>"].join(`
22`)}function se(t,e,n,o){let s=[`--bg:${n.bg}`,`--fg:${n.fg}`,n.line?`--line:${n.line}`:"",n.accent?`--accent:${n.accent}`:"",n.muted?`--muted:${n.muted}`:"",n.surface?`--surface:${n.surface}`:"",n.border?`--border:${n.border}`:""].filter(Boolean).join(";");return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${t} ${e}" width="${t}" height="${e}" style="${s}${o?"":";background:var(--bg)"}">`}function wt(t,e,n){return ke(t,e,n)}var Ur="'JetBrains Mono'",ds=`${Ur}, 'SF Mono', 'Fira Code', ui-monospace, monospace`,ct={nodeLabel:13,edgeLabel:11,groupHeader:12},bt={nodeLabel:500,edgeLabel:400,groupHeader:600};var Jr={horizontal:20,vertical:10,diamondExtra:24},Mt={outerBox:1,innerBox:.75,connector:1},Nt="0.35em",Zt={width:8,height:5};function Vr(t,e,n="Inter",o=!1){let s=[];s.push(se(t.width,t.height,e,o)),s.push(ie(n,!1)),s.push("<defs>"),s.push(Kr());let r=new Set;for(let i of t.edges)i.inlineStyle?.stroke&&r.add(i.inlineStyle.stroke);for(let i of r)s.push(Qr(i));s.push("</defs>");for(let i of t.groups)s.push(an(i,n));for(let i of t.edges)s.push(Zr(i));for(let i of t.edges)i.label&&s.push(eo(i,n));for(let i of t.nodes)s.push(ro(i,n));return s.push("</svg>"),s.join(`
23`)}function Kr(){let t=Zt.width,e=Zt.height,n='fill="var(--_arrow)" stroke="var(--_arrow)" stroke-width="0.75" stroke-linejoin="round"',o=t-1;return` <marker id="arrowhead" markerWidth="${t}" markerHeight="${e}" refX="${o}" refY="${e/2}" orient="auto">
24 <polygon points="0 0, ${t} ${e/2}, 0 ${e}" ${n} />
25 </marker>
26 <marker id="arrowhead-start" markerWidth="${t}" markerHeight="${e}" refX="1" refY="${e/2}" orient="auto-start-reverse">
27 <polygon points="${t} 0, 0 ${e/2}, ${t} ${e}" ${n} />
28 </marker>`}function Qr(t){let e=Zt.width,n=Zt.height,o=At(t),s=`fill="${o}" stroke="${o}" stroke-width="0.75" stroke-linejoin="round"`,r=e-1,i=sn(t);return` <marker id="arrowhead-${i}" markerWidth="${e}" markerHeight="${n}" refX="${r}" refY="${n/2}" orient="auto">
29 <polygon points="0 0, ${e} ${n/2}, 0 ${n}" ${s} />
30 </marker>
31 <marker id="arrowhead-start-${i}" markerWidth="${e}" markerHeight="${n}" refX="1" refY="${n/2}" orient="auto-start-reverse">
32 <polygon points="${e} 0, 0 ${n/2}, ${e} ${n}" ${s} />
33 </marker>`}function sn(t){return t.replace(/[^a-zA-Z0-9]/g,e=>e.charCodeAt(0).toString(16))}function an(t,e){let n=ct.groupHeader+16,o=[];o.push(`<g class="subgraph" data-id="${At(t.id)}" data-label="${At(t.label)}">`),o.push(` <rect x="${t.x}" y="${t.y}" width="${t.width}" height="${t.height}" rx="0" ry="0" fill="var(--_group-fill)" stroke="var(--_node-stroke)" stroke-width="${Mt.outerBox}" />`),o.push(` <rect x="${t.x}" y="${t.y}" width="${t.width}" height="${n}" rx="0" ry="0" fill="var(--_group-hdr)" stroke="var(--_node-stroke)" stroke-width="${Mt.outerBox}" />`),o.push(" "+Gt(t.label,t.x+12,t.y+n/2,ct.groupHeader,`font-size="${ct.groupHeader}" font-weight="${bt.groupHeader}" fill="var(--_text-sec)"`));for(let s of t.children)o.push(an(s,e));return o.push("</g>"),o.join(`
34`)}function Zr(t){if(t.points.length<2)return"";let e=to(t.points),n=t.style==="dotted"?' stroke-dasharray="4 4"':"",o=t.style==="thick"?Mt.connector*2:Mt.connector,s=At(t.inlineStyle?.stroke??"var(--_line)"),r=At(t.inlineStyle?.["stroke-width"]??String(o)),i=t.inlineStyle?.stroke?`-${sn(t.inlineStyle.stroke)}`:"",a="";t.hasArrowEnd&&(a+=` marker-end="url(#arrowhead${i})"`),t.hasArrowStart&&(a+=` marker-start="url(#arrowhead-start${i})"`);let c=['class="edge"',`data-from="${At(t.source)}"`,`data-to="${At(t.target)}"`,`data-style="${t.style}"`,`data-arrow-start="${t.hasArrowStart}"`,`data-arrow-end="${t.hasArrowEnd}"`];return t.label&&c.push(`data-label="${At(t.label)}"`),`<polyline ${c.join(" ")} points="${e}" fill="none" stroke="${s}" stroke-width="${r}"${n}${a} />`}function to(t){return t.map(e=>`${e.x},${e.y}`).join(" ")}function eo(t,e){let n=t.labelPosition??no(t.points),o=t.label,s=8,r=Te(o,ct.edgeLabel,bt.edgeLabel),i=Ze(o,n.x,n.y,r.width,r.height,ct.edgeLabel,s,`text-anchor="middle" font-size="${ct.edgeLabel}" font-weight="${bt.edgeLabel}" fill="var(--_text-sec)"`,'rx="2" ry="2" fill="var(--bg)" stroke="var(--_inner-stroke)" stroke-width="1"');return`<g class="edge-label" data-from="${At(t.source)}" data-to="${At(t.target)}" data-label="${At(o)}">
35 ${i.replace(/\n/g,`
36 `)}
37</g>`}function no(t){if(t.length===0)return{x:0,y:0};if(t.length===1)return t[0];let e=0;for(let o=1;o<t.length;o++)e+=on(t[o-1],t[o]);let n=e/2;for(let o=1;o<t.length;o++){let s=on(t[o-1],t[o]);if(n<=s){let r=n/s;return{x:t[o-1].x+r*(t[o].x-t[o-1].x),y:t[o-1].y+r*(t[o].y-t[o-1].y)}}n-=s}return t[t.length-1]}function on(t,e){return Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2)}function ro(t,e){let n=oo(t),o=$o(t,e),s=[];return s.push(`<g class="node" data-id="${At(t.id)}" data-label="${At(t.label)}" data-shape="${t.shape}">`),s.push(` ${n.replace(/\n/g,`
38 `)}`),o&&s.push(` ${o.replace(/\n/g,`
39 `)}`),s.push("</g>"),s.join(`
40`)}function oo(t){let{x:e,y:n,width:o,height:s,shape:r,inlineStyle:i}=t,a=At(i?.fill??"var(--_node-fill)"),c=At(i?.stroke??"var(--_node-stroke)"),l=At(i?.["stroke-width"]??String(Mt.innerBox));switch(r){case"diamond":return lo(e,n,o,s,a,c,l);case"rounded":return so(e,n,o,s,a,c,l);case"stadium":return ao(e,n,o,s,a,c,l);case"circle":return co(e,n,o,s,a,c,l);case"subroutine":return fo(e,n,o,s,a,c,l);case"doublecircle":return uo(e,n,o,s,a,c,l);case"hexagon":return ho(e,n,o,s,a,c,l);case"cylinder":return go(e,n,o,s,a,c,l);case"asymmetric":return mo(e,n,o,s,a,c,l);case"trapezoid":return po(e,n,o,s,a,c,l);case"trapezoid-alt":return xo(e,n,o,s,a,c,l);case"state-start":return bo(e,n,o,s);case"state-end":return yo(e,n,o,s);default:return io(e,n,o,s,a,c,l)}}function io(t,e,n,o,s,r,i){return`<rect x="${t}" y="${e}" width="${n}" height="${o}" rx="0" ry="0" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function so(t,e,n,o,s,r,i){return`<rect x="${t}" y="${e}" width="${n}" height="${o}" rx="6" ry="6" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function ao(t,e,n,o,s,r,i){let a=o/2;return`<rect x="${t}" y="${e}" width="${n}" height="${o}" rx="${a}" ry="${a}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function co(t,e,n,o,s,r,i){let a=t+n/2,c=e+o/2,l=Math.min(n,o)/2;return`<circle cx="${a}" cy="${c}" r="${l}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function lo(t,e,n,o,s,r,i){let a=t+n/2,c=e+o/2,l=n/2,d=o/2;return`<polygon points="${[`${a},${c-d}`,`${a+l},${c}`,`${a},${c+d}`,`${a-l},${c}`].join(" ")}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function fo(t,e,n,o,s,r,i){return`<rect x="${t}" y="${e}" width="${n}" height="${o}" rx="0" ry="0" fill="${s}" stroke="${r}" stroke-width="${i}" />
41<line x1="${t+8}" y1="${e}" x2="${t+8}" y2="${e+o}" stroke="${r}" stroke-width="${i}" />
42<line x1="${t+n-8}" y1="${e}" x2="${t+n-8}" y2="${e+o}" stroke="${r}" stroke-width="${i}" />`}function uo(t,e,n,o,s,r,i){let a=t+n/2,c=e+o/2,l=Math.min(n,o)/2,d=l-5;return`<circle cx="${a}" cy="${c}" r="${l}" fill="${s}" stroke="${r}" stroke-width="${i}" />
43<circle cx="${a}" cy="${c}" r="${d}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function ho(t,e,n,o,s,r,i){let a=o/4;return`<polygon points="${[`${t+a},${e}`,`${t+n-a},${e}`,`${t+n},${e+o/2}`,`${t+n-a},${e+o}`,`${t+a},${e+o}`,`${t},${e+o/2}`].join(" ")}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function go(t,e,n,o,s,r,i){let c=t+n/2,l=e+7,d=o-14;return`<rect x="${t}" y="${l}" width="${n}" height="${d}" fill="${s}" stroke="none" />
44<line x1="${t}" y1="${l}" x2="${t}" y2="${l+d}" stroke="${r}" stroke-width="${i}" />
45<line x1="${t+n}" y1="${l}" x2="${t+n}" y2="${l+d}" stroke="${r}" stroke-width="${i}" />
46<ellipse cx="${c}" cy="${e+o-7}" rx="${n/2}" ry="7" fill="${s}" stroke="${r}" stroke-width="${i}" />
47<ellipse cx="${c}" cy="${l}" rx="${n/2}" ry="7" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function mo(t,e,n,o,s,r,i){return`<polygon points="${[`${t+12},${e}`,`${t+n},${e}`,`${t+n},${e+o}`,`${t+12},${e+o}`,`${t},${e+o/2}`].join(" ")}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function po(t,e,n,o,s,r,i){let a=n*.15;return`<polygon points="${[`${t+a},${e}`,`${t+n-a},${e}`,`${t+n},${e+o}`,`${t},${e+o}`].join(" ")}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function xo(t,e,n,o,s,r,i){let a=n*.15;return`<polygon points="${[`${t},${e}`,`${t+n},${e}`,`${t+n-a},${e+o}`,`${t+a},${e+o}`].join(" ")}" fill="${s}" stroke="${r}" stroke-width="${i}" />`}function bo(t,e,n,o){let s=t+n/2,r=e+o/2,i=Math.min(n,o)/2-2;return`<circle cx="${s}" cy="${r}" r="${i}" fill="var(--_text)" stroke="none" />`}function yo(t,e,n,o){let s=t+n/2,r=e+o/2,i=Math.min(n,o)/2-2,a=i-4;return`<circle cx="${s}" cy="${r}" r="${i}" fill="none" stroke="var(--_text)" stroke-width="${Mt.innerBox*2}" />
48<circle cx="${s}" cy="${r}" r="${a}" fill="var(--_text)" stroke="none" />`}function $o(t,e){if((t.shape==="state-start"||t.shape==="state-end")&&!t.label)return"";let n=t.x+t.width/2,o=t.y+t.height/2,s=At(t.inlineStyle?.color??"var(--_text)");return Gt(t.label,n,o,ct.nodeLabel,`text-anchor="middle" font-size="${ct.nodeLabel}" font-weight="${bt.nodeLabel}" fill="${s}"`)}function At(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function Ee(t){let e={actors:[],messages:[],blocks:[],notes:[]},n=new Set,o=[];for(let s=1;s<t.length;s++){let r=t[s],i=r.match(/^(participant|actor)\s+(\S+?)(?:\s+as\s+(.+))?$/);if(i){let f=i[1],u=i[2],g=i[3]?.trim()??u,p=mt(g);n.has(u)||(n.add(u),e.actors.push({id:u,label:p,type:f}));continue}let a=r.match(/^Note\s+(left of|right of|over)\s+([^:]+):\s*(.+)$/i);if(a){let f=a[1].toLowerCase(),u=a[2].trim(),g=mt(a[3].trim()),p=u.split(",").map(A=>A.trim());for(let A of p)fe(e,n,A);let $="over";f==="left of"?$="left":f==="right of"&&($="right"),e.notes.push({actorIds:p,text:g,position:$,afterIndex:e.messages.length-1});continue}let c=r.match(/^(loop|alt|opt|par|critical|break|rect)\s*(.*)$/);if(c){let f=c[1],u=c[2]?.trim()??"",g=mt(u);o.push({type:f,label:g,startIndex:e.messages.length,dividers:[]});continue}let l=r.match(/^(else|and)\s*(.*)$/);if(l&&o.length>0){let f=l[2]?.trim()??"",u=mt(f);o[o.length-1].dividers.push({index:e.messages.length,label:u});continue}if(r==="end"&&o.length>0){let f=o.pop();e.blocks.push({type:f.type,label:f.label,startIndex:f.startIndex,endIndex:Math.max(e.messages.length-1,f.startIndex),dividers:f.dividers});continue}let d=r.match(/^(\S+?)\s*(--?>?>|--?[)x]|--?>>|--?>)\s*([+-]?)(\S+?)\s*:\s*(.+)$/);if(d){let f=d[1],u=d[2],g=d[3],p=d[4],$=mt(d[5].trim());fe(e,n,f),fe(e,n,p);let A=u.startsWith("--")?"dashed":"solid",X=u.includes(">>")||u.includes("x")?"filled":"open",v={from:f,to:p,label:$,lineStyle:A,arrowHead:X};g==="+"&&(v.activate=!0),g==="-"&&(v.deactivate=!0),e.messages.push(v);continue}let h=r.match(/^(\S+?)\s*(->>|-->>|-\)|--\)|-x|--x|->|-->)\s*([+-]?)(\S+?)\s*:\s*(.+)$/);if(h){let f=h[1],u=h[2],g=h[3],p=h[4],$=mt(h[5].trim());fe(e,n,f),fe(e,n,p);let A=u.startsWith("--")?"dashed":"solid",X=u.includes(">>")||u.includes("x")?"filled":"open",v={from:f,to:p,label:$,lineStyle:A,arrowHead:X};g==="+"&&(v.activate=!0),g==="-"&&(v.deactivate=!0),e.messages.push(v);continue}}return e}function fe(t,e,n){e.has(n)||(e.add(n),t.actors.push({id:n,label:n,type:"participant"}))}var at={padding:30,actorGap:140,actorHeight:40,actorPadX:16,headerGap:20,messageRowHeight:40,selfMessageHeight:30,activationWidth:10,blockPadX:10,blockPadTop:40,blockPadBottom:8,blockHeaderExtra:28,dividerExtra:24,noteWidth:60,notePadX:12,notePadY:6,noteGap:10};function Co(t,e={}){if(t.actors.length===0)return{width:0,height:0,actors:[],lifelines:[],messages:[],activations:[],blocks:[],notes:[]};let n=t.actors.map(m=>{let M=wt(m.label,ct.nodeLabel,bt.nodeLabel);return Math.max(M+at.actorPadX*2,80)}),o=[],s=at.padding+n[0]/2;for(let m=0;m<t.actors.length;m++){if(m>0){let M=Math.max(at.actorGap,(n[m-1]+n[m])/2+40);s+=M}o.push(s)}let r=new Map;for(let m=0;m<t.actors.length;m++)r.set(t.actors[m].id,m);let i=at.padding,a=t.actors.map((m,M)=>({id:m.id,label:m.label,type:m.type,x:o[M],y:i,width:n[M],height:at.actorHeight})),c=i+at.actorHeight+at.headerGap,l=[],d=new Map;for(let m of t.blocks){let M=d.get(m.startIndex)??0;d.set(m.startIndex,Math.max(M,at.blockHeaderExtra));for(let H of m.dividers){let C=d.get(H.index)??0;d.set(H.index,Math.max(C,at.dividerExtra))}}let h=new Map;for(let m of t.notes){let M=h.get(m.afterIndex)??[];M.push(m),h.set(m.afterIndex,M)}let f=[],u=new Map,g=[],p=4;for(let m=0;m<t.messages.length;m++){let M=t.messages[m],H=r.get(M.from)??0,C=r.get(M.to)??0,z=M.from===M.to,P=d.get(m)??0;P>0&&(c+=P);let U=o[H],T=o[C];if(l.push({from:M.from,to:M.to,label:M.label,lineStyle:M.lineStyle,arrowHead:M.arrowHead,x1:U,x2:T,y:c,isSelf:z}),M.activate){u.has(M.to)||u.set(M.to,[]);let it=u.get(M.to),et=it.length;it.push({startY:c,depth:et})}if(M.deactivate){let it=u.get(M.from);if(it&&it.length>0){let{startY:et,depth:w}=it.pop(),G=r.get(M.from)??0,N=w*p;g.push({actorId:M.from,x:o[G]-at.activationWidth/2+N,topY:et,bottomY:c,width:at.activationWidth})}}c+=z?at.selfMessageHeight+at.messageRowHeight:at.messageRowHeight;let K=h.get(m);if(K&&K.length>0){let it=z?at.selfMessageHeight:0,et=l[m].y+it+8;for(let w of K){let G=Math.max(at.noteWidth,wt(w.text,ct.edgeLabel,bt.edgeLabel)+at.notePadX*2),N=ct.edgeLabel+at.notePadY*2,x=r.get(w.actorIds[0]??"")??0,B;if(w.position==="left")B=o[x]-n[x]/2-G-at.noteGap;else if(w.position==="right")B=o[x]+n[x]/2+at.noteGap;else if(w.actorIds.length>1){let rt=r.get(w.actorIds[w.actorIds.length-1]??"")??x;B=(o[x]+o[rt])/2-G/2}else B=o[x]-G/2;f.push({text:w.text,x:B,y:et,width:G,height:N,position:w.position,actors:w.actorIds}),et+=N+4}c=Math.max(c,et+at.messageRowHeight/2)}}for(let[m,M]of u)for(let{startY:H,depth:C}of M){let z=r.get(m)??0,P=C*p;g.push({actorId:m,x:o[z]-at.activationWidth/2+P,topY:H,bottomY:c-at.messageRowHeight/2,width:at.activationWidth})}let $=t.blocks.map(m=>{let M=l[m.startIndex],H=l[m.endIndex],C=(M?.y??c)-at.blockPadTop,z=(H?.y??c)+at.blockPadBottom+12,P=new Set;for(let w=m.startIndex;w<=m.endIndex;w++){let G=t.messages[w];G&&(P.add(r.get(G.from)??0),P.add(r.get(G.to)??0))}if(P.size===0)for(let w=0;w<t.actors.length;w++)P.add(w);let U=Math.min(...P),T=Math.max(...P),K=o[U]-n[U]/2-at.blockPadX,it=o[T]+n[T]/2+at.blockPadX,et=m.dividers.map(w=>{let G=l[w.index],N=G?.y??c,x=28;if(w.label&&G?.label){let B=`[${w.label}]`,rt=wt(B,ct.edgeLabel,bt.edgeLabel),y=K+8,R=y+rt,W=wt(G.label,ct.edgeLabel,bt.edgeLabel),E=G.isSelf?G.x1+36:(G.x1+G.x2)/2-W/2,_=E+W;R>E&&y<_&&(x=36)}return{y:N-x,label:w.label}});return{type:m.type,label:m.label,x:K,y:C,width:it-K,height:z-C,dividers:et}}),A=f,X=c+at.padding,v=at.padding,Y=0;for(let m of a)v=Math.min(v,m.x-m.width/2),Y=Math.max(Y,m.x+m.width/2);for(let m of $)v=Math.min(v,m.x),Y=Math.max(Y,m.x+m.width);for(let m of A)v=Math.min(v,m.x),Y=Math.max(Y,m.x+m.width);for(let m of l)if(m.isSelf&&m.label){let C=m.x1+30+8,z=wt(m.label,ct.edgeLabel,bt.edgeLabel);Y=Math.max(Y,C+z+8)}let D=v<at.padding?at.padding-v:0;if(D>0){for(let m of a)m.x+=D;for(let m of l)m.x1+=D,m.x2+=D;for(let m of g)m.x+=D;for(let m of $)m.x+=D;for(let m of A)m.x+=D;for(let m=0;m<o.length;m++)o[m]+=D}let V=t.actors.map((m,M)=>({actorId:m.id,x:o[M],topY:i+at.actorHeight,bottomY:X-at.padding})),ft=Y+D+at.padding,j=X;return{width:Math.max(ft,200),height:Math.max(j,100),actors:a,lifelines:V,messages:l,activations:g,blocks:$,notes:A}}function wo(t,e,n="Inter",o=!1){let s=[];s.push(se(t.width,t.height,e,o)),s.push(ie(n,!1)),s.push("<defs>"),s.push(Mo()),s.push("</defs>");for(let r of t.blocks)s.push(Do(r));for(let r of t.lifelines)s.push(vo(r));for(let r of t.activations)s.push(So(r));for(let r of t.messages)s.push(Ro(r));for(let r of t.notes)s.push(ko(r));for(let r of t.actors)s.push(Ao(r));return s.push("</svg>"),s.join(`
49`)}function Mo(){let t=Zt.width,e=Zt.height;return` <marker id="seq-arrow" markerWidth="${t}" markerHeight="${e}" refX="${t}" refY="${e/2}" orient="auto-start-reverse">
50 <polygon points="0 0, ${t} ${e/2}, 0 ${e}" fill="var(--_arrow)" />
51 </marker>
52 <marker id="seq-arrow-open" markerWidth="${t}" markerHeight="${e}" refX="${t}" refY="${e/2}" orient="auto-start-reverse">
53 <polyline points="0 0, ${t} ${e/2}, 0 ${e}" fill="none" stroke="var(--_arrow)" stroke-width="1" />
54 </marker>`}function Ao(t){let{id:e,x:n,y:o,width:s,height:r,label:i,type:a}=t,c=[];if(c.push(`<g class="actor" data-id="${Bt(e)}" data-label="${Bt(i)}" data-type="${a}">`),a==="actor"){let l=r/24*.9,d=n-12*l,h=o+(r-24*l)/2,f=Mt.outerBox/l,u="var(--_line)";c.push(` <g transform="translate(${d},${h}) scale(${l})">
55 <path d="M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" fill="none" stroke="${u}" stroke-width="${f}" />
56 <path d="M15 10C15 11.6569 13.6569 13 12 13C10.3431 13 9 11.6569 9 10C9 8.34315 10.3431 7 12 7C13.6569 7 15 8.34315 15 10Z" fill="none" stroke="${u}" stroke-width="${f}" />
57 <path d="M5.62842 18.3563C7.08963 17.0398 9.39997 16 12 16C14.6 16 16.9104 17.0398 18.3716 18.3563" fill="none" stroke="${u}" stroke-width="${f}" />
58 </g>`),c.push(" "+Gt(i,n,o+r+14,ct.nodeLabel,`font-size="${ct.nodeLabel}" text-anchor="middle" font-weight="${bt.nodeLabel}" fill="var(--_text)"`))}else{let l=n-s/2;c.push(` <rect x="${l}" y="${o}" width="${s}" height="${r}" rx="4" ry="4" fill="var(--_node-fill)" stroke="var(--_node-stroke)" stroke-width="${Mt.outerBox}" />`),c.push(" "+Gt(i,n,o+r/2,ct.nodeLabel,`font-size="${ct.nodeLabel}" text-anchor="middle" font-weight="${bt.nodeLabel}" fill="var(--_text)"`))}return c.push("</g>"),c.join(`
59`)}function vo(t){return`<line class="lifeline" data-actor="${Bt(t.actorId)}" x1="${t.x}" y1="${t.topY}" x2="${t.x}" y2="${t.bottomY}" stroke="var(--_line)" stroke-width="0.75" stroke-dasharray="6 4" />`}function So(t){return`<rect class="activation" data-actor="${Bt(t.actorId)}" x="${t.x}" y="${t.topY}" width="${t.width}" height="${t.bottomY-t.topY}" fill="var(--_node-fill)" stroke="var(--_node-stroke)" stroke-width="${Mt.innerBox}" />`}function Ro(t){let e=[],n=t.lineStyle==="dashed"?' stroke-dasharray="6 4"':"",o=t.arrowHead==="filled"?"seq-arrow":"seq-arrow-open";if(e.push(`<g class="message" data-from="${Bt(t.from)}" data-to="${Bt(t.to)}" data-label="${Bt(t.label)}" data-line-style="${t.lineStyle}" data-arrow-head="${t.arrowHead}" data-self="${t.isSelf}">`),t.isSelf)e.push(` <polyline points="${t.x1},${t.y} ${t.x1+30},${t.y} ${t.x1+30},${t.y+20} ${t.x2},${t.y+20}" fill="none" stroke="var(--_line)" stroke-width="${Mt.connector}"${n} marker-end="url(#${o})" />`),e.push(" "+Gt(t.label,t.x1+30+8,t.y+20/2,ct.edgeLabel,`font-size="${ct.edgeLabel}" text-anchor="start" font-weight="${bt.edgeLabel}" fill="var(--_text-muted)"`));else{e.push(` <line x1="${t.x1}" y1="${t.y}" x2="${t.x2}" y2="${t.y}" stroke="var(--_line)" stroke-width="${Mt.connector}"${n} marker-end="url(#${o})" />`);let s=(t.x1+t.x2)/2;e.push(" "+Gt(t.label,s,t.y-10,ct.edgeLabel,`font-size="${ct.edgeLabel}" text-anchor="middle" font-weight="${bt.edgeLabel}" fill="var(--_text-muted)"`))}return e.push("</g>"),e.join(`
60`)}function Do(t){let e=[],n=t.label?` data-label="${Bt(t.label)}"`:"";e.push(`<g class="block" data-type="${Bt(t.type)}"${n}>`),e.push(` <rect x="${t.x}" y="${t.y}" width="${t.width}" height="${t.height}" rx="0" ry="0" fill="none" stroke="var(--_node-stroke)" stroke-width="${Mt.outerBox}" />`);let o=`${t.type}${t.label?` [${t.label}]`:""}`,s=o.split(`
61`)[0],r=wt(s,ct.edgeLabel,bt.groupHeader)+16,i=18;e.push(` <rect x="${t.x}" y="${t.y}" width="${r}" height="${i}" fill="var(--_group-hdr)" stroke="var(--_node-stroke)" stroke-width="${Mt.outerBox}" />`),e.push(" "+Gt(o,t.x+6,t.y+i/2,ct.edgeLabel,`font-size="${ct.edgeLabel}" font-weight="${bt.groupHeader}" fill="var(--_text-sec)"`));for(let a of t.dividers)e.push(` <line x1="${t.x}" y1="${a.y}" x2="${t.x+t.width}" y2="${a.y}" stroke="var(--_line)" stroke-width="0.75" stroke-dasharray="6 4" />`),a.label&&e.push(" "+Gt(`[${a.label}]`,t.x+8,a.y+14,ct.edgeLabel,`font-size="${ct.edgeLabel}" text-anchor="start" font-weight="${bt.edgeLabel}" fill="var(--_text-muted)"`));return e.push("</g>"),e.join(`
62`)}function ko(t){let{x:n,y:o,width:s,height:r}=t,i=t.actors&&t.actors.length>0?` data-actors="${t.actors.map(Bt).join(",")}"`:"",a=t.position?` data-position="${Bt(t.position)}"`:"",c=[`${n},${o}`,`${n+s-6},${o}`,`${n+s},${o+6}`,`${n+s},${o+r}`,`${n},${o+r}`].join(" ");return`<g class="note"${a}${i}>
63 <polygon points="${c}" fill="var(--bg)" stroke="var(--_node-stroke)" stroke-width="${Mt.innerBox}" />
64 <polygon points="${n+s-6},${o} ${n+s},${o+6} ${n+s-6},${o+6}" fill="var(--_inner-stroke)" stroke="var(--_node-stroke)" stroke-width="${Mt.innerBox}" />
65 ${Gt(t.text,n+s/2,o+r/2,ct.edgeLabel,`font-size="${ct.edgeLabel}" text-anchor="middle" font-weight="${bt.edgeLabel}" fill="var(--_text-muted)"`)}
66</g>`}function Bt(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function Ye(t){let e={},n={},o=[],s,r=!1;for(let i of t){if(/^xychart(-beta)?\b/i.test(i)){/\bhorizontal\b/i.test(i)&&(r=!0);continue}let a=i.match(/^title\s+"([^"]+)"/);if(a){s=a[1];continue}let c=i.match(/^x-axis\s+(?:"([^"]*)"\s*)?\[([^\]]+)\]/);if(c){c[1]&&(e.title=c[1]),e.categories=c[2].split(",").map(g=>g.trim());continue}let l=i.match(/^x-axis\s+(?:"([^"]*)"\s+)?(-?\d+(?:\.\d+)?)\s*-->\s*(-?\d+(?:\.\d+)?)/);if(l){l[1]&&(e.title=l[1]),e.range={min:parseFloat(l[2]),max:parseFloat(l[3])};continue}let d=i.match(/^y-axis\s+(?:"([^"]*)"\s+)?(-?\d+(?:\.\d+)?)\s*-->\s*(-?\d+(?:\.\d+)?)/);if(d){d[1]&&(n.title=d[1]),n.range={min:parseFloat(d[2]),max:parseFloat(d[3])};continue}let h=i.match(/^y-axis\s+"([^"]+)"\s*$/);if(h){n.title=h[1];continue}let f=i.match(/^bar\s+\[([^\]]+)\]/);if(f){o.push({type:"bar",data:cn(f[1])});continue}let u=i.match(/^line\s+\[([^\]]+)\]/);if(u){o.push({type:"line",data:cn(u[1])});continue}}if(!n.range&&o.length>0){let i=o.flatMap(d=>d.data),a=Math.min(...i),c=Math.max(...i),l=c-a||1;a=a-l*.1,c=c+l*.1,a>0&&a<l*.5&&(a=0),n.range={min:a,max:c}}return n.range||(n.range={min:0,max:100}),{title:s,horizontal:r,xAxis:e,yAxis:n,series:o}}function cn(t){return t.split(",").map(e=>parseFloat(e.trim()))}var F={plotWidth:600,plotHeight:340,padding:22,titleFontSize:18,titleFontWeight:600,titleHeight:42,axisLabelFontSize:14,axisLabelFontWeight:400,axisTitleFontSize:15,axisTitleFontWeight:500,xLabelHeight:38,yLabelWidth:58,yLabelGap:18,axisTitlePad:30,tickLength:4,barPadRatio:.2,barGroupGap:0,maxBarWidth:40,legendFontSize:14,legendFontWeight:400,legendHeight:28,legendSwatchW:14,legendSwatchH:14,legendGap:6,legendItemGap:16};function Lo(t,e={}){return t.horizontal?Io(t):To(t)}function To(t){let e=!!t.title,n=!!t.xAxis.title,o=!!t.yAxis.title,s=t.series.length>1,r=t.yAxis.range,i=ln(r.min,r.max),a=Math.max(...i.map(et=>wt(xe(et),F.axisLabelFontSize,F.axisLabelFontWeight)),F.yLabelWidth),c=F.padding+(e?F.titleHeight:0)+(s?F.legendHeight:0),l=F.padding+F.xLabelHeight+(n?F.axisTitlePad:0),d=F.padding+a+F.yLabelGap+(o?F.axisTitlePad:0),h=F.padding,f=F.plotWidth,u=F.plotHeight,g=d+f+h,p=c+u+l,$={x:d,y:c,width:f,height:u},A=Pe(t),X=et=>d+(et+.5)*(f/A),v=f/A,Y=et=>{let w=(et-r.min)/(r.max-r.min||1);return c+u-w*u},D=Eo(t,X,c+u,v),V=i.map(et=>({label:xe(et),x:d,y:Y(et),tx:d-F.tickLength,ty:Y(et),labelX:d-F.yLabelGap,labelY:Y(et),textAnchor:"end"})),ft=i.map(et=>({x1:d,y1:Y(et),x2:d+f,y2:Y(et)})),j=Xe(t,A),m=t.series.map((et,w)=>w),M=Yo(t,X,Y,v,r.min,j,m),H=Po(t,X,Y,j,m),C=F.padding+(e?F.titleHeight:0)+F.legendHeight/2,z=s?dn(t,g/2,C,m):[],P={x1:d,y1:c+u,x2:d+f,y2:c+u},U={x1:d,y1:c,x2:d,y2:c+u},T={ticks:D,line:P,...n?{title:{text:t.xAxis.title,x:d+f/2,y:p-F.padding}}:{}},K={ticks:V,line:U,...o?{title:{text:t.yAxis.title,x:F.padding+4,y:c+u/2,rotate:-90}}:{}},it=e?{text:t.title,x:g/2,y:F.padding+F.titleFontSize}:void 0;return{width:g,height:p,title:it,xAxis:T,yAxis:K,plotArea:$,bars:M,lines:H,gridLines:ft,legend:z}}function Io(t){let e=!!t.title,n=!!t.xAxis.title,o=!!t.yAxis.title,s=t.series.length>1,r=t.yAxis.range,i=ln(r.min,r.max),a=Pe(t),c=Xe(t,a),l=Math.max(...c.map(x=>wt(x,F.axisLabelFontSize,F.axisLabelFontWeight)),40),d=F.padding+(e?F.titleHeight:0)+(s?F.legendHeight:0),h=F.padding+F.xLabelHeight+(o?F.axisTitlePad:0),f=F.padding+l+F.yLabelGap+(n?F.axisTitlePad:0),u=F.padding,g=F.plotWidth,p=F.plotHeight,$=f+g+u,A=d+p+h,X={x:f,y:d,width:g,height:p},v=x=>{let B=(x-r.min)/(r.max-r.min||1);return f+B*g},Y=p/a,D=x=>d+(x+.5)*Y,V=i.map(x=>({label:xe(x),x:v(x),y:d+p,tx:v(x),ty:d+p+F.tickLength,labelX:v(x),labelY:d+p+18,textAnchor:"middle"})),ft=c.map((x,B)=>({label:x,x:f,y:D(B),tx:f-F.tickLength,ty:D(B),labelX:f-F.yLabelGap,labelY:D(B),textAnchor:"end"})),j=i.map(x=>({x1:v(x),y1:d,x2:v(x),y2:d+p})),m=t.series.map((x,B)=>B),H=t.series.filter(x=>x.type==="bar").length,C=[];if(H>0){let x=Y*(1-F.barPadRatio),B=H>1?(x-(H-1)*F.barGroupGap)/H:x,rt=Math.min(B,F.maxBarWidth),y=H>1?rt*H+F.barGroupGap*(H-1):rt,R=0,W=0;for(let E of t.series){if(E.type!=="bar"){W++;continue}for(let _=0;_<E.data.length;_++){let O=D(_)-y/2+R*(rt+F.barGroupGap),k=v(Math.max(E.data[_],r.min)),nt=v(Math.max(0,r.min));C.push({x:Math.min(nt,k),y:O,width:Math.abs(k-nt),height:rt,value:E.data[_],label:c[_],seriesIndex:R,colorIndex:m[W]})}R++,W++}}let z=[],P=0,U=0;for(let x of t.series){if(x.type!=="line"){U++;continue}let B=x.data.map((rt,y)=>({x:v(rt),y:D(y),value:rt,label:c[y]}));z.push({points:B,seriesIndex:P,colorIndex:m[U]}),P++,U++}let T={x1:f,y1:d+p,x2:f+g,y2:d+p},K={x1:f,y1:d,x2:f,y2:d+p},it={ticks:V,line:T,...o?{title:{text:t.yAxis.title,x:f+g/2,y:A-F.padding}}:{}},et={ticks:ft,line:K,...n?{title:{text:t.xAxis.title,x:F.padding+4,y:d+p/2,rotate:-90}}:{}},w=e?{text:t.title,x:$/2,y:F.padding+F.titleFontSize}:void 0,G=F.padding+(e?F.titleHeight:0)+F.legendHeight/2,N=s?dn(t,$/2,G,m):[];return{width:$,height:A,horizontal:!0,title:w,xAxis:it,yAxis:et,plotArea:X,bars:C,lines:z,gridLines:j,legend:N}}function Pe(t){if(t.xAxis.categories)return t.xAxis.categories.length;for(let e of t.series)if(e.data.length>0)return e.data.length;return 1}function Xe(t,e){if(t.xAxis.categories)return t.xAxis.categories;if(t.xAxis.range){let{min:n,max:o}=t.xAxis.range,s=e>1?(o-n)/(e-1):0;return Array.from({length:e},(r,i)=>xe(n+s*i))}return Array.from({length:e},(n,o)=>String(o+1))}function Eo(t,e,n,o){let s=Pe(t);return Xe(t,s).map((i,a)=>({label:i,x:e(a),y:n,tx:e(a),ty:n+F.tickLength,labelX:e(a),labelY:n+18,textAnchor:"middle"}))}function Yo(t,e,n,o,s,r,i){let c=t.series.filter($=>$.type==="bar").length;if(c===0)return[];let l=o*(1-F.barPadRatio),d=c>1?(l-(c-1)*F.barGroupGap)/c:l,h=Math.min(d,F.maxBarWidth),f=c>1?h*c+F.barGroupGap*(c-1):h,u=[],g=0,p=0;for(let $ of t.series){if($.type!=="bar"){p++;continue}for(let A=0;A<$.data.length;A++){let Y=e(A)-f/2+g*(h+F.barGroupGap),D=n($.data[A]),V=n(Math.max(0,s));u.push({x:Y,y:Math.min(D,V),width:h,height:Math.abs(V-D),value:$.data[A],label:r[A],seriesIndex:g,colorIndex:i[p]})}g++,p++}return u}function Po(t,e,n,o,s){let r=[],i=0,a=0;for(let c of t.series){if(c.type!=="line"){a++;continue}let l=c.data.map((d,h)=>({x:e(h),y:n(d),value:d,label:o[h]}));r.push({points:l,seriesIndex:i,colorIndex:s[a]}),i++,a++}return r}function ln(t,e){let n=e-t;if(n<=0)return[t];let o=n/6,s=Math.pow(10,Math.floor(Math.log10(o))),r=o/s,i;r<=1.5?i=s:r<=3?i=2*s:r<=7?i=5*s:i=10*s;let a=Math.ceil(t/i)*i,c=[];for(let l=a;l<=e+i*.001;l+=i)c.push(Math.round(l*1e10)/1e10);return c}function xe(t){return Number.isInteger(t)?String(t):t.toFixed(Math.abs(t)<10?1:0)}function dn(t,e,n,o){let s=[],r=0,i=0;for(let d=0;d<t.series.length;d++){let h=t.series[d],f=h.type==="bar"?`Bar ${r+1}`:`Line ${i+1}`;s.push({label:f,x:0,y:n,type:h.type,seriesIndex:h.type==="bar"?r:i,colorIndex:o[d]}),h.type==="bar"?r++:i++}let a=s.map(d=>{let h=wt(d.label,F.legendFontSize,F.legendFontWeight);return F.legendSwatchW+F.legendGap+h}),c=a.reduce((d,h)=>d+h,0)+(s.length-1)*F.legendItemGap,l=e-c/2;for(let d=0;d<s.length;d++)s[d].x=l,l+=a[d]+F.legendItemGap;return s}var ae="#3b82f6";function un(t){let e=t.replace("#",""),n=parseInt(e.substring(0,2),16)/255,o=parseInt(e.substring(2,4),16)/255,s=parseInt(e.substring(4,6),16)/255,r=Math.max(n,o,s),i=Math.min(n,o,s),a=(r+i)/2;if(r===i)return[0,0,a*100];let c=r-i,l=a>.5?c/(2-r-i):c/(r+i),d;return r===n?d=((o-s)/c+(o<s?6:0))/6:r===o?d=((s-n)/c+2)/6:d=((n-o)/c+4)/6,[d*360,l*100,a*100]}function Xo(t,e,n){let o=e/100,s=n/100,r=(1-Math.abs(2*s-1))*o,i=r*(1-Math.abs(t/60%2-1)),a=s-r/2,c,l,d;t<60?(c=r,l=i,d=0):t<120?(c=i,l=r,d=0):t<180?(c=0,l=r,d=i):t<240?(c=0,l=i,d=r):t<300?(c=i,l=0,d=r):(c=r,l=0,d=i);let h=f=>Math.round((f+a)*255).toString(16).padStart(2,"0");return`#${h(c)}${h(l)}${h(d)}`}function fn(t){return/^#[0-9a-fA-F]{6}$/.test(t)}function Ho(t){return un(t)[2]<50}function be(t,e,n){if(t===0)return e;let o=fn(e)?e:ae,s=n&&fn(n)?n:void 0,[r,i]=un(o),a=Math.max(55,Math.min(85,i)),c=Math.ceil(t/2),l=t%2===1,d=s&&Ho(s)?!l:l,h=d?Math.max(25,48-c*13):Math.min(78,55+c*11),f=(d?-8:12)*c,u=((r+f)%360+360)%360;return Xo(u,a,h)}var pt={titleSize:18,titleWeight:600,axisTitleSize:15,axisTitleWeight:500,labelSize:14,labelWeight:400,legendSize:14,legendWeight:400,dotRadius:5,lineWidth:2.5,barRadius:8},ut={fontSize:15,fontWeight:500,height:32,padX:14,offsetY:12,rx:8,minY:4,pointerSize:6};function Go(t,e,n="Inter",o=!1,s=!1){let r=[],i=Math.max(0,...t.bars.map(m=>m.colorIndex),...t.lines.map(m=>m.colorIndex)),a=se(t.width,t.height,e,o).replace("<svg ",`<svg data-xychart-colors="${i}" `);r.push(a),r.push(ie(n,!1));let c=Math.max(...t.lines.map(m=>m.points.length),0),l=c>0&&c<=12,{style:d,defs:h}=Wo(t,s,l,e.accent,e.bg);r.push(d),h&&r.push(h);let{plotArea:f}=t,u=t.xAxis.ticks.map(m=>m.x),g=t.horizontal?t.yAxis.ticks.map(m=>m.y):t.gridLines.map(m=>m.y1),p=u.length>1?Math.abs(u[1]-u[0]):f.width/6,$=g.length>1?Math.abs(g[1]-g[0]):f.height/6,A=p/Math.max(1,Math.round(p/20)),X=$/Math.max(1,Math.round($/20)),v=u[0]??f.x,Y=g[0]??f.y,D=v-Math.ceil((v-f.x)/A)*A,V=Y-Math.ceil((Y-f.y)/X)*X;for(let m=V;m<=f.y+f.height+.5;m+=X)for(let M=D;M<=f.x+f.width+.5;M+=A)r.push(`<circle cx="${S(M)}" cy="${S(m)}" r="1.5" class="xychart-grid"/>`);let ft=[];for(let m of t.bars){let M=` data-value="${m.value}"${m.label?` data-label="${vt(m.label)}"`:""}`,H=t.horizontal?Bo(m.x,m.y,m.width,m.height,pt.barRadius):No(m.x,m.y,m.width,m.height,pt.barRadius);if(r.push(`<path d="${H}" class="xychart-bar xychart-color-${m.colorIndex}"${M}/>`),s){let C=He(m.value),z=m.label?`${m.label}: ${C}`:C,P=hn(m.x+m.width/2,m.y,C);ft.push(`<g class="xychart-bar-group"><rect x="${S(m.x)}" y="${S(m.y)}" width="${S(m.width)}" height="${S(m.height)}" fill="transparent"/><title>${vt(z)}</title>`+P+"</g>")}}for(let m of t.lines){if(m.points.length===0)continue;let M=_o(m.points);r.push(`<path d="${M}" class="xychart-line-shadow xychart-color-${m.colorIndex}" transform="translate(0,2)"/>`),r.push(`<path d="${M}" class="xychart-line xychart-color-${m.colorIndex}"/>`)}let j=[];if(s||l){let m=new Map;for(let H of t.legend)H.type==="line"&&m.set(H.seriesIndex,H.label);let M=new Map;for(let H of t.lines)for(let C of H.points){let z=S(C.x);M.has(z)||M.set(z,[]),M.get(z).push({x:C.x,y:C.y,value:C.value,label:C.label,seriesIndex:H.seriesIndex,colorIndex:H.colorIndex})}for(let H of M.values()){let C=H[0].x,z=H[0].label||"";if(s&&H.length>1){let P=Math.min(...H.map(x=>x.y)),U=Math.max(...H.map(x=>x.y)),T=pt.dotRadius*3,K=`<rect x="${S(C-T)}" y="${S(P-T)}" width="${S(T*2)}" height="${S(U-P+T*2)}" fill="transparent" class="xychart-hit"/>`,it=H.map(x=>({text:He(x.value),legendLabel:m.get(x.seriesIndex)||`Line ${x.seriesIndex+1}`})),et=zo(C,P-pt.dotRadius,z,it),w=it.map(x=>x.text),G=z?`${z}: ${w.join(" \xB7 ")}`:w.join(" \xB7 "),N=`<g class="xychart-dot-group">${K}`;for(let x of H){let B=` data-value="${x.value}"${x.label?` data-label="${vt(x.label)}"`:""}`;N+=`<circle cx="${S(x.x)}" cy="${S(x.y)}" r="${pt.dotRadius}" class="xychart-dot xychart-color-${x.colorIndex}"${B}/>`}N+=`<title>${vt(G)}</title>${et}</g>`,j.push(N)}else if(s){let P=H[0],U=` data-value="${P.value}"${P.label?` data-label="${vt(P.label)}"`:""}`,T=He(P.value),K=P.label?`${P.label}: ${T}`:T,it=hn(C,P.y-pt.dotRadius,T),et=l?`<circle cx="${S(C)}" cy="${S(P.y)}" r="${pt.dotRadius*3}" fill="transparent" class="xychart-hit"/>`:"";j.push(`<g class="xychart-dot-group">${et}<circle cx="${S(P.x)}" cy="${S(P.y)}" r="${pt.dotRadius}" class="xychart-dot xychart-color-${P.colorIndex}"${U}/><title>${vt(K)}</title>${it}</g>`)}else for(let P of H){let U=` data-value="${P.value}"${P.label?` data-label="${vt(P.label)}"`:""}`;r.push(`<circle cx="${S(P.x)}" cy="${S(P.y)}" r="${pt.dotRadius}" class="xychart-dot xychart-color-${P.colorIndex}"${U}/>`)}}}for(let m of t.xAxis.ticks)r.push(`<text x="${m.labelX}" y="${m.labelY}" text-anchor="${m.textAnchor}" font-size="${pt.labelSize}" font-weight="${pt.labelWeight}" dy="${Nt}" class="xychart-label">${vt(m.label)}</text>`);for(let m of t.yAxis.ticks)r.push(`<text x="${m.labelX}" y="${m.labelY}" text-anchor="${m.textAnchor}" font-size="${pt.labelSize}" font-weight="${pt.labelWeight}" dy="${Nt}" class="xychart-label">${vt(m.label)}</text>`);if(t.xAxis.title){let m=t.xAxis.title,M=m.rotate?` transform="rotate(${m.rotate},${m.x},${m.y})"`:"";r.push(`<text x="${m.x}" y="${m.y}" text-anchor="middle"${M} font-size="${pt.axisTitleSize}" font-weight="${pt.axisTitleWeight}" dy="${Nt}" class="xychart-axis-title">${vt(m.text)}</text>`)}if(t.yAxis.title){let m=t.yAxis.title,M=m.rotate?` transform="rotate(${m.rotate},${m.x},${m.y})"`:"";r.push(`<text x="${m.x}" y="${m.y}" text-anchor="middle"${M} font-size="${pt.axisTitleSize}" font-weight="${pt.axisTitleWeight}" dy="${Nt}" class="xychart-axis-title">${vt(m.text)}</text>`)}t.title&&r.push(`<text x="${t.title.x}" y="${t.title.y}" text-anchor="middle" font-size="${pt.titleSize}" font-weight="${pt.titleWeight}" dy="${Nt}" class="xychart-title">${vt(t.title.text)}</text>`);for(let m of t.legend){if(m.type==="bar")r.push(`<rect x="${m.x}" y="${m.y-14/2}" width="14" height="14" rx="3" class="xychart-bar xychart-color-${m.colorIndex}"/>`);else{let z=m.y;r.push(`<line x1="${m.x}" y1="${z}" x2="${m.x+14}" y2="${z}" stroke-width="${pt.lineWidth}" stroke-linecap="round" class="xychart-legend-line xychart-color-${m.colorIndex}"/>`)}r.push(`<text x="${m.x+14+6}" y="${m.y}" text-anchor="start" font-size="${pt.legendSize}" font-weight="${pt.legendWeight}" dy="${Nt}" class="xychart-label">${vt(m.label)}</text>`)}for(let m of ft)r.push(m);for(let m of j)r.push(m);return r.push("</svg>"),r.join(`
67`)}function Wo(t,e,n,o,s){let r=o??ae,i=new Set;for(let f of t.bars)i.add(f.colorIndex);for(let f of t.lines)i.add(f.colorIndex);let a=[];for(let f of[...i].sort((u,g)=>u-g)){let u=f===0?`var(--accent, ${ae})`:be(f,r,s);a.push(` --xychart-color-${f}: ${u};`),a.push(` --xychart-bar-fill-${f}: color-mix(in srgb, var(--bg) 75%, var(--xychart-color-${f}) 25%);`)}let c=[];for(let f of[...i].sort((u,g)=>u-g)){let u=`var(--xychart-color-${f})`;c.push(` .xychart-bar.xychart-color-${f} { stroke: ${u}; fill: var(--xychart-bar-fill-${f}); }`),c.push(` path.xychart-color-${f}, line.xychart-color-${f} { stroke: ${u}; }`),c.push(` circle.xychart-color-${f} { fill: ${u}; }`)}let l=e?`
68 .xychart-tip { opacity: 0; pointer-events: none; }
69 .xychart-tip-bg { fill: var(--_text); filter: drop-shadow(0 1px 3px color-mix(in srgb, var(--fg) 20%, transparent)); }
70 .xychart-tip-text { fill: var(--bg); font-size: ${ut.fontSize}px; font-weight: ${ut.fontWeight}; }
71 .xychart-tip-ptr { fill: var(--_text); }
72 .xychart-bar-group:hover .xychart-tip,
73 .xychart-dot-group:hover .xychart-tip { opacity: 1; }`:"",d=a.length>0?`
74 svg {
75${a.join(`
76`)}
77 }`:"";return{style:`<style>
78 .xychart-grid { fill: var(--_inner-stroke); stroke: none; opacity: 0.65; }
79 .xychart-bar { stroke-width: 1.5; }
80 .xychart-line { fill: none; stroke-width: ${pt.lineWidth}; stroke-linecap: round; stroke-linejoin: round; }
81 .xychart-line-shadow { fill: none; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; opacity: 0.12; }
82 .xychart-dot { stroke: var(--bg); stroke-width: 2; }
83 .xychart-label { fill: var(--_text-muted); }
84 .xychart-axis-title { fill: var(--_text-sec); }
85 .xychart-title { fill: var(--_text); }${d}
86${c.join(`
87`)}${l}
88</style>`,defs:""}}function No(t,e,n,o,s){let r=Math.min(s,n/2,o/2);return r<=0?`M${S(t)},${S(e)} h${S(n)} v${S(o)} h${S(-n)} Z`:[`M${S(t)},${S(e+r)}`,`Q${S(t)},${S(e)} ${S(t+r)},${S(e)}`,`L${S(t+n-r)},${S(e)}`,`Q${S(t+n)},${S(e)} ${S(t+n)},${S(e+r)}`,`L${S(t+n)},${S(e+o-r)}`,`Q${S(t+n)},${S(e+o)} ${S(t+n-r)},${S(e+o)}`,`L${S(t+r)},${S(e+o)}`,`Q${S(t)},${S(e+o)} ${S(t)},${S(e+o-r)}`,"Z"].join(" ")}function Bo(t,e,n,o,s){let r=Math.min(s,n/2,o/2);return r<=0?`M${S(t)},${S(e)} h${S(n)} v${S(o)} h${S(-n)} Z`:[`M${S(t+r)},${S(e)}`,`L${S(t+n-r)},${S(e)}`,`Q${S(t+n)},${S(e)} ${S(t+n)},${S(e+r)}`,`L${S(t+n)},${S(e+o-r)}`,`Q${S(t+n)},${S(e+o)} ${S(t+n-r)},${S(e+o)}`,`L${S(t+r)},${S(e+o)}`,`Q${S(t)},${S(e+o)} ${S(t)},${S(e+o-r)}`,`L${S(t)},${S(e+r)}`,`Q${S(t)},${S(e)} ${S(t+r)},${S(e)}`,"Z"].join(" ")}function _o(t){if(t.length===0)return"";if(t.length===1)return`M${S(t[0].x)},${S(t[0].y)}`;if(t.length===2)return`M${S(t[0].x)},${S(t[0].y)} L${S(t[1].x)},${S(t[1].y)}`;let e=t.length,n=[],o=[];for(let a=0;a<e-1;a++)n.push(t[a+1].x-t[a].x),o.push(n[a]===0?0:(t[a+1].y-t[a].y)/n[a]);let s=new Array(e).fill(0);if(e>2){let a=new Array(e).fill(0),c=new Array(e).fill(0);for(let l=1;l<e-1;l++){let d=2*(n[l-1]+n[l]),h=3*(o[l]-o[l-1]);if(l===1)a[l]=n[l]/d,c[l]=h/d;else{let f=d-n[l-1]*a[l-1];a[l]=n[l]/f,c[l]=(h-n[l-1]*c[l-1])/f}}for(let l=e-2;l>=1;l--)s[l]=c[l]-a[l]*s[l+1]}let r=new Array(e).fill(0);for(let a=0;a<e-1;a++)r[a]=o[a]-n[a]*(2*s[a]+s[a+1])/3;r[e-1]=o[e-2]+n[e-2]*s[e-2]/3;let i=`M${S(t[0].x)},${S(t[0].y)}`;for(let a=0;a<e-1;a++){let c=n[a]/3,l=t[a].x+c,d=t[a].y+r[a]*c,h=t[a+1].x-c,f=t[a+1].y-r[a+1]*c;i+=` C${S(l)},${S(d)} ${S(h)},${S(f)} ${S(t[a+1].x)},${S(t[a+1].y)}`}return i}function zo(t,e,n,o){let a=wt(n,ut.fontSize,600),c=Math.max(...o.map(D=>{let V=wt(D.legendLabel,ut.fontSize,ut.fontWeight),ft=wt(D.text,ut.fontSize,ut.fontWeight);return V+10+ft})),l=Math.max(a,c)+ut.padX*2,d=26+o.length*20+6,h=Math.max(ut.minY,e-ut.offsetY-d-ut.pointerSize),f=t-l/2,u=t,g=h+d,p=ut.pointerSize,$=`<polygon points="${S(u-p)},${S(g)} ${S(u+p)},${S(g)} ${S(u)},${S(g+p)}" class="xychart-tip xychart-tip-ptr"/>`,A=`<rect x="${S(f)}" y="${S(h)}" width="${S(l)}" height="${d}" rx="${ut.rx}" class="xychart-tip xychart-tip-bg"/>`;A+=$;let X=h+6+20/2;A+=`<text x="${S(t)}" y="${S(X)}" text-anchor="middle" font-weight="600" font-size="${ut.fontSize}" dy="${Nt}" class="xychart-tip xychart-tip-text">${vt(n)}</text>`;let v=f+ut.padX,Y=f+l-ut.padX;for(let D of o)X+=20,A+=`<text x="${S(v)}" y="${S(X)}" text-anchor="start" font-size="${ut.fontSize}" font-weight="${ut.fontWeight}" dy="${Nt}" class="xychart-tip xychart-tip-text">${vt(D.legendLabel)}</text>`,A+=`<text x="${S(Y)}" y="${S(X)}" text-anchor="end" font-size="${ut.fontSize}" font-weight="${ut.fontWeight}" dy="${Nt}" class="xychart-tip xychart-tip-text">${vt(D.text)}</text>`;return A}function hn(t,e,n){let s=wt(n,ut.fontSize,ut.fontWeight)+ut.padX*2,r=ut.height,i=Math.max(ut.minY,e-ut.offsetY-r-ut.pointerSize),a=t-s/2,c=t,l=i+r/2,d=t,h=i+r,f=ut.pointerSize,u=`<polygon points="${S(d-f)},${S(h)} ${S(d+f)},${S(h)} ${S(d)},${S(h+f)}" class="xychart-tip xychart-tip-ptr"/>`;return`<rect x="${S(a)}" y="${S(i)}" width="${S(s)}" height="${r}" rx="${ut.rx}" class="xychart-tip xychart-tip-bg"/>`+u+`<text x="${S(c)}" y="${S(l)}" text-anchor="middle" dy="${Nt}" class="xychart-tip xychart-tip-text">${vt(n)}</text>`}function He(t){return Number.isInteger(t)?t.toLocaleString("en-US"):t.toFixed(Math.abs(t)<10?1:0)}function S(t){return String(Math.round(t*10)/10)}function vt(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var Z={x:1,y:0},q={x:1,y:2},tt={x:0,y:1},J={x:2,y:1},Tt={x:2,y:0},Lt={x:0,y:0},Ht={x:2,y:2},It={x:0,y:2},jt={x:1,y:1};function Ge(t,e){return t.x===e.x&&t.y===e.y}function ye(t,e){return t.x===e.x&&t.y===e.y}function ue(t,e){return{x:t.x+e.x,y:t.y+e.y}}function Ft(t){return`${t.x},${t.y}`}var gn={name:"",styles:{}};var Ce={fg:"#27272a",border:"#a1a1aa",line:"#71717a",arrow:"#52525b",corner:"#71717a",junction:"#a1a1aa"};function mn(){let t=globalThis.process;if(t){if(!t.stdout?.isTTY)return"none";let e=t.env?.COLORTERM?.toLowerCase()??"",n=t.env?.TERM?.toLowerCase()??"";return e==="truecolor"||e==="24bit"?"truecolor":n.includes("256color")||n.includes("256")?"ansi256":n&&n!=="dumb"?"ansi16":"none"}return typeof document<"u"?"html":"none"}function Ne(t){let e=t.replace("#","");return e.length===3?{r:parseInt(e[0]+e[0],16),g:parseInt(e[1]+e[1],16),b:parseInt(e[2]+e[2],16)}:{r:parseInt(e.substring(0,2),16),g:parseInt(e.substring(2,4),16),b:parseInt(e.substring(4,6),16)}}var we="\x1B[",$e=`${we}0m`;function pn(t){let{r:e,g:n,b:o}=Ne(t);return`${we}38;2;${e};${n};${o}m`}function Oo(t,e,n){let o=(t+e+n)/3;if(Math.max(Math.abs(t-o),Math.abs(e-o),Math.abs(n-o))<10){let l=Math.round(o/255*23);return 232+Math.min(23,Math.max(0,l))}let r=l=>l<48?0:l<115?1:Math.min(5,Math.floor((l-35)/40)),i=r(t),a=r(e),c=r(n);return 16+36*i+6*a+c}function xn(t){let{r:e,g:n,b:o}=Ne(t),s=Oo(e,n,o);return`${we}38;5;${s}m`}function bn(t){let{r:e,g:n,b:o}=Ne(t),s=.299*e+.587*n+.114*o,r=s>100?0:60,i;return e>180&&n<100&&o<100?i=31:n>180&&e<100&&o<100?i=32:e>150&&n>150&&o<100?i=33:o>180&&e<100&&n<100?i=34:e>150&&o>150&&n<100?i=35:n>150&&o>150&&e<100?i=36:s>200?i=37:s<50?i=30:i=37,`${we}${i+r}m`}function yn(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function $n(t,e){return`<span style="color:${t}">${yn(e)}</span>`}function Cn(t,e){switch(t){case"text":return e.fg;case"border":return e.border;case"line":return e.line;case"arrow":return e.arrow;case"corner":return e.corner??e.line;case"junction":return e.junction??e.border;default:return e.fg}}function We(t,e,n){if(n==="none")return"";let o=Cn(t,e);switch(n){case"truecolor":return pn(o);case"ansi256":return xn(o);case"ansi16":return bn(o);default:return""}}function wn(t,e,n,o){if(o==="none")return t.join("");if(o==="html")return jo(t,e,n);let s="",r=null,i="";for(let a=0;a<t.length;a++){let c=t[a],l=e[a]??null;if(c===" "){i.length>0&&(r!==null?s+=We(r,n,o)+i+$e:s+=i,i="",r=null),s+=c;continue}if(l===r){i+=c;continue}i.length>0&&(r!==null?s+=We(r,n,o)+i+$e:s+=i),i=c,r=l}return i.length>0&&r!==null?s+=We(r,n,o)+i+$e:i.length>0&&(s+=i),s}function jo(t,e,n){let o="",s=null,r="",i=()=>{r.length!==0&&(s!==null?o+=$n(Cn(s,n),r):o+=yn(r),r="",s=null)};for(let a=0;a<t.length;a++){let c=t[a],l=e[a]??null;if(c===" "){i(),o+=" ";continue}if(l===s){r+=c;continue}i(),r=c,s=l}return i(),o}function Me(t,e,n){if(n==="none"||t.length===0)return t;if(n==="html")return $n(e,t);let o;switch(n){case"truecolor":o=pn(e);break;case"ansi256":o=xn(e);break;case"ansi16":o=bn(e);break;default:return t}return`${o}${t}${$e}`}function gt(t,e){let n=[];for(let o=0;o<=t;o++){let s=[];for(let r=0;r<=e;r++)s.push(" ");n.push(s)}return n}function $t(t){let[e,n]=he(t);return gt(e,n)}function Jt(t,e){let n=[];for(let o=0;o<=t;o++){let s=[];for(let r=0;r<=e;r++)s.push(null);n.push(s)}return n}function qt(t,e,n){let o=t.length-1,s=(t[0]?.length??1)-1,r=Math.max(e,o),i=Math.max(n,s),a=Jt(r,i);for(let c=0;c<a.length;c++)for(let l=0;l<a[0].length;l++)c<t.length&&l<t[0].length&&(a[c][l]=t[c][l]);return t.length=0,t.push(...a),t}function Vt(t,e,n,o){(e>=t.length||n>=(t[0]?.length??0))&&qt(t,e,n),t[e][n]=o}function he(t){return[t.length-1,(t[0]?.length??1)-1]}function _t(t,e,n){let[o,s]=he(t),r=Math.max(e,o),i=Math.max(n,s),a=gt(r,i);for(let c=0;c<a.length;c++)for(let l=0;l<a[0].length;l++)c<t.length&&l<t[0].length&&(a[c][l]=t[c][l]);return t.length=0,t.push(...a),t}var Fo=new Set(["\u2500","\u2502","\u250C","\u2510","\u2514","\u2518","\u251C","\u2524","\u252C","\u2534","\u253C","\u2574","\u2575","\u2576","\u2577"]);function Mn(t){return Fo.has(t)}function An(t){return/^[a-zA-Z0-9]$/.test(t)}var qo={"\u2500":{"\u2502":"\u253C","\u250C":"\u252C","\u2510":"\u252C","\u2514":"\u2534","\u2518":"\u2534","\u251C":"\u253C","\u2524":"\u253C","\u252C":"\u252C","\u2534":"\u2534"},"\u2502":{"\u2500":"\u253C","\u250C":"\u251C","\u2510":"\u2524","\u2514":"\u251C","\u2518":"\u2524","\u251C":"\u251C","\u2524":"\u2524","\u252C":"\u253C","\u2534":"\u253C"},"\u250C":{"\u2500":"\u252C","\u2502":"\u251C","\u2510":"\u252C","\u2514":"\u251C","\u2518":"\u253C","\u251C":"\u251C","\u2524":"\u253C","\u252C":"\u252C","\u2534":"\u253C"},"\u2510":{"\u2500":"\u252C","\u2502":"\u2524","\u250C":"\u252C","\u2514":"\u253C","\u2518":"\u2524","\u251C":"\u253C","\u2524":"\u2524","\u252C":"\u252C","\u2534":"\u253C"},"\u2514":{"\u2500":"\u2534","\u2502":"\u251C","\u250C":"\u251C","\u2510":"\u253C","\u2518":"\u2534","\u251C":"\u251C","\u2524":"\u253C","\u252C":"\u253C","\u2534":"\u2534"},"\u2518":{"\u2500":"\u2534","\u2502":"\u2524","\u250C":"\u253C","\u2510":"\u2524","\u2514":"\u2534","\u251C":"\u253C","\u2524":"\u2524","\u252C":"\u253C","\u2534":"\u2534"},"\u251C":{"\u2500":"\u253C","\u2502":"\u251C","\u250C":"\u251C","\u2510":"\u253C","\u2514":"\u251C","\u2518":"\u253C","\u2524":"\u253C","\u252C":"\u253C","\u2534":"\u253C"},"\u2524":{"\u2500":"\u253C","\u2502":"\u2524","\u250C":"\u253C","\u2510":"\u2524","\u2514":"\u253C","\u2518":"\u2524","\u251C":"\u253C","\u252C":"\u253C","\u2534":"\u253C"},"\u252C":{"\u2500":"\u252C","\u2502":"\u253C","\u250C":"\u252C","\u2510":"\u252C","\u2514":"\u253C","\u2518":"\u253C","\u251C":"\u253C","\u2524":"\u253C","\u2534":"\u253C"},"\u2534":{"\u2500":"\u2534","\u2502":"\u253C","\u250C":"\u253C","\u2510":"\u253C","\u2514":"\u2534","\u2518":"\u2534","\u251C":"\u253C","\u2524":"\u253C","\u252C":"\u253C"}};function Uo(t,e){return qo[t]?.[e]??t}function zt(t,e,n,...o){let[s,r]=he(t);for(let a of o){let[c,l]=he(a);s=Math.max(s,c+e.x),r=Math.max(r,l+e.y)}let i=gt(s,r);for(let a=0;a<=s;a++)for(let c=0;c<=r;c++)a<t.length&&c<t[0].length&&(i[a][c]=t[a][c]);for(let a of o)for(let c=0;c<a.length;c++)for(let l=0;l<a[0].length;l++){let d=a[c][l];if(d!==" "){let h=c+e.x,f=l+e.y,u=i[h][f];!n&&Mn(d)&&Mn(u)?i[h][f]=Uo(u,d):An(u)&&An(d)||(i[h][f]=d)}}return i}function te(t,e){let[n,o]=he(t),s=[],r=e?.roleCanvas,i=e?.colorMode??"none",a=e?.theme??Ce;for(let c=0;c<=o;c++)if(i==="none"||!r){let l="";for(let d=0;d<=n;d++)l+=t[d][c];s.push(l)}else{let l=[],d=[];for(let h=0;h<=n;h++)l.push(t[h][c]),d.push(r[h]?.[c]??null);s.push(wn(l,d,a,i))}return s.join(`
89`)}var Jo={"\u25B2":"\u25BC","\u25BC":"\u25B2","\u25E4":"\u25E3","\u25E3":"\u25E4","\u25E5":"\u25E2","\u25E2":"\u25E5","^":"v",v:"^","\u250C":"\u2514","\u2514":"\u250C","\u2510":"\u2518","\u2518":"\u2510","\u252C":"\u2534","\u2534":"\u252C","\u2575":"\u2577","\u2577":"\u2575"};function vn(t){for(let e of t)e.reverse();for(let e of t)for(let n=0;n<e.length;n++){let o=Jo[e[n]];o&&(e[n]=o)}return t}function Sn(t){for(let e of t)e.reverse();return t}function Be(t,e,n,o=!1){_t(t,e.x+n.length,e.y);for(let s=0;s<n.length;s++){let r=e.x+s,i=t[r][e.y];(o||i===" ")&&(t[r][e.y]=n[s])}}function Rn(t,e,n){let o=0,s=0;for(let r of e.values())o+=r;for(let r of n.values())s+=r;_t(t,o-1,s-1)}function Dn(t,e,n){let o=0,s=0;for(let r of e.values())o+=r;for(let r of n.values())s+=r;qt(t,o-1,s-1)}function kn(t,e){let n=new Map,o=0;for(let[a,c]of t.nodes){let l={name:a,displayLabel:c.label,shape:c.shape,index:o,gridCoord:null,drawingCoord:null,drawing:null,drawn:!1,styleClassName:"",styleClass:gn};n.set(a,l),o++}let s=[...n.values()],r=[];for(let a of t.edges){let c=n.get(a.source),l=n.get(a.target);!c||!l||r.push({from:c,to:l,text:a.label??"",path:[],labelLine:[],startDir:{x:0,y:0},endDir:{x:0,y:0},style:a.style,hasArrowStart:a.hasArrowStart,hasArrowEnd:a.hasArrowEnd})}let i=[];for(let a of t.subgraphs)Ln(a,null,n,i);Vo(t.subgraphs,i,n,t);for(let[a,c]of t.classAssignments){let l=n.get(a),d=t.classDefs.get(c);l&&d&&(l.styleClassName=c,l.styleClass={name:c,styles:d})}return{nodes:s,edges:r,canvas:gt(0,0),roleCanvas:Jt(0,0),grid:new Map,columnWidth:new Map,rowHeight:new Map,subgraphs:i,config:e,offsetX:0,offsetY:0,bundles:[]}}function Ln(t,e,n,o){let s;t.direction&&(s=t.direction==="LR"||t.direction==="RL"?"LR":"TD");let r={name:t.label,nodes:[],parent:e,children:[],minX:0,minY:0,maxX:0,maxY:0,direction:s};for(let i of t.nodeIds){let a=n.get(i);a&&r.nodes.push(a)}o.push(r);for(let i of t.children){let a=Ln(i,r,n,o);r.children.push(a);for(let c of a.nodes)r.nodes.includes(c)||r.nodes.push(c)}return r}function Vo(t,e,n,o){let s=new Map;Qo(t,e,s);let r=new Map;function i(a){let c=s.get(a);if(c){for(let l of a.children)i(l);for(let l of a.nodeIds)r.has(l)||r.set(l,c)}}for(let a of t)i(a);for(let a of e)a.nodes=a.nodes.filter(c=>{let l;for(let[h,f]of n)if(f===c){l=h;break}if(!l)return!1;let d=r.get(l);return d?Ko(a,d):!0})}function Ko(t,e){let n=e;for(;n!==null;){if(n===t)return!0;n=n.parent}return!1}function Qo(t,e,n){let o=[];function s(r){for(let i of r)o.push(i),s(i.children)}s(t);for(let r=0;r<o.length&&r<e.length;r++)n.set(o[r],e[r])}var _e=class{items=[];get length(){return this.items.length}push(e){this.items.push(e),this.bubbleUp(this.items.length-1)}pop(){if(this.items.length===0)return;let e=this.items[0],n=this.items.pop();return this.items.length>0&&(this.items[0]=n,this.sinkDown(0)),e}bubbleUp(e){for(;e>0;){let n=e-1>>1;if(this.items[e].priority<this.items[n].priority)[this.items[e],this.items[n]]=[this.items[n],this.items[e]],e=n;else break}}sinkDown(e){let n=this.items.length;for(;;){let o=e,s=2*e+1,r=2*e+2;if(s<n&&this.items[s].priority<this.items[o].priority&&(o=s),r<n&&this.items[r].priority<this.items[o].priority&&(o=r),o!==e)[this.items[e],this.items[o]]=[this.items[o],this.items[e]],e=o;else break}}};function Zo(t,e){let n=Math.abs(t.x-e.x),o=Math.abs(t.y-e.y);return n===0||o===0?n+o:n+o+1}var ti=[{x:1,y:0},{x:-1,y:0},{x:0,y:1},{x:0,y:-1}];function ei(t,e){return e.x<0||e.y<0?!1:!t.has(Ft(e))}function ee(t,e,n){let o=new _e;o.push({coord:e,priority:0});let s=new Map;s.set(Ft(e),0);let r=new Map;for(r.set(Ft(e),null);o.length>0;){let i=o.pop().coord;if(Ge(i,n)){let c=[],l=i;for(;l!==null;)c.unshift(l),l=r.get(Ft(l))??null;return c}let a=s.get(Ft(i));for(let c of ti){let l={x:i.x+c.x,y:i.y+c.y};if(!ei(t,l)&&!Ge(l,n))continue;let d=a+1,h=Ft(l),f=s.get(h);if(f===void 0||d<f){s.set(h,d);let u=d+Zo(l,n);o.push({coord:l,priority:u}),r.set(h,i)}}}return null}function Ut(t){if(t.length<=2)return t;let e=new Set,n=t[0],o=t[1];for(let s=2;s<t.length;s++){let r=t[s],i=o.x-n.x,a=o.y-n.y,c=r.x-o.x,l=r.y-o.y;i===c&&a===l&&e.add(s-1),n=o,o=r}return t.filter((s,r)=>!e.has(r))}function Ae(t){return t===Z?q:t===q?Z:t===tt?J:t===J?tt:t===Tt?It:t===Lt?Ht:t===Ht?Lt:t===It?Tt:jt}function b(t,e){return t.x===e.x&&t.y===e.y}function St(t,e){return t.x===e.x?t.y<e.y?q:Z:t.y===e.y?t.x<e.x?J:tt:t.x<e.x?t.y<e.y?Ht:Tt:t.y<e.y?It:Lt}function ni(t){return t==="LR"?[J,q,q,J]:[q,J,J,q]}function ri(t,e){if(t.from===t.to)return ni(e);let n=St(t.from.gridCoord,t.to.gridCoord),o,s,r,i,a=e==="LR"?b(n,tt)||b(n,Lt)||b(n,It):b(n,Z)||b(n,Lt)||b(n,Tt);return b(n,Ht)?e==="LR"?(o=q,s=tt,r=J,i=Z):(o=J,s=Z,r=q,i=tt):b(n,Tt)?e==="LR"?(o=Z,s=tt,r=J,i=q):(o=J,s=q,r=Z,i=tt):b(n,It)?e==="LR"?(o=q,s=q,r=tt,i=Z):(o=tt,s=Z,r=q,i=J):b(n,Lt)?e==="LR"?(o=q,s=q,r=tt,i=q):(o=J,s=J,r=Z,i=J):a?e==="LR"&&b(n,tt)?(o=q,s=q,r=tt,i=J):e==="TD"&&b(n,Z)?(o=J,s=J,r=Z,i=q):(o=n,s=Ae(n),r=n,i=Ae(n)):(o=n,s=Ae(n),r=n,i=Ae(n)),[o,s,r,i]}function Tn(t,e){let n=kt(t,e.from),o=kt(t,e.to),s=n&&n===o&&n.direction?n.direction:t.config.graphDirection,[r,i,a,c]=ri(e,s),l=ue(e.from.gridCoord,r),d=ue(e.to.gridCoord,i),h=ee(t.grid,l,d),f=ue(e.from.gridCoord,a),u=ue(e.to.gridCoord,c),g=ee(t.grid,f,u);if(h!==null&&g!==null){h=Ut(h),g=Ut(g),h.length<=g.length?(e.startDir=r,e.endDir=i,e.path=h):(e.startDir=a,e.endDir=c,e.path=g);return}if(h!==null){e.startDir=r,e.endDir=i,e.path=Ut(h);return}if(g!==null){e.startDir=a,e.endDir=c,e.path=Ut(g);return}e.startDir=r,e.endDir=i,e.path=[l,d]}function ze(t,e){if(e.text.length===0)return;let n=e.text.length,o=e.path.length,s=t.config.graphDirection==="TD",r=[];for(let f=1;f<o;f++){let u=e.path[f-1],g=e.path[f],p=[u,g],$=oi(t,p),A=u.x===g.x;r.push({line:p,width:$,index:f,isVertical:A})}let i=r.filter(f=>f.width>=n&&f.index>1),a;if(i.length>0)i.sort((f,u)=>u.index-f.index),a=i[0].line;else{let f=r.filter(u=>u.width>=n);f.length>0?(f.sort((u,g)=>g.index-u.index),a=f[0].line):(r.sort((u,g)=>g.width-u.width),a=r[0]?.line??[e.path[0],e.path[1]])}let c=Math.min(a[0].x,a[1].x),l=Math.max(a[0].x,a[1].x),d=c+Math.floor((l-c)/2),h=t.columnWidth.get(d)??0;t.columnWidth.set(d,Math.max(h,n+2)),e.labelLine=[a[0],a[1]]}function oi(t,e){let n=0,o=Math.min(e[0].x,e[1].x),s=Math.max(e[0].x,e[1].x);for(let r=o;r<=s;r++)n+=t.columnWidth.get(r)??0;return n}function En(t){if(t.config.graphDirection!=="TD")return[];let e=[],n=new Set,o=new Map;for(let r of t.edges){if(r.from===r.to)continue;let i=o.get(r.to)??[];i.push(r),o.set(r.to,i)}for(let[r,i]of o){if(i.length<2||!In(i,t)||i.some(c=>n.has(c)))continue;let a={type:"fan-in",edges:[...i],sharedNode:r,otherNodes:i.map(c=>c.from),junctionPoint:null,sharedPath:[],junctionDir:jt,sharedNodeDir:jt};for(let c of i)c.bundle=a,n.add(c);e.push(a)}let s=new Map;for(let r of t.edges){if(r.from===r.to||n.has(r))continue;let i=s.get(r.from)??[];i.push(r),s.set(r.from,i)}for(let[r,i]of s){if(i.length<2||!In(i,t))continue;let a={type:"fan-out",edges:[...i],sharedNode:r,otherNodes:i.map(c=>c.to),junctionPoint:null,sharedPath:[],junctionDir:jt,sharedNodeDir:jt};for(let c of i)c.bundle=a,n.add(c);e.push(a)}return e}function In(t,e){if(t.length<2)return!1;let n=t[0].style,o=kt(e,t[0].from),s=kt(e,t[0].to);for(let r of t){if(r.style!==n||r.text.length>0)return!1;let i=kt(e,r.from),a=kt(e,r.to);if(i!==o||a!==s||i!==a)return!1}return!0}function ii(t,e){let n=t.config.graphDirection,o=e.sharedNode.gridCoord,s=e.otherNodes.map(r=>r.gridCoord);if(e.type==="fan-in"){let r=Math.min(...s.map(l=>l.x)),i=Math.max(...s.map(l=>l.x)),a=Math.min(...s.map(l=>l.y)),c=Math.max(...s.map(l=>l.y));if(n==="TD"){let l=o.y-1,d=Math.floor((r+i)/2)+1;return{x:o.x+1,y:l}}else{let l=o.x-1,d=o.y+1;return{x:l,y:d}}}else{let r=Math.min(...s.map(l=>l.x)),i=Math.max(...s.map(l=>l.x)),a=Math.min(...s.map(l=>l.y)),c=Math.max(...s.map(l=>l.y));if(n==="TD"){let l=o.y+3;return{x:o.x+1,y:l}}else{let l=o.x+3,d=o.y+1;return{x:l,y:d}}}}function si(t,e){let n=t.config.graphDirection;e.junctionPoint=ii(t,e);let o=e.junctionPoint;if(e.type==="fan-in"){e.junctionDir=n==="TD"?Z:tt,e.sharedNodeDir=n==="TD"?q:J;let s=e.sharedNode.gridCoord,r=n==="TD"?{x:s.x+1,y:s.y}:{x:s.x,y:s.y+1},i=ee(t.grid,o,r);e.sharedPath=i?Ut(i):[o,r];for(let a of e.edges){let c=a.from.gridCoord,l=n==="TD"?{x:c.x+1,y:c.y+2}:{x:c.x+2,y:c.y+1},d=ee(t.grid,l,o);a.pathToJunction=d?Ut(d):[l,o],a.startDir=n==="TD"?q:J,a.endDir=n==="TD"?Z:tt,a.path=[...a.pathToJunction,...e.sharedPath.slice(1)]}}else{e.junctionDir=n==="TD"?q:J,e.sharedNodeDir=n==="TD"?Z:tt;let s=e.sharedNode.gridCoord,r=n==="TD"?{x:s.x+1,y:s.y+2}:{x:s.x+2,y:s.y+1},i=ee(t.grid,r,o);e.sharedPath=i?Ut(i):[r,o];for(let a of e.edges){let c=a.to.gridCoord,l=n==="TD"?{x:c.x+1,y:c.y}:{x:c.x,y:c.y+1},d=ee(t.grid,o,l);a.pathToJunction=d?Ut(d):[o,l],a.startDir=n==="TD"?q:J,a.endDir=n==="TD"?Z:tt,a.path=[...e.sharedPath,...a.pathToJunction.slice(1)]}}}function Yn(t){for(let e of t.bundles)si(t,e)}function ht(t){return t.split(`
90`)}function ve(t){let e=ht(t);return Math.max(...e.map(n=>n.length),0)}function Oe(t){return ht(t).length}var Pn={rectangle:{unicode:{tl:"\u250C",tr:"\u2510",bl:"\u2514",br:"\u2518"},ascii:{tl:"+",tr:"+",bl:"+",br:"+"}},rounded:{unicode:{tl:"\u256D",tr:"\u256E",bl:"\u2570",br:"\u256F"},ascii:{tl:".",tr:".",bl:"'",br:"'"}},circle:{unicode:{tl:"\u25EF",tr:"\u25EF",bl:"\u25EF",br:"\u25EF"},ascii:{tl:"o",tr:"o",bl:"o",br:"o"}},doublecircle:{unicode:{tl:"\u25CE",tr:"\u25CE",bl:"\u25CE",br:"\u25CE"},ascii:{tl:"@",tr:"@",bl:"@",br:"@"}},diamond:{unicode:{tl:"\u25C7",tr:"\u25C7",bl:"\u25C7",br:"\u25C7"},ascii:{tl:"<",tr:">",bl:"<",br:">"}},hexagon:{unicode:{tl:"\u231C",tr:"\u231D",bl:"\u231E",br:"\u231F"},ascii:{tl:"*",tr:"*",bl:"*",br:"*"}},stadium:{unicode:{tl:"(",tr:")",bl:"(",br:")"},ascii:{tl:"(",tr:")",bl:"(",br:")"}},subroutine:{unicode:{tl:"\u255F",tr:"\u2562",bl:"\u255F",br:"\u2562"},ascii:{tl:"|",tr:"|",bl:"|",br:"|"}},cylinder:{unicode:{tl:"\u256D",tr:"\u256E",bl:"\u2570",br:"\u256F"},ascii:{tl:".",tr:".",bl:"'",br:"'"}},asymmetric:{unicode:{tl:"\u25B7",tr:"\u2510",bl:"\u25B7",br:"\u2518"},ascii:{tl:">",tr:"+",bl:">",br:"+"}},trapezoid:{unicode:{tl:"/",tr:"\\",bl:"\u2514",br:"\u2518"},ascii:{tl:"/",tr:"\\",bl:"+",br:"+"}},"trapezoid-alt":{unicode:{tl:"\u250C",tr:"\u2510",bl:"\\",br:"/"},ascii:{tl:"+",tr:"+",bl:"\\",br:"/"}},"state-start":{unicode:{tl:"\u25CF",tr:"\u25CF",bl:"\u25CF",br:"\u25CF"},ascii:{tl:"*",tr:"*",bl:"*",br:"*"}},"state-end":{unicode:{tl:"\u25C9",tr:"\u25C9",bl:"\u25C9",br:"\u25C9"},ascii:{tl:"@",tr:"@",bl:"@",br:"@"}}};function Rt(t,e){let n=Pn[t]??Pn.rectangle;return e?n.ascii:n.unicode}function Et(t,e){let n=ht(t),o=Math.max(...n.map(d=>d.length),0),s=n.length,r=2*e.padding+o,i=r+2,a=s+2*e.padding,c=a%2===0?a+1:a,l=c+2;return{width:i,height:l,labelArea:{x:1+e.padding,y:1+e.padding,width:o,height:s},gridColumns:[1,r,1],gridRows:[1,c,1]}}function Yt(t,e,n,o){let{width:s,height:r}=e,i=gt(s-1,r-1),a={x:0,y:0},c={x:s-1,y:r-1},l=o?"-":"\u2500",d=o?"|":"\u2502";for(let $=a.x+1;$<c.x;$++)i[$][a.y]=l,i[$][c.y]=l;for(let $=a.y+1;$<c.y;$++)i[a.x][$]=d,i[c.x][$]=d;i[a.x][a.y]=n.tl,i[c.x][a.y]=n.tr,i[a.x][c.y]=n.bl,i[c.x][c.y]=n.br;let h=ht(t),f=s-1,u=r-1,p=Math.floor(u/2)-Math.floor((h.length-1)/2);for(let $=0;$<h.length;$++){let A=h[$],X=Math.floor(f/2)-Math.ceil(A.length/2)+1;for(let v=0;v<A.length;v++){let Y=X+v,D=p+$;Y>=0&&Y<i.length&&D>=0&&D<i[0].length&&(i[Y][D]=A[v])}}return i}function Ct(t,e,n){let{width:o,height:s}=e,r=n.x+Math.floor(o/2),i=n.y+Math.floor(s/2);return b(t,Z)?{x:r,y:n.y}:b(t,q)?{x:r,y:n.y+s-1}:b(t,tt)?{x:n.x,y:i}:b(t,J)?{x:n.x+o-1,y:i}:b(t,Lt)?{x:n.x,y:n.y}:b(t,Tt)?{x:n.x+o-1,y:n.y}:b(t,It)?{x:n.x,y:n.y+s-1}:b(t,Ht)?{x:n.x+o-1,y:n.y+s-1}:{x:r,y:i}}var je={getDimensions:Et,render(t,e,n){let o=Rt("rectangle",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var Xn={getDimensions:Et,render(t,e,n){let o=Rt("diamond",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var Hn={getDimensions:Et,render(t,e,n){let o=Rt("circle",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var Gn={getDimensions(t,e){return{width:5,height:3,labelArea:{x:2,y:1,width:1,height:1},gridColumns:[1,3,1],gridRows:[1,1,1]}},render(t,e,n){let{width:o,height:s}=e,r=gt(o-1,s-1),i=Math.floor(o/2);return n.useAscii?(r[0][0]=".",r[1][0]="-",r[2][0]="-",r[3][0]="-",r[4][0]=".",r[0][1]="|",r[i][1]="*",r[4][1]="|",r[0][2]="'",r[1][2]="-",r[2][2]="-",r[3][2]="-",r[4][2]="'"):(r[0][0]="\u256D",r[1][0]="\u2500",r[2][0]="\u2500",r[3][0]="\u2500",r[4][0]="\u256E",r[0][1]="\u2502",r[i][1]="\u25CF",r[4][1]="\u2502",r[0][2]="\u2570",r[1][2]="\u2500",r[2][2]="\u2500",r[3][2]="\u2500",r[4][2]="\u256F"),r},getAttachmentPoint(t,e,n){let{width:o,height:s}=e,r=n.x+Math.floor(o/2),i=n.y+Math.floor(s/2);return b(t,Z)?{x:r,y:n.y}:b(t,q)?{x:r,y:n.y+s-1}:b(t,tt)?{x:n.x,y:i}:b(t,J)?{x:n.x+o-1,y:i}:{x:r,y:i}}},Wn={getDimensions(t,e){return{width:5,height:3,labelArea:{x:2,y:1,width:1,height:1},gridColumns:[1,3,1],gridRows:[1,1,1]}},render(t,e,n){let{width:o,height:s}=e,r=gt(o-1,s-1),i=Math.floor(o/2);return n.useAscii?(r[0][0]="#",r[1][0]="=",r[2][0]="=",r[3][0]="=",r[4][0]="#",r[0][1]="#",r[i][1]="*",r[4][1]="#",r[0][2]="#",r[1][2]="=",r[2][2]="=",r[3][2]="=",r[4][2]="#"):(r[0][0]="\u2554",r[1][0]="\u2550",r[2][0]="\u2550",r[3][0]="\u2550",r[4][0]="\u2557",r[0][1]="\u2551",r[i][1]="\u25CE",r[4][1]="\u2551",r[0][2]="\u255A",r[1][2]="\u2550",r[2][2]="\u2550",r[3][2]="\u2550",r[4][2]="\u255D"),r},getAttachmentPoint(t,e,n){let{width:o,height:s}=e,r=n.x+Math.floor(o/2),i=n.y+Math.floor(s/2);return b(t,Z)?{x:r,y:n.y}:b(t,q)?{x:r,y:n.y+s-1}:b(t,tt)?{x:n.x,y:i}:b(t,J)?{x:n.x+o-1,y:i}:{x:r,y:i}}};var Nn={getDimensions:Et,render(t,e,n){let o=Rt("rounded",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var Bn={getDimensions(t,e){let n=ht(t),o=Math.max(...n.map(l=>l.length),0),s=n.length,r=2*e.padding+o,i=r+4,a=s+2*e.padding,c=Math.max(a+2,3);return{width:i,height:c,labelArea:{x:2+e.padding,y:1+e.padding,width:o,height:s},gridColumns:[2,r,2],gridRows:[1,a,1]}},render(t,e,n){let{width:o,height:s}=e,r=gt(o-1,s-1),i=Math.floor(s/2),a=n.useAscii?"-":"\u2500";if(s===3)r[0][i]="(",r[o-1][i]=")";else if(n.useAscii){for(let d=0;d<s;d++)r[0][d]="(",r[o-1][d]=")";for(let d=1;d<o-1;d++)r[d][0]=a,r[d][s-1]=a}else{r[0][0]="\u256D";for(let d=1;d<o-1;d++)r[d][0]=a;r[o-1][0]="\u256E";for(let d=1;d<s-1;d++)r[0][d]="\u2502",r[o-1][d]="\u2502";r[0][s-1]="\u2570";for(let d=1;d<o-1;d++)r[d][s-1]=a;r[o-1][s-1]="\u256F"}let c=ht(t),l=i-Math.floor((c.length-1)/2);for(let d=0;d<c.length;d++){let h=c[d],f=Math.floor(o/2)-Math.floor(h.length/2);for(let u=0;u<h.length;u++){let g=f+u,p=l+d;g>0&&g<o-1&&p>=0&&p<s&&(r[g][p]=h[u])}}return r},getAttachmentPoint:Ct};var _n={getDimensions:Et,render(t,e,n){let o=Rt("hexagon",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var zn={getDimensions(t,e){let n=ht(t),o=Math.max(...n.map(l=>l.length),0),s=n.length,r=2*e.padding+o,i=r+4,a=s+2*e.padding,c=a+2;return{width:i,height:c,labelArea:{x:2+e.padding,y:1+e.padding,width:o,height:s},gridColumns:[2,r,2],gridRows:[1,a,1]}},render(t,e,n){let{width:o,height:s}=e,r=gt(o-1,s-1),i=n.useAscii?"-":"\u2500",a=n.useAscii?"|":"\u2502";r[0][0]=n.useAscii?"+":"\u250C",r[1][0]=n.useAscii?"+":"\u252C";for(let h=2;h<o-2;h++)r[h][0]=i;r[o-2][0]=n.useAscii?"+":"\u252C",r[o-1][0]=n.useAscii?"+":"\u2510";for(let h=1;h<s-1;h++)r[0][h]=a,r[1][h]=a,r[o-2][h]=a,r[o-1][h]=a;r[0][s-1]=n.useAscii?"+":"\u2514",r[1][s-1]=n.useAscii?"+":"\u2534";for(let h=2;h<o-2;h++)r[h][s-1]=i;r[o-2][s-1]=n.useAscii?"+":"\u2534",r[o-1][s-1]=n.useAscii?"+":"\u2518";let c=ht(t),d=Math.floor(s/2)-Math.floor((c.length-1)/2);for(let h=0;h<c.length;h++){let f=c[h],u=Math.floor(o/2)-Math.floor(f.length/2);for(let g=0;g<f.length;g++){let p=u+g,$=d+h;p>1&&p<o-2&&$>0&&$<s-1&&(r[p][$]=f[g])}}return r},getAttachmentPoint:Ct},On={getDimensions:Et,render(t,e,n){let o=Rt("doublecircle",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct},jn={getDimensions(t,e){let n=ht(t),o=Math.max(...n.map(l=>l.length),0),s=n.length,r=2*e.padding+o,i=r+2,a=s+2*e.padding+2,c=a+2;return{width:i,height:c,labelArea:{x:1+e.padding,y:2+e.padding,width:o,height:s},gridColumns:[1,r,1],gridRows:[2,a-2,2]}},render(t,e,n){let{width:o,height:s}=e,r=gt(o-1,s-1),i=n.useAscii?"-":"\u2500",a=n.useAscii?"|":"\u2502";r[0][0]=n.useAscii?".":"\u256D";for(let h=1;h<o-1;h++)r[h][0]=i;r[o-1][0]=n.useAscii?".":"\u256E",r[0][1]=a;for(let h=1;h<o-1;h++)r[h][1]=i;r[o-1][1]=a;for(let h=2;h<s-2;h++)r[0][h]=a,r[o-1][h]=a;r[0][s-2]=a;for(let h=1;h<o-1;h++)r[h][s-2]=i;r[o-1][s-2]=a,r[0][s-1]=n.useAscii?"'":"\u2570";for(let h=1;h<o-1;h++)r[h][s-1]=i;r[o-1][s-1]=n.useAscii?"'":"\u256F";let c=ht(t),d=Math.floor(s/2)-Math.floor((c.length-1)/2);for(let h=0;h<c.length;h++){let f=c[h],u=Math.floor(o/2)-Math.floor(f.length/2);for(let g=0;g<f.length;g++){let p=u+g,$=d+h;p>0&&p<o-1&&$>1&&$<s-2&&(r[p][$]=f[g])}}return r},getAttachmentPoint:Ct},Fn={getDimensions:Et,render(t,e,n){let o=Rt("asymmetric",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct},qn={getDimensions:Et,render(t,e,n){let o=Rt("trapezoid",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct},Un={getDimensions:Et,render(t,e,n){let o=Rt("trapezoid-alt",n.useAscii);return Yt(t,e,o,n.useAscii)},getAttachmentPoint:Ct};var ai=new Map([["rectangle",je],["rounded",Nn],["diamond",Xn],["stadium",Bn],["circle",Hn],["subroutine",zn],["doublecircle",On],["hexagon",_n],["cylinder",jn],["asymmetric",Fn],["trapezoid",qn],["trapezoid-alt",Un],["state-start",Gn],["state-end",Wn]]);function Jn(t){return ai.get(t)??je}function Vn(t,e,n){return Jn(t).getDimensions(e,n)}function Kn(t,e,n,o){return Jn(t).getAttachmentPoint(e,n,o)}function ci(t,e){return li(t,e)}function li(t,e){let n=t.gridCoord,o=e.config.useAscii,s=0;for(let v=0;v<2;v++)s+=e.columnWidth.get(n.x+v)??0;let r=0;for(let v=0;v<2;v++)r+=e.rowHeight.get(n.y+v)??0;let i={x:0,y:0},a={x:s,y:r},c=gt(Math.max(i.x,a.x),Math.max(i.y,a.y)),l=Rt(t.shape,o),d=t.shape==="state-end",h=o?d?"=":"-":d?"\u2550":"\u2500",f=o?d?"\u2016":"|":d?"\u2551":"\u2502",g=d?o?{tl:"#",tr:"#",bl:"#",br:"#"}:{tl:"\u2554",tr:"\u2557",bl:"\u255A",br:"\u255D"}:l;for(let v=i.x+1;v<a.x;v++)c[v][i.y]=h;for(let v=i.x+1;v<a.x;v++)c[v][a.y]=h;for(let v=i.y+1;v<a.y;v++)c[i.x][v]=f;for(let v=i.y+1;v<a.y;v++)c[a.x][v]=f;c[i.x][i.y]=g.tl,c[a.x][i.y]=g.tr,c[i.x][a.y]=g.bl,c[a.x][a.y]=g.br;let p=t.displayLabel,$=ht(p),X=i.y+Math.floor(r/2)-Math.floor(($.length-1)/2);for(let v=0;v<$.length;v++){let Y=$[v],D=i.x+Math.floor(s/2)-Math.ceil(Y.length/2)+1;for(let V=0;V<Y.length;V++)D+V>=0&&D+V<c.length&&X+v>=0&&X+v<c[0].length&&(c[D+V][X+v]=Y[V])}return c}function Zn(t,e){return ci(t,e)}function Se(t,e,n=1){let o=0;for(let v of t)for(let Y of v)o=Math.max(o,Y.length);let r=o+2*n+2,i=0;for(let v of t)i+=Math.max(v.length,1);let a=t.length-1,c=i+a+2,l=e?"-":"\u2500",d=e?"|":"\u2502",h=e?"+":"\u250C",f=e?"+":"\u2510",u=e?"+":"\u2514",g=e?"+":"\u2518",p=e?"+":"\u251C",$=e?"+":"\u2524",A=gt(r-1,c-1);A[0][0]=h;for(let v=1;v<r-1;v++)A[v][0]=l;A[r-1][0]=f,A[0][c-1]=u;for(let v=1;v<r-1;v++)A[v][c-1]=l;A[r-1][c-1]=g;for(let v=1;v<c-1;v++)A[0][v]=d,A[r-1][v]=d;let X=1;for(let v=0;v<t.length;v++){let Y=t[v],D=Y.length>0?Y:[""];for(let V of D){let ft=1+n;for(let j=0;j<V.length;j++)A[ft+j][X]=V[j];X++}if(v<t.length-1){A[0][X]=p;for(let V=1;V<r-1;V++)A[V][X]=l;A[r-1][X]=$,X++}}return A}var di={solid:{h:{unicode:"\u2500",ascii:"-"},v:{unicode:"\u2502",ascii:"|"}},dotted:{h:{unicode:"\u2504",ascii:"."},v:{unicode:"\u2506",ascii:":"}},thick:{h:{unicode:"\u2501",ascii:"="},v:{unicode:"\u2503",ascii:"\u2016"}}};function qe(t,e,n,o,s,r,i="solid"){let a=St(e,n),c=[],l=di[i],d=r?l.h.ascii:l.h.unicode,h=r?l.v.ascii:l.v.unicode;if(b(a,Z))for(let f=e.y-o;f>=n.y-s;f--)c.push({x:e.x,y:f}),t[e.x][f]=h;else if(b(a,q))for(let f=e.y+o;f<=n.y+s;f++)c.push({x:e.x,y:f}),t[e.x][f]=h;else if(b(a,tt))for(let f=e.x-o;f>=n.x-s;f--)c.push({x:f,y:e.y}),t[f][e.y]=d;else if(b(a,J))for(let f=e.x+o;f<=n.x+s;f++)c.push({x:f,y:e.y}),t[f][e.y]=d;else if(b(a,Lt)){for(let f=e.x-o;f>=n.x;f--)c.push({x:f,y:e.y}),t[f][e.y]=d;for(let f=e.y-1;f>=n.y-s;f--)c.push({x:n.x,y:f}),t[n.x][f]=h}else if(b(a,Tt)){for(let f=e.x+o;f<=n.x;f++)c.push({x:f,y:e.y}),t[f][e.y]=d;for(let f=e.y-1;f>=n.y-s;f--)c.push({x:n.x,y:f}),t[n.x][f]=h}else if(b(a,It)){for(let f=e.x-o;f>=n.x;f--)c.push({x:f,y:e.y}),t[f][e.y]=d;for(let f=e.y+1;f<=n.y+s;f++)c.push({x:n.x,y:f}),t[n.x][f]=h}else if(b(a,Ht))if(n.x-e.x<=1)for(let u=e.y+o;u<=n.y+s;u++)c.push({x:e.x,y:u}),t[e.x][u]=h;else{for(let u=e.x+o;u<=n.x;u++)c.push({x:u,y:e.y}),t[u][e.y]=d;for(let u=e.y+1;u<=n.y+s;u++)c.push({x:n.x,y:u}),t[n.x][u]=h}return c}function fi(t,e){if(e.path.length===0){let d=$t(t.canvas);return[d,d,d,d,d,d]}let n=pi(t,e),[o,s,r]=hi(t,e.path,e.style),i=gi(t,e.path,s[0],e.from.shape),a;e.hasArrowEnd?a=Qn(t,s[s.length-1],r[r.length-1]):a=$t(t.canvas);let c;if(e.hasArrowStart&&s.length>0){let h=s[0][0],f=ui(r[0]),u={x:h.x,y:h.y};b(r[0],J)?u.x=h.x-1:b(r[0],tt)?u.x=h.x+1:b(r[0],q)?u.y=h.y-1:b(r[0],Z)&&(u.y=h.y+1),c=Qn(t,[h,u],f)}else c=$t(t.canvas);let l=mi(t,e.path);return[o,i,a,c,l,n]}function ui(t){return b(t,Z)?q:b(t,q)?Z:b(t,tt)?J:b(t,J)?tt:b(t,Lt)?Ht:b(t,Tt)?It:b(t,It)?Tt:b(t,Ht)?Lt:jt}function hi(t,e,n="solid"){let o=$t(t.canvas),s=e[0],r=[],i=[];for(let a=1;a<e.length;a++){let c=e[a],l=Ot(t,s),d=Ot(t,c);if(ye(l,d)){s=c;continue}let h=St(s,c),f=qe(o,l,d,1,-1,t.config.useAscii,n);f.length===0&&f.push(l),r.push(f),i.push(h),s=c}return[o,r,i]}function gi(t,e,n,o){let s=$t(t.canvas);if(t.config.useAscii||o==="state-start"||o==="state-end")return s;let r=n[0],i=St(e[0],e[1]);return b(i,Z)?s[r.x][r.y+1]="\u2534":b(i,q)?s[r.x][r.y-1]="\u252C":b(i,tt)?s[r.x+1][r.y]="\u2524":b(i,J)&&(s[r.x-1][r.y]="\u251C"),s}function Qn(t,e,n){let o=$t(t.canvas);if(e.length===0)return o;let s=e[0],r=e[e.length-1],i=St(s,r);(e.length===1||b(i,jt))&&(i=n);let a;return t.config.useAscii?b(i,Z)?a="^":b(i,q)?a="v":b(i,tt)?a="<":b(i,J)?a=">":b(n,Z)?a="^":b(n,q)?a="v":b(n,tt)?a="<":b(n,J)?a=">":a="*":b(i,Z)?a="\u25B2":b(i,q)?a="\u25BC":b(i,tt)?a="\u25C4":b(i,J)?a="\u25BA":b(i,Tt)?a="\u25E5":b(i,Lt)?a="\u25E4":b(i,Ht)?a="\u25E2":b(i,It)?a="\u25E3":b(n,Z)?a="\u25B2":b(n,q)?a="\u25BC":b(n,tt)?a="\u25C4":b(n,J)?a="\u25BA":b(n,Tt)?a="\u25E5":b(n,Lt)?a="\u25E4":b(n,Ht)?a="\u25E2":b(n,It)?a="\u25E3":a="\u25CF",o[r.x][r.y]=a,o}function mi(t,e){let n=$t(t.canvas);for(let o=1;o<e.length-1;o++){let s=e[o],r=Ot(t,s),i=St(e[o-1],s),a=St(s,e[o+1]),c;t.config.useAscii?c="+":b(i,J)&&b(a,q)||b(i,Z)&&b(a,tt)?c="\u2510":b(i,J)&&b(a,Z)||b(i,q)&&b(a,tt)?c="\u2518":b(i,tt)&&b(a,q)||b(i,Z)&&b(a,J)?c="\u250C":b(i,tt)&&b(a,Z)||b(i,q)&&b(a,J)?c="\u2514":c="+",n[r.x][r.y]=c}return n}function pi(t,e){let n=$t(t.canvas);if(e.text.length===0)return n;let o=er(t,e.labelLine),s;if(e.path.length>=2){let r=e.path[0].y,i=e.path[e.path.length-1].y;i<r?s=!0:i>r&&(s=!1)}return xi(n,o,e.text,s),n}function xi(t,e,n,o){if(e.length<2)return;let s=Math.min(e[0].x,e[1].x),r=Math.max(e[0].x,e[1].x),i=Math.min(e[0].y,e[1].y),a=Math.max(e[0].y,e[1].y),c=s+Math.floor((r-s)/2),l=i+Math.floor((a-i)/2);if(o!==void 0&&s===r){let f=a-i,u=Math.max(1,Math.floor(f/4));o?l=l+u:l=l-u}let d=ht(n),h=l-Math.floor((d.length-1)/2);for(let f=0;f<d.length;f++){let u=d[f],g=c-Math.floor(u.length/2);Be(t,{x:g,y:h+f},u)}}function ce(t,e,n){let o=e.gridCoord,s=0;for(let c=0;c<2;c++)s+=t.columnWidth.get(o.x+c)??0;let r=0;for(let c=0;c<2;c++)r+=t.rowHeight.get(o.y+c)??0;let i={width:s+1,height:r+1,labelArea:{x:0,y:0,width:0,height:0},gridColumns:[0,0,0],gridRows:[0,0,0]},a=e.drawingCoord;return Kn(e.shape,n,i,a)}function bi(t,e,n){let o=$t(t.canvas);if(!e.pathToJunction||e.pathToJunction.length===0)return[o,o,o,o,o,o];let s=$t(t.canvas),r=t.config.useAscii,i=e.pathToJunction.map((d,h)=>n.type==="fan-in"&&h===0?ce(t,e.from,e.startDir):n.type==="fan-out"&&h===e.pathToJunction.length-1?ce(t,e.to,e.endDir):Ot(t,d));for(let d=1;d<i.length;d++){let h=i[d-1],f=i[d];ye(h,f)||qe(s,h,f,1,-1,r,e.style)}let a=$t(t.canvas);for(let d=1;d<e.pathToJunction.length-1;d++){let h=e.pathToJunction[d],f=Ot(t,h),u=St(e.pathToJunction[d-1],h),g=St(h,e.pathToJunction[d+1]),p;r?p="+":b(u,J)&&b(g,q)||b(u,Z)&&b(g,tt)?p="\u2510":b(u,J)&&b(g,Z)||b(u,q)&&b(g,tt)?p="\u2518":b(u,tt)&&b(g,q)||b(u,Z)&&b(g,J)?p="\u250C":b(u,tt)&&b(g,Z)||b(u,q)&&b(g,J)?p="\u2514":p="+",a[f.x][f.y]=p}let c=$t(t.canvas);if(n.type==="fan-in"&&e.pathToJunction.length>=2){let d=i[0],h=St(e.pathToJunction[0],e.pathToJunction[1]);r||(b(h,Z)?c[d.x][d.y]="\u2534":b(h,q)?c[d.x][d.y]="\u252C":b(h,tt)?c[d.x][d.y]="\u2524":b(h,J)&&(c[d.x][d.y]="\u251C"))}let l=$t(t.canvas);return[s,c,o,o,a,l]}function yi(t,e){let n=$t(t.canvas),o=$t(t.canvas);if(e.sharedPath.length<2)return[n,o];let s=t.config.useAscii,r=e.edges[0]?.style??"solid",i=t.config.graphDirection,a=e.sharedPath.map((c,l)=>{if(e.type==="fan-in"&&l===e.sharedPath.length-1){let d=i==="TD"?Z:tt;return ce(t,e.sharedNode,d)}if(e.type==="fan-out"&&l===0){let d=i==="TD"?q:J;return ce(t,e.sharedNode,d)}return Ot(t,c)});for(let c=1;c<a.length;c++){let l=a[c-1],d=a[c];ye(l,d)||qe(n,l,d,1,-1,s,r)}for(let c=1;c<e.sharedPath.length-1;c++){let l=e.sharedPath[c],d=Ot(t,l),h=St(e.sharedPath[c-1],l),f=St(l,e.sharedPath[c+1]),u;s?u="+":b(h,J)&&b(f,q)||b(h,Z)&&b(f,tt)?u="\u2510":b(h,J)&&b(f,Z)||b(h,q)&&b(f,tt)?u="\u2518":b(h,tt)&&b(f,q)||b(h,Z)&&b(f,J)?u="\u250C":b(h,tt)&&b(f,Z)||b(h,q)&&b(f,J)?u="\u2514":u="+",o[d.x][d.y]=u}return[n,o]}function $i(t,e){let n=$t(t.canvas);if(e.sharedPath.length<2)return n;let o=e.sharedPath.length-1,s=e.sharedPath[o-1],r=e.sharedPath[o],i=St(s,r),a=t.config.graphDirection,c=a==="TD"?Z:tt,l=ce(t,e.sharedNode,c);a==="TD"?l.y-=1:l.x-=1;let d;return t.config.useAscii?b(i,Z)?d="^":b(i,q)?d="v":b(i,tt)?d="<":b(i,J)?d=">":d="v":b(i,Z)?d="\u25B2":b(i,q)?d="\u25BC":b(i,tt)?d="\u25C4":b(i,J)?d="\u25BA":d="\u25BC",n[l.x][l.y]=d,n}function Ci(t,e){let n=$t(t.canvas);if(!e.pathToJunction||e.pathToJunction.length<2)return n;let o=e.pathToJunction.length-1,s=e.pathToJunction[o-1],r=e.pathToJunction[o],i=St(s,r),a=t.config.graphDirection,c=a==="TD"?Z:tt,l=ce(t,e.to,c);a==="TD"?l.y-=1:l.x-=1;let d;return t.config.useAscii?b(i,Z)?d="^":b(i,q)?d="v":b(i,tt)?d="<":b(i,J)?d=">":d="v":b(i,Z)?d="\u25B2":b(i,q)?d="\u25BC":b(i,tt)?d="\u25C4":b(i,J)?d="\u25BA":d="\u25BC",n[l.x][l.y]=d,n}function wi(t,e){let n=$t(t.canvas);if(!e.junctionPoint)return n;let o=Ot(t,e.junctionPoint),s=t.config.useAscii,r=!1,i=!1,a=!1,c=!1;if(e.sharedPath.length>=2){let d=e.type==="fan-in"?0:e.sharedPath.length-1,h=e.type==="fan-in"?1:e.sharedPath.length-2,f=St(e.sharedPath[d],e.sharedPath[h]);b(f,q)?i=!0:b(f,Z)?r=!0:b(f,J)?c=!0:b(f,tt)&&(a=!0)}for(let d of e.edges)if(d.pathToJunction&&d.pathToJunction.length>=2){let h=e.type==="fan-in"?d.pathToJunction.length-1:0,f=e.type==="fan-in"?d.pathToJunction.length-2:1,u=St(d.pathToJunction[f],d.pathToJunction[h]);b(u,q)?r=!0:b(u,Z)?i=!0:b(u,J)?a=!0:b(u,tt)&&(c=!0)}let l;return s?l="+":r&&i&&a&&c?l="\u253C":i&&a&&c&&!r?l="\u252C":r&&a&&c&&!i?l="\u2534":r&&i&&c&&!a?l="\u251C":r&&i&&a&&!c?l="\u2524":a&&c?l="\u2500":r&&i?l="\u2502":i&&c?l="\u250C":i&&a?l="\u2510":r&&c?l="\u2514":r&&a?l="\u2518":l="\u253C",n[o.x][o.y]=l,n}function Mi(t,e){let n=t.maxX-t.minX,o=t.maxY-t.minY;if(n<=0||o<=0)return gt(0,0);let s={x:0,y:0},r={x:n,y:o},i=gt(n,o);if(e.config.useAscii){for(let a=s.x+1;a<r.x;a++)i[a][s.y]="-";for(let a=s.x+1;a<r.x;a++)i[a][r.y]="-";for(let a=s.y+1;a<r.y;a++)i[s.x][a]="|";for(let a=s.y+1;a<r.y;a++)i[r.x][a]="|";i[s.x][s.y]="+",i[r.x][s.y]="+",i[s.x][r.y]="+",i[r.x][r.y]="+"}else{for(let a=s.x+1;a<r.x;a++)i[a][s.y]="\u2500";for(let a=s.x+1;a<r.x;a++)i[a][r.y]="\u2500";for(let a=s.y+1;a<r.y;a++)i[s.x][a]="\u2502";for(let a=s.y+1;a<r.y;a++)i[r.x][a]="\u2502";i[s.x][s.y]="\u250C",i[r.x][s.y]="\u2510",i[s.x][r.y]="\u2514",i[r.x][r.y]="\u2518"}return i}function Ai(t,e){let n=t.maxX-t.minX,o=t.maxY-t.minY;if(n<=0||o<=0)return[gt(0,0),{x:0,y:0}];let s=gt(n,o),r=ht(t.name);for(let i=0;i<r.length;i++){let a=r[i],c=1+i,l=Math.floor(n/2)-Math.floor(a.length/2);l<1&&(l=1);for(let d=0;d<a.length;d++)l+d<n&&c<o&&(s[l+d][c]=a[d])}return[s,{x:t.minX,y:t.minY}]}function vi(t){function e(o){return o.parent===null?0:1+e(o.parent)}let n=[...t];return n.sort((o,s)=>e(o)-e(s)),n}function Fe(t,e,n,o){for(let s=0;s<e.length;s++)for(let r=0;r<(e[0]?.length??0);r++){let i=e[s]?.[r];if(i&&i!==" "){let a=s+n.x,c=r+n.y;a>=0&&c>=0&&Vt(t,a,c,o)}}}function re(t,e,n,o){for(let s of e)Fe(t,s,n,o)}function Si(t,e,n){let o=s=>/^[┌┐└┘├┤┬┴┼│─╭╮╰╯+\-|.':]$/.test(s);for(let s=0;s<e.length;s++)for(let r=0;r<(e[0]?.length??0);r++){let i=e[s]?.[r];if(i&&i!==" "){let a=s+n.x,c=r+n.y;a>=0&&c>=0&&Vt(t,a,c,o(i)?"border":"text")}}}function tr(t){let e=t.config.useAscii,n={x:0,y:0},o=vi(t.subgraphs);for(let f of o){let u=Mi(f,t),g={x:f.minX,y:f.minY};t.canvas=zt(t.canvas,g,e,u),Fe(t.roleCanvas,u,g,"border")}for(let f of t.nodes)!f.drawn&&f.drawingCoord&&f.drawing&&(t.canvas=zt(t.canvas,f.drawingCoord,e,f.drawing),Si(t.roleCanvas,f.drawing,f.drawingCoord),f.drawn=!0);let s=[],r=[],i=[],a=[],c=[],l=[],d=[],h=new Set;for(let f of t.edges)if(f.bundle&&f.pathToJunction){let u=f.bundle,[g,p,,,$,A]=bi(t,f,u);if(s.push(g),r.push($),c.push(p),l.push(A),!h.has(u)){h.add(u);let[X,v]=yi(t,u);if(s.push(X),r.push(v),u.type==="fan-in"){let D=$i(t,u);i.push(D)}let Y=wi(t,u);d.push(Y)}if(u.type==="fan-out"&&f.hasArrowEnd){let X=Ci(t,f);i.push(X)}}else{let[u,g,p,$,A,X]=fi(t,f);s.push(u),r.push(A),i.push(p),a.push($),c.push(g),l.push(X)}t.canvas=zt(t.canvas,n,e,...s),re(t.roleCanvas,s,n,"line"),t.canvas=zt(t.canvas,n,e,...r),re(t.roleCanvas,r,n,"corner"),t.canvas=zt(t.canvas,n,e,...d),re(t.roleCanvas,d,n,"junction"),t.canvas=zt(t.canvas,n,e,...i),re(t.roleCanvas,i,n,"arrow"),t.canvas=zt(t.canvas,n,e,...c),re(t.roleCanvas,c,n,"junction"),t.canvas=zt(t.canvas,n,e,...a),re(t.roleCanvas,a,n,"arrow"),t.canvas=zt(t.canvas,n,e,...l),re(t.roleCanvas,l,n,"text");for(let f of t.subgraphs){if(f.nodes.length===0)continue;let[u,g]=Ai(f,t);t.canvas=zt(t.canvas,g,e,u),Fe(t.roleCanvas,u,g,"text")}return t.canvas}function Ot(t,e,n){let o=n?{x:e.x+n.x,y:e.y+n.y}:e,s=0;for(let c=0;c<o.x;c++)s+=t.columnWidth.get(c)??0;let r=0;for(let c=0;c<o.y;c++)r+=t.rowHeight.get(c)??0;let i=t.columnWidth.get(o.x)??0,a=t.rowHeight.get(o.y)??0;return{x:s+Math.floor(i/2)+t.offsetX,y:r+Math.floor(a/2)+t.offsetY}}function er(t,e){return e.map(n=>Ot(t,n))}function ge(t,e,n,o){let s=o??ki(t,e);if(t.grid.has(Ft(n)))return s==="LR"?ge(t,e,{x:n.x,y:n.y+4},s):ge(t,e,{x:n.x+4,y:n.y},s);for(let r=0;r<3;r++)for(let i=0;i<3;i++){let a={x:n.x+r,y:n.y+i};t.grid.set(Ft(a),e)}return e.gridCoord=n,n}function Ri(t,e){let n=e.gridCoord,o=t.config.boxBorderPadding,s=Vn(e.shape,e.displayLabel,{useAscii:t.config.useAscii,padding:o}),r=s.gridColumns,i=s.gridRows;for(let a=0;a<r.length;a++){let c=n.x+a,l=t.columnWidth.get(c)??0;t.columnWidth.set(c,Math.max(l,r[a]))}for(let a=0;a<i.length;a++){let c=n.y+a,l=t.rowHeight.get(c)??0;t.rowHeight.set(c,Math.max(l,i[a]))}if(n.x>0){let a=t.columnWidth.get(n.x-1)??0;t.columnWidth.set(n.x-1,Math.max(a,t.config.paddingX))}if(n.y>0){let a=t.config.paddingY;Li(t,e)&&(a+=4);let c=t.rowHeight.get(n.y-1)??0;t.rowHeight.set(n.y-1,Math.max(c,a))}}function nr(t,e){for(let n of e)t.columnWidth.has(n.x)||t.columnWidth.set(n.x,Math.floor(t.config.paddingX/2)),t.rowHeight.has(n.y)||t.rowHeight.set(n.y,Math.floor(t.config.paddingY/2))}function Ue(t,e){return t.subgraphs.some(n=>n.nodes.includes(e))}function kt(t,e){let n=null;for(let o of t.subgraphs)o.nodes.includes(e)&&(!n||Di(n,o))&&(n=o);return n}function Di(t,e){let n=e;for(;n!==null;){if(n===t)return!0;n=n.parent}return!1}function ki(t,e){let n=kt(t,e);return n?.direction?n.direction:t.config.graphDirection}function Li(t,e){let n=kt(t,e);if(!n)return!1;let o=!1;for(let s of t.edges)if(s.to===e&&kt(t,s.from)!==n){o=!0;break}if(!o)return!1;for(let s of n.nodes){if(s===e||!s.gridCoord)continue;let r=!1;for(let i of t.edges)if(i.to===s&&kt(t,i.from)!==n){r=!0;break}if(r&&s.gridCoord.y<e.gridCoord.y)return!1}return!0}function rr(t,e){if(e.nodes.length===0)return;let n=1e6,o=1e6,s=-1e6,r=-1e6;for(let c of e.children)rr(t,c),c.nodes.length>0&&(n=Math.min(n,c.minX),o=Math.min(o,c.minY),s=Math.max(s,c.maxX),r=Math.max(r,c.maxY));for(let c of e.nodes){if(!c.drawingCoord||!c.drawing)continue;let l=c.drawingCoord.x,d=c.drawingCoord.y,h=l+c.drawing.length-1,f=d+c.drawing[0].length-1;n=Math.min(n,l),o=Math.min(o,d),s=Math.max(s,h),r=Math.max(r,f)}let i=2,a=2;e.minX=n-i,e.minY=o-i-a,e.maxX=s+i,e.maxY=r+i}function Ti(t){let n=t.subgraphs.filter(o=>o.parent===null&&o.nodes.length>0);for(let o=0;o<n.length;o++)for(let s=o+1;s<n.length;s++){let r=n[o],i=n[s];r.minX<i.maxX&&r.maxX>i.minX&&(r.maxY>=i.minY-1&&r.minY<i.minY?i.minY=r.maxY+1+1:i.maxY>=r.minY-1&&i.minY<r.minY&&(r.minY=i.maxY+1+1)),r.minY<i.maxY&&r.maxY>i.minY&&(r.maxX>=i.minX-1&&r.minX<i.minX?i.minX=r.maxX+1+1:i.maxX>=r.minX-1&&i.minX<r.minX&&(r.minX=i.maxX+1+1))}}function Ii(t){for(let e of t.subgraphs)rr(t,e);Ti(t)}function Ei(t){if(t.subgraphs.length===0)return;let e=0,n=0;for(let r of t.subgraphs)e=Math.min(e,r.minX),n=Math.min(n,r.minY);let o=-e,s=-n;if(!(o===0&&s===0)){t.offsetX=o,t.offsetY=s;for(let r of t.subgraphs)r.minX+=o,r.minY+=s,r.maxX+=o,r.maxY+=s;for(let r of t.nodes)r.drawingCoord&&(r.drawingCoord.x+=o,r.drawingCoord.y+=s)}}function or(t){let e=t.config.graphDirection,n=new Array(100).fill(0),o=new Set,s=[];for(let f of t.nodes){o.has(f.name)||s.push(f),o.add(f.name);for(let u of Je(t,f))o.add(u.name)}let r=s.filter(f=>{let u=kt(t,f);if(!u)return!0;for(let g of t.edges)if(g.to===f&&kt(t,g.from)!==u)return!1;return!0}),i=!1,a=!1;for(let f of r)Ue(t,f)?Je(t,f).length>0&&(a=!0):i=!0;let c=e==="LR"&&i&&a,l,d=[];c?(l=r.filter(f=>!Ue(t,f)),d=r.filter(f=>Ue(t,f))):l=r;for(let f of l){let u=e==="LR"?{x:0,y:n[0]}:{x:n[0],y:0};ge(t,t.nodes[f.index],u),n[0]=n[0]+4}if(c&&d.length>0)for(let u of d){let g=e==="LR"?{x:4,y:n[4]}:{x:n[4],y:4};ge(t,t.nodes[u.index],g),n[4]=n[4]+4}let h=l.length+d.length;for(;h<t.nodes.length;){let f=h;for(let u of t.nodes){if(u.gridCoord===null)continue;let g=u.gridCoord;for(let p of Je(t,u)){if(p.gridCoord!==null)continue;let $=kt(t,u),A=kt(t,p),X=$&&$===A&&$.direction?$.direction:t.config.graphDirection,v=X==="LR"?g.x+4:g.y+4,Y;X!==t.config.graphDirection?Y=X==="LR"?g.y:g.x:Y=n[v];let D=X==="LR"?{x:v,y:Y}:{x:Y,y:v};ge(t,t.nodes[p.index],D,X),X===t.config.graphDirection&&(n[v]=Y+4),h++}}if(h===f)break}for(let f of t.nodes)Ri(t,f);t.bundles=En(t),Yn(t);for(let f of t.edges){if(f.bundle&&f.path.length>0){nr(t,f.path),ze(t,f);continue}Tn(t,f),nr(t,f.path),ze(t,f)}for(let f of t.nodes)f.drawingCoord=Ot(t,f.gridCoord),f.drawing=Zn(f,t);Rn(t.canvas,t.columnWidth,t.rowHeight),Dn(t.roleCanvas,t.columnWidth,t.rowHeight),Ii(t),Ei(t)}function Yi(t,e){return t.edges.filter(n=>n.from.name===e.name)}function Je(t,e){return Yi(t,e).map(n=>n.to)}function ir(t,e,n,o){let s=t.split(`
91`).map(y=>y.trim()).filter(y=>y.length>0&&!y.startsWith("%%")),r=Ee(s);if(r.actors.length===0)return"";let i=e.useAscii,a=i?"-":"\u2500",c=i?"|":"\u2502",l=i?"+":"\u250C",d=i?"+":"\u2510",h=i?"+":"\u2514",f=i?"+":"\u2518",u=i?"+":"\u252C",g=i?"+":"\u2534",p=i?"+":"\u251C",$=i?"+":"\u2524",A=new Map;r.actors.forEach((y,R)=>A.set(y.id,R));let X=1,Y=r.actors.map(y=>ve(y.label)+2*X+2).map(y=>Math.ceil(y/2)),D=r.actors.map(y=>Oe(y.label)+2),V=Math.max(...D,3),ft=new Array(Math.max(r.actors.length-1,0)).fill(0);for(let y of r.messages){let R=A.get(y.from),W=A.get(y.to);if(R===W)continue;let E=Math.min(R,W),_=Math.max(R,W),L=ve(y.label)+4,ot=_-E,O=Math.ceil(L/ot);for(let k=E;k<_;k++)ft[k]=Math.max(ft[k],O)}let j=[Y[0]];for(let y=1;y<r.actors.length;y++){let R=Math.max(Y[y-1]+Y[y]+2,ft[y-1]+2,10);j[y]=j[y-1]+R}let m=[],M=[],H=new Map,C=new Map,z=new Map,P=[],U=V;for(let y=0;y<r.messages.length;y++){for(let _=0;_<r.blocks.length;_++)r.blocks[_].startIndex===y&&(U+=2,H.set(_,U-1));for(let _=0;_<r.blocks.length;_++)for(let L=0;L<r.blocks[_].dividers.length;L++)r.blocks[_].dividers[L].index===y&&(U+=1,z.set(`${_}:${L}`,U),U+=1);U+=1;let R=r.messages[y],W=R.from===R.to,E=Oe(R.label);W?(M[y]=U+1,m[y]=U,U+=2+E):(M[y]=U,m[y]=U+E,U+=E+1);for(let _=0;_<r.notes.length;_++)if(r.notes[_].afterIndex===y){U+=1;let L=r.notes[_],ot=ht(L.text),O=Math.max(...ot.map(Q=>Q.length))+4,k=ot.length+2,nt=A.get(L.actorIds[0])??0,I;if(L.position==="left")I=j[nt]-O-1;else if(L.position==="right")I=j[nt]+2;else if(L.actorIds.length>=2){let Q=A.get(L.actorIds[1])??nt;I=Math.floor((j[nt]+j[Q])/2)-Math.floor(O/2)}else I=j[nt]-Math.floor(O/2);I=Math.max(0,I),P.push({x:I,y:U,width:O,height:k,lines:ot}),U+=k}for(let _=0;_<r.blocks.length;_++)r.blocks[_].endIndex===y&&(U+=1,C.set(_,U),U+=1)}U+=1;let T=U,K=T+V,it=j[j.length-1]??0,et=Y[Y.length-1]??0,w=it+et+2;for(let y=0;y<r.messages.length;y++){let R=r.messages[y];if(R.from===R.to){let W=A.get(R.from),E=j[W]+6+2+R.label.length;w=Math.max(w,E+1)}}for(let y of P)w=Math.max(w,y.x+y.width+1);let G=gt(w,K-1),N=Jt(w,K-1);function x(y,R,W,E){y>=0&&y<G.length&&R>=0&&R<(G[0]?.length??0)&&(G[y][R]=W,Vt(N,y,R,E))}function B(y,R,W){let E=ht(W),_=ve(W),L=_+2*X+2,ot=E.length+2,O=y-Math.floor(L/2);x(O,R,l,"border");for(let nt=1;nt<L-1;nt++)x(O+nt,R,a,"border");x(O+L-1,R,d,"border");for(let nt=0;nt<E.length;nt++){let I=R+1+nt;x(O,I,c,"border"),x(O+L-1,I,c,"border");let Q=E[nt],dt=O+1+X+Math.floor((_-Q.length)/2);for(let st=0;st<Q.length;st++)x(dt+st,I,Q[st],"text")}let k=R+ot-1;x(O,k,h,"border");for(let nt=1;nt<L-1;nt++)x(O+nt,k,a,"border");x(O+L-1,k,f,"border")}for(let y=0;y<r.actors.length;y++){let R=j[y];for(let W=V;W<=T;W++)x(R,W,c,"line")}for(let y=0;y<r.actors.length;y++){let R=r.actors[y];B(j[y],0,R.label),B(j[y],T,R.label),i||(x(j[y],V-1,u,"junction"),x(j[y],T,g,"junction"))}for(let y=0;y<r.messages.length;y++){let R=r.messages[y],W=A.get(R.from),E=A.get(R.to),_=j[W],L=j[E],ot=W===E,O=R.lineStyle==="dashed",k=R.arrowHead==="filled",nt=O?i?".":"\u254C":a;if(ot){let I=m[y],Q=Math.max(4,4);x(_,I,p,"junction");for(let lt=_+1;lt<_+Q;lt++)x(lt,I,nt,"line");x(_+Q,I,i?"+":"\u2510","corner"),x(_+Q,I+1,c,"line");let dt=_+Q+2;for(let lt=0;lt<R.label.length;lt++)dt+lt<w&&x(dt+lt,I+1,R.label[lt],"text");let st=k?i?"<":"\u25C0":i?"<":"\u25C1";x(_,I+2,st,"arrow");for(let lt=_+1;lt<_+Q;lt++)x(lt,I+2,nt,"line");x(_+Q,I+2,i?"+":"\u2518","corner")}else{let I=M[y],Q=m[y],dt=_<L,st=Math.floor((_+L)/2),lt=ht(R.label);for(let xt=0;xt<lt.length;xt++){let yt=lt[xt],Pt=st-Math.floor(yt.length/2),Qt=I+xt;for(let Xt=0;Xt<yt.length;Xt++){let oe=Pt+Xt;oe>=0&&oe<w&&x(oe,Qt,yt[Xt],"text")}}if(dt){for(let yt=_+1;yt<L;yt++)x(yt,Q,nt,"line");x(L,Q,k?i?">":"\u25B6":i?">":"\u25B7","arrow")}else{for(let yt=L+1;yt<_;yt++)x(yt,Q,nt,"line");x(L,Q,k?i?"<":"\u25C0":i?"<":"\u25C1","arrow")}}}for(let y=0;y<r.blocks.length;y++){let R=r.blocks[y],W=H.get(y),E=C.get(y);if(W===void 0||E===void 0)continue;let _=w,L=0;for(let I=R.startIndex;I<=R.endIndex&&!(I>=r.messages.length);I++){let Q=r.messages[I],dt=A.get(Q.from)??0,st=A.get(Q.to)??0;_=Math.min(_,j[Math.min(dt,st)]),L=Math.max(L,j[Math.max(dt,st)])}let ot=Math.max(0,_-4),O=Math.min(w-1,L+4);x(ot,W,l,"border");for(let I=ot+1;I<O;I++)x(I,W,a,"border");x(O,W,d,"border");let k=R.label?`${R.type} [${R.label}]`:R.type,nt=ht(k);for(let I=0;I<nt.length&&W+I<E;I++){let Q=nt[I];for(let dt=0;dt<Q.length&&ot+1+dt<O;dt++)x(ot+1+dt,W+I,Q[dt],"text")}x(ot,E,h,"border");for(let I=ot+1;I<O;I++)x(I,E,a,"border");x(O,E,f,"border");for(let I=W+1;I<E;I++)x(ot,I,c,"border"),x(O,I,c,"border");for(let I=0;I<R.dividers.length;I++){let Q=z.get(`${y}:${I}`);if(Q===void 0)continue;let dt=rt();x(ot,Q,p,"junction");for(let lt=ot+1;lt<O;lt++)x(lt,Q,dt,"line");x(O,Q,$,"junction");let st=R.dividers[I].label;if(st){let lt=`[${st}]`;for(let xt=0;xt<lt.length&&ot+1+xt<O;xt++)x(ot+1+xt,Q,lt[xt],"text")}}}for(let y of P){_t(G,y.x+y.width,y.y+y.height),qt(N,y.x+y.width,y.y+y.height),x(y.x,y.y,l,"border");for(let W=1;W<y.width-1;W++)x(y.x+W,y.y,a,"border");x(y.x+y.width-1,y.y,d,"border");for(let W=0;W<y.lines.length;W++){let E=y.y+1+W;x(y.x,E,c,"border"),x(y.x+y.width-1,E,c,"border");for(let _=0;_<y.lines[W].length;_++)x(y.x+2+_,E,y.lines[W][_],"text")}let R=y.y+y.height-1;x(y.x,R,h,"border");for(let W=1;W<y.width-1;W++)x(y.x+W,R,a,"border");x(y.x+y.width-1,R,f,"border")}return te(G,{roleCanvas:N,colorMode:n,theme:o});function rt(){return i?"-":"\u254C"}}function ar(t){let e={classes:[],relationships:[],namespaces:[]},n=new Map,o=null,s=null,r=0;for(let i=1;i<t.length;i++){let a=t[i];if(s&&r>0){if(a==="}"){r--,r===0&&(s=null);continue}let g=a.match(/^<<(\w+)>>$/);if(g){s.annotation=g[1];continue}let p=sr(a);p&&(p.isMethod?s.methods.push(p.member):s.attributes.push(p.member));continue}let c=a.match(/^namespace\s+(\S+)\s*\{$/);if(c){o={name:c[1],classIds:[]};continue}if(a==="}"&&o){e.namespaces.push(o),o=null;continue}let l=a.match(/^class\s+(\S+?)(?:\s*~(\w+)~)?\s*\{$/);if(l){let g=l[1],p=l[2],$=le(n,g);p&&($.label=`${g}<${p}>`),s=$,r=1,o&&o.classIds.push(g);continue}let d=a.match(/^class\s+(\S+?)(?:\s*~(\w+)~)?\s*$/);if(d){let g=d[1],p=d[2],$=le(n,g);p&&($.label=`${g}<${p}>`),o&&o.classIds.push(g);continue}let h=a.match(/^class\s+(\S+?)\s*\{\s*<<(\w+)>>\s*\}$/);if(h){let g=le(n,h[1]);g.annotation=h[2];continue}let f=a.match(/^(\S+?)\s*:\s*(.+)$/);if(f){let g=f[2];if(!g.match(/<\|--|--|\*--|o--|-->|\.\.>|\.\.\|>/)){let p=le(n,f[1]),$=sr(g);$&&($.isMethod?p.methods.push($.member):p.attributes.push($.member));continue}}let u=Pi(a);if(u){le(n,u.from),le(n,u.to),e.relationships.push(u);continue}}return e.classes=[...n.values()],e}function le(t,e){let n=t.get(e);return n||(n={id:e,label:e,attributes:[],methods:[]},t.set(e,n)),n}function sr(t){let e=t.trim().replace(/;$/,"");if(!e)return null;let n="",o=e;/^[+\-#~]/.test(o)&&(n=o[0],o=o.slice(1).trim());let s=o.match(/^(.+?)\(([^)]*)\)(?:\s*(.+))?$/);if(s){let d=s[1].trim(),h=s[2]?.trim()||void 0,f=s[3]?.trim(),u=d.endsWith("$")||o.includes("$"),g=d.endsWith("*")||o.includes("*");return{member:{visibility:n,name:d.replace(/[$*]$/,""),type:f||void 0,isStatic:u,isAbstract:g,isMethod:!0,params:h},isMethod:!0}}let r=o.split(/\s+/),i,a;r.length>=2?(a=r[0],i=r.slice(1).join(" ")):i=r[0]??o;let c=i.endsWith("$"),l=i.endsWith("*");return{member:{visibility:n,name:i.replace(/[$*]$/,""),type:a||void 0,isStatic:c,isAbstract:l,isMethod:!1},isMethod:!1}}function Pi(t){let e=t.match(/^(\S+?)\s+(?:"([^"]*?)"\s+)?(<\|--|<\|\.\.|\*--|o--|-->|--\*|--o|--\|>|\.\.>|\.\.\|>|<--|<\.\.?|--)\s+(?:"([^"]*?)"\s+)?(\S+?)(?:\s*:\s*(.+))?$/);if(!e)return null;let n=e[1],o=e[2],s=o?mt(o):void 0,r=e[3].trim(),i=e[4],a=i?mt(i):void 0,c=e[5],l=e[6]?.trim(),d=l?mt(l):void 0,h=Xi(r);return h?{from:n,to:c,type:h.type,markerAt:h.markerAt,label:d,fromCardinality:s,toCardinality:a}:null}function Xi(t){switch(t.trim()){case"<|--":return{type:"inheritance",markerAt:"from"};case"--|>":return{type:"inheritance",markerAt:"to"};case"<|..":return{type:"realization",markerAt:"from"};case"..|>":return{type:"realization",markerAt:"to"};case"*--":return{type:"composition",markerAt:"from"};case"--*":return{type:"composition",markerAt:"to"};case"o--":return{type:"aggregation",markerAt:"from"};case"--o":return{type:"aggregation",markerAt:"to"};case"-->":return{type:"association",markerAt:"to"};case"<--":return{type:"association",markerAt:"from"};case"..>":return{type:"dependency",markerAt:"to"};case"<..":return{type:"dependency",markerAt:"from"};case"--":return{type:"association",markerAt:"to"};default:return null}}function Hi(t){return/^[┌┐└┘├┤┬┴┼│─╭╮╰╯+\-|]$/.test(t)?"border":"text"}function cr(t){let e=t.visibility||"",n=t.type?`: ${t.type}`:"";return`${e}${t.name}${n}`}function Gi(t){let e=[];t.annotation&&e.push(`<<${t.annotation}>>`);let n=ht(t.label);e.push(...n);let o=t.attributes.map(cr),s=t.methods.map(cr);return o.length===0&&s.length===0?[e]:s.length===0?[e,o]:[e,o,s]}function Wi(t,e){return{type:t,markerAt:e,dashed:t==="dependency"||t==="realization"}}function ne(t,e,n){switch(t){case"inheritance":case"realization":return n==="down"?e?"^":"\u25B3":n==="up"?e?"v":"\u25BD":n==="left"?e?">":"\u25C1":e?"<":"\u25B7";case"composition":return e?"*":"\u25C6";case"aggregation":return e?"o":"\u25C7";case"association":case"dependency":return n==="down"?e?"v":"\u25BC":n==="up"?e?"^":"\u25B2":n==="left"?e?"<":"\u25C0":e?">":"\u25B6"}}function lr(t,e,n,o){let s=t.split(`
92`).map(w=>w.trim()).filter(w=>w.length>0&&!w.startsWith("%%")),r=ar(s);if(r.classes.length===0)return"";let i=e.useAscii,a=4,c=3,l=new Map,d=new Map,h=new Map;for(let w of r.classes){let G=Gi(w);l.set(w.id,G);let N=0;for(let y of G)for(let R of y)N=Math.max(N,R.length);let x=N+4,B=0;for(let y of G)B+=Math.max(y.length,1);let rt=B+(G.length-1)+2;d.set(w.id,x),h.set(w.id,rt)}let f=new Map;for(let w of r.classes)f.set(w.id,w);let u=new Map,g=new Map;for(let w of r.relationships){let G=w.type==="inheritance"||w.type==="realization",N=G&&w.markerAt==="to"?w.to:w.from,x=G&&w.markerAt==="to"?w.from:w.to;u.has(x)||u.set(x,new Set),u.get(x).add(N),g.has(N)||g.set(N,new Set),g.get(N).add(x)}let p=new Map,A=r.classes.filter(w=>!u.has(w.id)||u.get(w.id).size===0).map(w=>w.id);for(let w of A)p.set(w,0);let X=r.classes.length-1,v=0;for(;v<A.length;){let w=A[v++],G=g.get(w);if(G)for(let N of G){let x=(p.get(w)??0)+1;x>X||(!p.has(N)||p.get(N)<x)&&(p.set(N,x),A.push(N))}}for(let w of r.classes)p.has(w.id)||p.set(w.id,0);let Y=Math.max(...p.values(),0),D=Array.from({length:Y+1},()=>[]);for(let w of r.classes)D[p.get(w.id)].push(w.id);let V=new Map,ft=0;for(let w=0;w<=Y;w++){let G=D[w];if(G.length===0)continue;let N=0,x=0;for(let B of G){let rt=f.get(B),y=d.get(B),R=h.get(B);V.set(B,{cls:rt,sections:l.get(B),x:N,y:ft,width:y,height:R}),N+=y+a,x=Math.max(x,R)}ft+=x+c}let j=0,m=0;for(let w of V.values())j=Math.max(j,w.x+w.width),m=Math.max(m,w.y+w.height);j+=4,m+=2;let M=gt(j-1,m-1),H=Jt(j-1,m-1);function C(w,G,N,x){w>=0&&w<M.length&&G>=0&&G<(M[0]?.length??0)&&(M[w][G]=N,Vt(H,w,G,x))}for(let w of V.values()){let G=Se(w.sections,i);for(let N=0;N<G.length;N++)for(let x=0;x<G[0].length;x++){let B=G[N][x];if(B!==" "){let rt=w.x+N,y=w.y+x;rt<j&&y<m&&C(rt,y,B,Hi(B))}}}let z=[];for(let w of V.values())z.push({x1:w.x,x2:w.x+w.width-1,y1:w.y,y2:w.y+w.height-1});function P(w,G,N){for(let[x,B]of V.entries())if(!N?.has(x)&&w>=B.x&&w<=B.x+B.width-1&&G>=B.y&&G<=B.y+B.height-1)return!0;return!1}function U(w,G,N,x){let B=!0;for(let rt=Math.min(G,N);rt<=Math.max(G,N);rt++)if(P(w,rt,x)){B=!1;break}if(B)return w;for(let rt=1;rt<j+10;rt++){let y=w+rt;B=!0;for(let W=Math.min(G,N);W<=Math.max(G,N);W++)if(P(y,W,x)){B=!1;break}if(B)return y;let R=w-rt;if(R>=0){B=!0;for(let W=Math.min(G,N);W<=Math.max(G,N);W++)if(P(R,W,x)){B=!1;break}if(B)return R}}return j+2}let T=i?"-":"\u2500",K=i?"|":"\u2502",it=i?".":"\u254C",et=i?":":"\u250A";for(let w of r.relationships){let G=V.get(w.from),N=V.get(w.to);if(!G||!N)continue;let x=Wi(w.type,w.markerAt),B=x.dashed?it:T,rt=x.dashed?et:K,y=new Set([w.from,w.to]),R=G.x+Math.floor(G.width/2),W=G.y+G.height-1,E=N.x+Math.floor(N.width/2),_=N.y;if(W<_){let L=U(R,W+1,_-1,y),ot=L!==R;if(L>=j&&_t(M,L+2,m),ot){let O=W+1,k=_-1,nt=Math.min(R,L),I=Math.max(R,L);for(let Q=nt;Q<=I;Q++)C(Q,O,B,"line");!i&&O<(M[0]?.length??0)&&(R<L?(C(R,O,"\u2514","corner"),C(L,O,"\u2510","corner")):(C(R,O,"\u2518","corner"),C(L,O,"\u250C","corner")));for(let Q=O+1;Q<=k;Q++)C(L,Q,rt,"line");if(L!==E){let Q=Math.min(L,E),dt=Math.max(L,E);for(let st=Q;st<=dt;st++)C(st,k,B,"line");!i&&k<(M[0]?.length??0)&&(L<E?(C(L,k,"\u2514","corner"),C(E,k,"\u2510","corner")):(C(L,k,"\u2518","corner"),C(E,k,"\u250C","corner")))}if(x.markerAt==="to"){let Q=ne(x.type,i,"down");C(E,k,Q,"arrow")}if(x.markerAt==="from"){let Q=ne(x.type,i,"down");C(R,W+1,Q,"arrow")}}else{let O=W+Math.floor((_-W)/2);for(let k=W+1;k<=O;k++)C(R,k,rt,"line");if(R!==E&&O<(M[0]?.length??0)){let k=Math.min(R,E),nt=Math.max(R,E);for(let I=k;I<=nt;I++)C(I,O,B,"line");i||(C(R,O,R<E?"\u2514":"\u2518","corner"),C(E,O,R<E?"\u2510":"\u250C","corner"))}for(let k=O+1;k<_;k++)C(E,k,rt,"line");x.markerAt==="to"&&C(E,_-1,ne(x.type,i,"down"),"arrow"),x.markerAt==="from"&&C(R,W+1,ne(x.type,i,"down"),"arrow")}}else if(N.y+N.height-1<G.y){let L=G.y,ot=N.y+N.height-1,O=ot+Math.floor((L-ot)/2);for(let k=L-1;k>=O;k--)C(R,k,rt,"line");if(R!==E){let k=Math.min(R,E),nt=Math.max(R,E);for(let I=k;I<=nt;I++)C(I,O,B,"line");!i&&O>=0&&O<m&&(C(R,O,R<E?"\u250C":"\u2510","corner"),C(E,O,R<E?"\u2518":"\u2514","corner"))}for(let k=O-1;k>ot;k--)C(E,k,rt,"line");if(x.markerAt==="from"){let k=ne(x.type,i,"up"),nt=L-1;for(let I=0;I<k.length;I++)C(R-Math.floor(k.length/2)+I,nt,k[I],"arrow")}if(x.markerAt==="to"){let nt=x.type==="inheritance"||x.type==="realization"?"down":"up",I=ne(x.type,i,nt),Q=ot+1;for(let dt=0;dt<I.length;dt++)C(E-Math.floor(I.length/2)+dt,Q,I[dt],"arrow")}}else{let L=Math.max(W,N.y+N.height-1)+2;_t(M,j,L+1),qt(H,j,L+1);for(let k=W+1;k<=L;k++)C(R,k,rt,"line");let ot=Math.min(R,E),O=Math.max(R,E);for(let k=ot;k<=O;k++)C(k,L,B,"line");for(let k=L-1;k>=N.y+N.height;k--)C(E,k,rt,"line");if(x.markerAt==="from"){let k=ne(x.type,i,"down"),nt=W+1;for(let I=0;I<k.length;I++)C(R-Math.floor(k.length/2)+I,nt,k[I],"arrow")}if(x.markerAt==="to"){let k=ne(x.type,i,"up"),nt=N.y+N.height;for(let I=0;I<k.length;I++)C(E-Math.floor(k.length/2)+I,nt,k[I],"arrow")}}if(w.label){let L=ht(w.label),ot=Math.max(...L.map(st=>st.length))+2,O,k;if(W<_)O=Math.floor((W+1+_-1)/2),k=Math.floor((R+E)/2);else if(N.y+N.height-1<G.y){let st=N.y+N.height-1;O=Math.floor((st+1+G.y-1)/2),k=Math.floor((R+E)/2)}else O=Math.max(W,N.y+N.height-1)+2,k=Math.floor((R+E)/2);let nt=O,I=Math.floor(L.length/2),Q=!1;for(let st=0;st<L.length;st++){let lt=nt-I+st,xt=k-Math.floor(ot/2),yt=Math.max(0,xt);for(let Pt=yt;Pt<yt+ot;Pt++)if(P(Pt,lt,y)){Q=!0;break}if(Q)break}if(Q){let st=W+1,lt=_-1;for(let xt=st;xt<=lt;xt++){let yt=!0,Pt=k-Math.floor(ot/2),Qt=Math.max(0,Pt);for(let Xt=Qt;Xt<Qt+ot;Xt++)if(P(Xt,xt,y)){yt=!1;break}if(yt){nt=xt;break}}}let dt=nt-I;for(let st=0;st<L.length;st++){let lt=` ${L[st]} `,xt=k-Math.floor(lt.length/2),yt=Math.max(0,xt),Pt=dt+st,Qt=yt+lt.length;Qt>0&&Pt>=0&&(_t(M,Math.max(Qt,1),Math.max(Pt+1,1)),qt(H,Math.max(Qt,1),Math.max(Pt+1,1)));for(let Xt=0;Xt<lt.length;Xt++){let oe=yt+Xt;oe>=0&&Pt>=0&&C(oe,Pt,lt[Xt],"text")}}}}return te(M,{roleCanvas:H,colorMode:n,theme:o})}function fr(t){let e={entities:[],relationships:[]},n=new Map,o=null;for(let s=1;s<t.length;s++){let r=t[s];if(o){if(r==="}"){o=null;continue}let c=Ni(r);c&&o.attributes.push(c);continue}let i=r.match(/^(\S+)\s*\{$/);if(i){let c=i[1];o=Ve(n,c);continue}let a=Bi(r);if(a){Ve(n,a.entity1),Ve(n,a.entity2),e.relationships.push(a);continue}}return e.entities=[...n.values()],e}function Ve(t,e){let n=t.get(e);return n||(n={id:e,label:e,attributes:[]},t.set(e,n)),n}function Ni(t){let e=t.match(/^(\S+)\s+(\S+)(?:\s+(.+))?$/);if(!e)return null;let n=e[1],o=e[2],s=e[3]?.trim()??"",r=[],i,a=s.match(/"([^"]*)"/);a&&(i=mt(a[1]));let c=s.replace(/"[^"]*"/,"").trim();for(let l of c.split(/\s+/)){let d=l.toUpperCase();(d==="PK"||d==="FK"||d==="UK")&&r.push(d)}return{type:n,name:o,keys:r,comment:i}}function Bi(t){let e=t.match(/^(\S+)\s+([|o}{]+(?:--|\.\.)[|o}{]+)\s+(\S+)\s*:\s*(.+)$/);if(!e)return null;let n=e[1],o=e[2],s=e[3],r=e[4].trim().replace(/^["']|["']$/g,""),i=mt(r),a=o.match(/^([|o}{]+)(--|\.\.?)([|o}{]+)$/);if(!a)return null;let c=a[1],l=a[2],d=a[3],h=dr(c),f=dr(d),u=l==="--";return!h||!f?null:{entity1:n,entity2:s,cardinality1:h,cardinality2:f,label:i,identifying:u}}function dr(t){let e=t.split("").sort().join("");return e==="||"?"one":e==="o|"?"zero-one":e==="|}"||e==="{|"?"many":e==="{o"||e==="o{"?"zero-many":null}function _i(t){return/^[┌┐└┘├┤┬┴┼│─╭╮╰╯+\-|]$/.test(t)?"border":"text"}function zi(t){return`${t.keys.length>0?t.keys.join(",")+" ":" "}${t.type} ${t.name}`}function Oi(t){let e=ht(t.label),n=t.attributes.map(zi);return n.length===0?[e]:[e,n]}function Re(t,e,n=!1){if(e)switch(t){case"one":return"|";case"zero-one":return"o|";case"many":return n?"<":">";case"zero-many":return n?"o<":">o"}else switch(t){case"one":return"\u2502";case"zero-one":return"\u25CB\u2502";case"many":return n?"\u255F":"\u2562";case"zero-many":return n?"\u25CB\u255F":"\u2562\u25CB"}}function ji(t){let e=new Set,n=[],o=new Map;for(let r of t.entities)o.set(r.id,new Set);for(let r of t.relationships)o.get(r.entity1)?.add(r.entity2),o.get(r.entity2)?.add(r.entity1);function s(r,i){let a=[r];for(;a.length>0;){let c=a.pop();if(!e.has(c)){e.add(c),i.add(c);for(let l of o.get(c)??[])e.has(l)||a.push(l)}}}for(let r of t.entities)if(!e.has(r.id)){let i=new Set;s(r.id,i),i.size>0&&n.push(i)}return n}function ur(t,e,n,o){let s=t.split(`
93`).map(M=>M.trim()).filter(M=>M.length>0&&!M.startsWith("%%")),r=fr(s);if(r.entities.length===0)return"";let i=e.useAscii,a=6,c=4,l=6,d=new Map,h=new Map,f=new Map,u=new Map;for(let M of r.entities){u.set(M.id,M);let H=Oi(M);d.set(M.id,H);let C=0;for(let T of H)for(let K of T)C=Math.max(C,K.length);let z=C+4,P=0;for(let T of H)P+=Math.max(T.length,1);let U=P+(H.length-1)+2;h.set(M.id,z),f.set(M.id,U)}let g=ji(r),p=new Map,$=0;for(let M of g){let H=r.entities.filter(K=>M.has(K.id)),C=Math.max(2,Math.ceil(Math.sqrt(H.length))),z=0,P=0,U=0,T=$;for(let K of H){let it=h.get(K.id),et=f.get(K.id);U>=C&&($+=P+c,z=0,P=0,U=0),p.set(K.id,{entity:K,sections:d.get(K.id),x:z,y:$,width:it,height:et}),z+=it+a,P=Math.max(P,et),U++}$+=P+l}let A=0,X=0;for(let M of p.values())A=Math.max(A,M.x+M.width),X=Math.max(X,M.y+M.height);A+=4,X+=2;let v=gt(A-1,X-1),Y=Jt(A-1,X-1);function D(M,H,C,z){M>=0&&M<v.length&&H>=0&&H<(v[0]?.length??0)&&(v[M][H]=C,Vt(Y,M,H,z))}for(let M of p.values()){let H=Se(M.sections,i);for(let C=0;C<H.length;C++)for(let z=0;z<H[0].length;z++){let P=H[C][z];if(P!==" "){let U=M.x+C,T=M.y+z;U<A&&T<X&&D(U,T,P,_i(P))}}}let V=i?"-":"\u2500",ft=i?"|":"\u2502",j=i?".":"\u254C",m=i?":":"\u250A";for(let M of r.relationships){let H=p.get(M.entity1),C=p.get(M.entity2);if(!H||!C)continue;let z=M.identifying?V:j,P=M.identifying?ft:m,U=H.x+Math.floor(H.width/2),T=H.y+Math.floor(H.height/2),K=C.x+Math.floor(C.width/2),it=C.y+Math.floor(C.height/2);if(Math.abs(T-it)<Math.max(H.height,C.height)){let[w,G]=U<K?[H,C]:[C,H],[N,x]=U<K?[M.cardinality1,M.cardinality2]:[M.cardinality2,M.cardinality1],B=w.x+w.width,rt=G.x-1,y=w.y+Math.floor(w.height/2);for(let E=B;E<=rt;E++)D(E,y,z,"line");let R=Re(N,i,!1);for(let E=0;E<R.length;E++)D(B+E,y,R[E],"arrow");let W=Re(x,i,!0);for(let E=0;E<W.length;E++)D(rt-W.length+1+E,y,W[E],"arrow");if(M.label){let E=ht(M.label),_=Math.floor((B+rt)/2);for(let L=0;L<E.length;L++){let ot=E[L],O=Math.max(B,_-Math.floor(ot.length/2)),k=y+1+L;_t(v,Math.max(O+ot.length,1),Math.max(k+1,1)),qt(Y,Math.max(O+ot.length,1),Math.max(k+1,1));for(let nt=0;nt<ot.length;nt++){let I=O+nt;I>=B&&I<=rt&&D(I,k,ot[nt],"text")}}}}else{let[w,G]=T<it?[H,C]:[C,H],[N,x]=T<it?[M.cardinality1,M.cardinality2]:[M.cardinality2,M.cardinality1],B=w.y+w.height,rt=G.y-1,y=w.x+Math.floor(w.width/2);for(let L=B;L<=rt;L++)D(y,L,P,"line");let R=G.x+Math.floor(G.width/2);if(y!==R){let L=Math.floor((B+rt)/2),ot=Math.min(y,R),O=Math.max(y,R);for(let k=ot;k<=O;k++)D(k,L,z,"line");for(let k=L+1;k<=rt;k++)D(R,k,P,"line")}let W=Re(N,i,!1);for(let L=0;L<W.length;L++)D(y-Math.floor(W.length/2)+L,B,W[L],"arrow");let E=y!==R?R:y,_=Re(x,i,!0);for(let L=0;L<_.length;L++)D(E-Math.floor(_.length/2)+L,rt,_[L],"arrow");if(M.label){let L=ht(M.label),O=Math.floor((B+rt)/2)-Math.floor((L.length-1)/2);for(let k=0;k<L.length;k++){let nt=L[k],I=y+2,Q=O+k;if(Q>=0)for(let dt=0;dt<nt.length;dt++){let st=I+dt;st>=0&&(_t(v,st+1,Q+1),qt(Y,st+1,Q+1),D(st,Q,nt[dt],"text"))}}}}}return te(v,{roleCanvas:Y,colorMode:n,theme:o})}var hr=60,gr=20,Fi={hLine:"\u2500",vLine:"\u2502",origin:"\u253C",yTick:"\u2524",xTick:"\u252C",bar:"\u2588",grid:"\xB7",cornerTL:"\u256D",cornerTR:"\u256E",cornerBL:"\u2570",cornerBR:"\u256F"},qi={hLine:"-",vLine:"|",origin:"+",yTick:"+",xTick:"+",bar:"#",grid:".",cornerTL:"+",cornerTR:"+",cornerBL:"+",cornerBR:"+"};function mr(t,e){let n=e.accent??ae;return t<=1?[n]:Array.from({length:t},(o,s)=>be(s,n,e.bg))}function Ui(t,e){switch(t){case"text":return e.fg;case"border":return e.border;case"line":return e.line;case"arrow":return e.arrow;case"corner":return e.corner??e.line;case"junction":return e.junction??e.border;default:return e.fg}}function pr(t,e,n,o){let s=t.split(`
94`).map(a=>a.trim()).filter(a=>a.length>0&&!a.startsWith("%%")),r=Ye(s),i=e.useAscii?qi:Fi;return r.horizontal?Vi(r,i,n,o):Ji(r,i,n,o)}function Ji(t,e,n,o){let s=Mr(t);if(s===0)return"";let r=t.yAxis.range,i=vr(r.min,r.max),a=i.map(T=>De(T)),c=Math.max(...a.map(T=>T.length))+1,l=Math.max(hr,s*6),d=gr,h=Math.floor(l/s),f=Ar(t,s),u=!!t.title,g=!!t.xAxis.title,p=t.series.length>1,$=u?0:-1,A=(u?2:0)+(p?1:0),X=c+1,v=X+h*s+2,Y=A+d,D=Y+1,V=g?D+1:-1,ft=D+1+(g?1:0)+0,j=br(v,ft),m=yr(v,ft),M=$r(v,ft),H=mr(t.series.length,o),C=T=>{let K=(T-r.min)/(r.max-r.min||1);return Math.round(K*(d-1))},z=T=>X+Math.floor(h*(T+.5));u&&$>=0&&Kt(j,m,$,Math.floor(v/2-t.title.length/2),t.title,"text"),p&&xr(j,m,M,t,u?1:0,v,e,H);for(let T=0;T<d;T++){let K=A+(d-1-T);Dt(j,m,K,X-1,e.vLine,"border")}Dt(j,m,Y,X-1,e.origin,"border");for(let T of i){let K=C(T);if(K<0||K>=d)continue;let it=A+(d-1-K),et=De(T);Dt(j,m,it,X-1,K===0?e.origin:e.yTick,"border");let w=c-et.length;Kt(j,m,it,Math.max(0,w),et,"text")}for(let T=X;T<X+h*s;T++)Dt(j,m,Y,T,e.hLine,"border");for(let T=0;T<s;T++){let K=z(T);Dt(j,m,Y,K,e.xTick,"border");let it=f[T],et=K-Math.floor(it.length/2);Kt(j,m,D,Math.max(0,et),it,"text")}if(g&&V>=0){let T=t.xAxis.title;Kt(j,m,V,Math.floor(v/2-T.length/2),T,"text")}for(let T of i){let K=C(T);if(K<0||K>=d)continue;let it=A+(d-1-K);for(let et=X;et<X+h*s;et++)Cr(j,it,et)===" "&&Dt(j,m,it,et,e.grid,"line")}let P=[];for(let T=0;T<t.series.length;T++)t.series[T].type==="bar"&&P.push({data:t.series[T].data,globalIdx:T});if(P.length>0){let T=P.length,K=Math.max(1,h-2),it=Math.max(1,Math.min(Math.floor(K/T),8)),et=it*T+(T-1),w=C(Math.max(0,r.min));for(let G=0;G<P.length;G++){let N=P[G],x=H[N.globalIdx];for(let B=0;B<N.data.length;B++){let R=z(B)-Math.floor(et/2)+G*(it+1),W=C(N.data[B]),E=Math.min(w,W),_=Math.max(w,W);for(let L=E;L<=_;L++){let ot=A+(d-1-L);for(let O=R;O<R+it;O++)Dt(j,m,ot,O,e.bar,"arrow",M,x)}}}}let U=[];for(let T=0;T<t.series.length;T++)t.series[T].type==="line"&&U.push({data:t.series[T].data,globalIdx:T});for(let T of U){if(T.data.length===0)continue;let K=H[T.globalIdx];Ki(j,m,T.data,z,C,A,d,X,h*s,e,M,K)}return wr(j,m,M,n,o)}function Vi(t,e,n,o){let s=Mr(t);if(s===0)return"";let r=t.yAxis.range,i=vr(r.min,r.max),a=Ar(t,s),c=Math.max(...a.map(C=>C.length))+1,l=Math.max(hr,40),d=Math.max(2,Math.floor(gr/s)),h=d*s,f=!!t.title,u=!!t.yAxis.title,g=t.series.length>1,p=(f?2:0)+(g?1:0),$=c+1,A=$+l+2,X=p+h+2+(u?1:0),v=p+h,Y=br(A,X),D=yr(A,X),V=$r(A,X),ft=mr(t.series.length,o),j=C=>{let z=(C-r.min)/(r.max-r.min||1);return $+Math.round(z*(l-1))},m=C=>p+Math.floor(d*(C+.5));f&&Kt(Y,D,0,Math.floor(A/2-t.title.length/2),t.title,"text"),g&&xr(Y,D,V,t,f?1:0,A,e,ft);for(let C=p;C<p+h;C++)Dt(Y,D,C,$-1,e.vLine,"border");Dt(Y,D,v,$-1,e.origin,"border");for(let C=0;C<s;C++){let z=m(C),P=a[C],U=c-P.length;Kt(Y,D,z,Math.max(0,U),P,"text")}for(let C=$;C<$+l;C++)Dt(Y,D,v,C,e.hLine,"border");for(let C of i){let z=j(C);if(z<$||z>=$+l)continue;Dt(Y,D,v,z,e.xTick,"border");let P=De(C);Kt(Y,D,v+1,z-Math.floor(P.length/2),P,"text")}if(u){let C=t.yAxis.title;Kt(Y,D,X-1,Math.floor(A/2-C.length/2),C,"text")}for(let C of i){let z=j(C);if(!(z<$||z>=$+l))for(let P=p;P<p+h;P++)Cr(Y,P,z)===" "&&Dt(Y,D,P,z,e.grid,"line")}let M=[];for(let C=0;C<t.series.length;C++)t.series[C].type==="bar"&&M.push({data:t.series[C].data,globalIdx:C});if(M.length>0){let C=M.length,z=1,P=z*C+(C-1),U=j(Math.max(0,r.min));for(let T=0;T<M.length;T++){let K=M[T],it=ft[K.globalIdx];for(let et=0;et<K.data.length;et++){let N=m(et)-Math.floor(P/2)+T*(z+1),x=j(K.data[et]),B=Math.min(U,x),rt=Math.max(U,x);for(let y=N;y<N+z;y++)for(let R=B;R<=rt;R++)Dt(Y,D,y,R,e.bar,"arrow",V,it)}}}let H=[];for(let C=0;C<t.series.length;C++)t.series[C].type==="line"&&H.push({data:t.series[C].data,globalIdx:C});for(let C of H){if(C.data.length===0)continue;let z=ft[C.globalIdx];Qi(Y,D,C.data,m,j,p,h,$,l,e,V,z)}return wr(Y,D,V,n,o)}function Ki(t,e,n,o,s,r,i,a,c,l,d,h){if(n.length===0)return;let f=n.map((g,p)=>({col:o(p),row:s(g)})),u=(g,p,$)=>{let A=r+(i-1-p);A>=0&&g>=a&&g<a+c&&Dt(t,e,A,g,$,"arrow",d,h)};if(f.length===1){u(f[0].col,f[0].row,l.hLine);return}for(let g=0;g<f.length-1;g++){let p=f[g],$=f[g+1];if(p.row===$.row){for(let D=p.col;D<=$.col;D++)u(D,p.row,l.hLine);continue}let A=Math.round((p.col+$.col)/2),X=$.row>p.row;for(let D=p.col;D<A;D++)u(D,p.row,l.hLine);X?u(A,p.row,l.cornerBR):u(A,p.row,l.cornerTR);let v=Math.min(p.row,$.row),Y=Math.max(p.row,$.row);for(let D=v+1;D<Y;D++)u(A,D,l.vLine);X?u(A,$.row,l.cornerTL):u(A,$.row,l.cornerBL);for(let D=A+1;D<=$.col;D++)u(D,$.row,l.hLine);if(g===0){let D=Math.max(a,p.col-Math.floor(($.col-p.col)/4));for(let V=D;V<p.col;V++)u(V,p.row,l.hLine)}if(g===f.length-2){let D=Math.min(a+c-1,$.col+Math.floor(($.col-p.col)/4));for(let V=$.col+1;V<=D;V++)u(V,$.row,l.hLine)}}}function Qi(t,e,n,o,s,r,i,a,c,l,d,h){if(n.length===0)return;let f=n.map((g,p)=>({row:o(p),col:s(g)})),u=(g,p,$)=>{g>=r&&g<r+i&&p>=a&&p<a+c&&Dt(t,e,g,p,$,"arrow",d,h)};if(f.length===1){u(f[0].row,f[0].col,l.vLine);return}for(let g=0;g<f.length-1;g++){let p=f[g],$=f[g+1];if(p.col===$.col){for(let D=p.row;D<=$.row;D++)u(D,p.col,l.vLine);continue}let A=Math.round((p.row+$.row)/2),X=$.col>p.col;for(let D=p.row;D<A;D++)u(D,p.col,l.vLine);X?u(A,p.col,l.cornerBL):u(A,p.col,l.cornerBR);let v=Math.min(p.col,$.col),Y=Math.max(p.col,$.col);for(let D=v+1;D<Y;D++)u(A,D,l.hLine);X?u(A,$.col,l.cornerTR):u(A,$.col,l.cornerTL);for(let D=A+1;D<=$.row;D++)u(D,$.col,l.vLine)}}function xr(t,e,n,o,s,r,i,a){let c=[],l=0,d=0;for(let g=0;g<o.series.length;g++)o.series[g].type==="bar"?(c.push({symbol:i.bar,label:`Bar ${l+1}`,globalIdx:g}),l++):(c.push({symbol:i.hLine,label:`Line ${d+1}`,globalIdx:g}),d++);let h=0;for(let g=0;g<c.length;g++)g>0&&(h+=2),h+=2+c[g].label.length;let u=Math.max(0,Math.floor(r/2-h/2));for(let g=0;g<c.length;g++){g>0&&(u+=2);let p=c[g];Dt(t,e,s,u,p.symbol,"arrow",n,a[p.globalIdx]),u+=1,u+=1,Kt(t,e,s,u,p.label,"text"),u+=p.label.length}}function br(t,e){return Array.from({length:t},()=>Array.from({length:e},()=>" "))}function yr(t,e){return Array.from({length:t},()=>Array.from({length:e}).fill(null))}function $r(t,e){return Array.from({length:t},()=>Array.from({length:e}).fill(null))}function Dt(t,e,n,o,s,r,i,a){o>=0&&o<t.length&&n>=0&&n<t[0].length&&(t[o][n]=s,e[o][n]=r,i&&a&&(i[o][n]=a))}function Cr(t,e,n){return n>=0&&n<t.length&&e>=0&&e<t[0].length?t[n][e]:" "}function Kt(t,e,n,o,s,r){for(let i=0;i<s.length;i++)Dt(t,e,n,o+i,s[i],r)}function wr(t,e,n,o,s){if(t.length===0)return"";let r=t[0].length,i=t.length,a=[];for(let c=0;c<r;c++){let l=[],d=[],h=[];for(let u=0;u<i;u++)l.push(t[u][c]),d.push(e[u][c]),h.push(n[u][c]);let f=l.length-1;for(;f>=0&&l[f]===" ";)f--;f<0?a.push(""):a.push(Zi(l.slice(0,f+1),d.slice(0,f+1),h.slice(0,f+1),s,o))}for(;a.length>0&&a[a.length-1]==="";)a.pop();return a.join(`
95`)}function Zi(t,e,n,o,s){if(s==="none")return t.join("");let r="",i=null,a="";for(let c=0;c<t.length;c++){let l=t[c];if(l===" "){a.length>0&&(r+=i?Me(a,i,s):a,a="",i=null),r+=" ";continue}let d=n[c]??null,h=e[c]??null,f=d??(h?Ui(h,o):null);f===i?a+=l:(a.length>0&&(r+=i?Me(a,i,s):a),a=l,i=f)}return a.length>0&&(r+=i?Me(a,i,s):a),r}function Mr(t){if(t.xAxis.categories)return t.xAxis.categories.length;for(let e of t.series)if(e.data.length>0)return e.data.length;return 0}function Ar(t,e){if(t.xAxis.categories)return t.xAxis.categories;if(t.xAxis.range){let{min:n,max:o}=t.xAxis.range,s=e>1?(o-n)/(e-1):0;return Array.from({length:e},(r,i)=>De(n+s*i))}return Array.from({length:e},(n,o)=>String(o+1))}function vr(t,e){let n=e-t;if(n<=0)return[t];let o=n/6,s=Math.pow(10,Math.floor(Math.log10(o))),r=o/s,i;r<=1.5?i=s:r<=3?i=2*s:r<=7?i=5*s:i=10*s;let a=Math.ceil(t/i)*i,c=[];for(let l=a;l<=e+i*.001;l+=i)c.push(Math.round(l*1e10)/1e10);return c}function De(t){return Number.isInteger(t)?String(t):t.toFixed(Math.abs(t)<10?1:0)}function ts(t){let e=t.trim().split(`
96`)[0]?.trim().toLowerCase()??"";return/^xychart(-beta)?\b/.test(e)?"xychart":/^sequencediagram\s*$/.test(e)?"sequence":/^classdiagram\s*$/.test(e)?"class":/^erdiagram\s*$/.test(e)?"er":"flowchart"}function es(t,e={}){let n={useAscii:e.useAscii??!1,paddingX:e.paddingX??5,paddingY:e.paddingY??5,boxBorderPadding:e.boxBorderPadding??1,graphDirection:"TD"},o=e.colorMode==="auto"||e.colorMode===void 0?mn():e.colorMode,s={...Ce,...e.theme};switch(ts(t)){case"xychart":return pr(t,n,o,s);case"sequence":return ir(t,n,o,s);case"class":return lr(t,n,o,s);case"er":return ur(t,n,o,s);default:{let i=Ie(t);i.direction==="LR"||i.direction==="RL"?n.graphDirection="LR":n.graphDirection="TD";let a=kn(i,n);return or(a),tr(a),i.direction==="BT"&&(vn(a.canvas),Sn(a.roleCanvas)),te(a.canvas,{roleCanvas:a.roleCanvas,colorMode:o,theme:s})}}}var ns=es;export{ct as FONT_SIZES,bt as FONT_WEIGHTS,Jr as NODE_PADDING,Co as layoutSequenceDiagram,Lo as layoutXYChart,Te as measureMultilineText,Ie as parseMermaid,Ee as parseSequenceDiagram,Ye as parseXYChart,ns as renderMermaidAscii,wo as renderSequenceSvg,Vr as renderSvg,Go as renderXYChartSvg};
97types/index.d.ts 16 lines1export type DiagramView = { source: string; zoom: number; x: number; y: number }
2
3export type Todo = { content: string; status: 'pending' | 'in_progress' | 'completed'; activeForm?: string }
4export type TrackedAgent = { id: string; type: string; label: string; isDone: boolean }
5export type TrackedTask = { id: string; subject: string; isDone: boolean }
6export type Reading = { tokens: number; window: number; percent: number }
7export type Limit = { kind: string; percentUsed: number; resetsAt?: string }
8export type Weather = { readings: Reading[]; limits: Limit[] }
9export type Progress = { agents: TrackedAgent[]; queued: { type: string; label: string }[]; tasks: TrackedTask[]; todos: Todo[] }
10
11declare module 'claude-code' {
12 interface PluginState {
13 colorwheel: { view: DiagramView | null; progress: Progress; weather: Weather; inverted: boolean }
14 }
15}
16