envprism 0.3.0 → 0.3.1-dev-main.64-e7adf59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -43
- package/dist/bin/envprism.mjs +254 -262
- package/dist/bin/envprism.mjs.map +1 -1
- package/dist/chunks/app-Bp7QXiLx.mjs +1965 -0
- package/dist/chunks/app-Bp7QXiLx.mjs.map +1 -0
- package/dist/chunks/matrix-CG1Msljr.mjs +740 -0
- package/dist/chunks/matrix-CG1Msljr.mjs.map +1 -0
- package/dist/chunks/serialize-DWF9VxrS.mjs +59 -0
- package/dist/chunks/serialize-DWF9VxrS.mjs.map +1 -0
- package/dist/config/define.mjs +14 -5
- package/dist/config/define.mjs.map +1 -1
- package/dist/index.mjs +3 -18
- package/package.json +18 -18
- package/dist/chunks/app-DgjyG_HE.mjs +0 -1800
- package/dist/chunks/app-DgjyG_HE.mjs.map +0 -1
- package/dist/chunks/matrix-C1pErf9Z.mjs +0 -676
- package/dist/chunks/matrix-C1pErf9Z.mjs.map +0 -1
- package/dist/chunks/serialize-D_ZNIgRa.mjs +0 -41
- package/dist/chunks/serialize-D_ZNIgRa.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-Bp7QXiLx.mjs","names":[],"sources":["../../src/tui/grouping.ts","../../src/tui/envfile.ts","../../src/tui/state/visible.ts","../../src/tui/actions/batch.ts","../../src/tui/actions/io.ts","../../src/tui/types.ts","../../src/tui/actions/prompt.ts","../../src/tui/keys/browse.ts","../../src/tui/keys/filter.ts","../../src/tui/keys/help.ts","../../src/tui/keys/prompt.ts","../../src/tui/keys/onKey.ts","../../src/tui/render/layout.ts","../../src/tui/render/filter.ts","../../src/tui/render/dom.ts","../../src/tui/render/footer.ts","../../src/tui/help.ts","../../src/tui/render/builders.ts","../../src/tui/render/help.ts","../../src/tui/render/matrix.ts","../../src/tui/render/prompt.ts","../../src/tui/render/sidebar.ts","../../src/tui/render/index.ts","../../src/tui/theme.ts","../../src/tui/app.ts"],"sourcesContent":["import type { Matrix } from '@/core/matrix.ts';\nimport { matchesFilter } from '@tui/format.ts';\nimport type { State } from '@tui/types.ts';\n\n// Lookup name for keys/sections that have no banner or prefix bucket.\nexport const SECTION_COLLAPSE_KEY = '__other__';\n\nexport function prefixSection(key: string): string | undefined {\n const idx = key.indexOf('_');\n if (idx <= 0) return undefined;\n return key.slice(0, idx);\n}\n\n/**\n * Sort by first-underscore-prefix while preserving the relative order each\n * prefix first appeared in. Keys without an underscore land in a trailing\n * \"Other\" group keeping their authored order.\n */\nexport function groupByPrefix(keys: string[]): string[] {\n const groups = new Map<string, string[]>();\n const order: string[] = [];\n const OTHER = SECTION_COLLAPSE_KEY;\n for (const k of keys) {\n const p = prefixSection(k) ?? OTHER;\n let bucket = groups.get(p);\n if (!bucket) {\n bucket = [];\n groups.set(p, bucket);\n if (p !== OTHER) order.push(p);\n }\n bucket.push(k);\n }\n if (groups.has(OTHER)) order.push(OTHER);\n return order.flatMap((p) => groups.get(p)!);\n}\n\n/**\n * Move row focus by `delta` while skipping section dividers that are not\n * collapsed. The user only needs to land on a divider when its section is\n * folded — that's the only context in which 'c' on the divider does work\n * the focused-key path doesn't already cover.\n */\nexport function stepRow(state: State, delta: number): number {\n const items = state.visibleItems;\n if (items.length === 0) return 0;\n const canFocus = (i: number) => {\n const it = items[i];\n if (!it) return false;\n if (it.kind === 'key') return true;\n // divider — focusable only when collapsed\n return state.collapsed.has(it.ref);\n };\n let i = state.rowIdx + delta;\n while (i >= 0 && i < items.length) {\n if (canFocus(i)) return i;\n i += delta;\n }\n // No focusable item further along — clamp to current.\n return state.rowIdx;\n}\n\nexport function orderedKeys(\n matrix: Matrix,\n state: State,\n sectionOf: (key: string) => string | undefined\n): string[] {\n void sectionOf;\n const filtered = matrix.keys.filter((k) => {\n if (!matchesFilter(k, state.filter)) return false;\n if (state.driftOnly && !keyDrifts(matrix, k)) return false;\n return true;\n });\n return state.grouping === 'prefix' ? groupByPrefix(filtered) : filtered;\n}\n\nexport interface SectionStats {\n drift: number;\n missing: number;\n total: number;\n}\n\nexport function sectionMetadata(\n matrix: Matrix,\n sectionOf: (key: string) => string | undefined,\n state: State\n): Map<string, SectionStats> {\n const out = new Map<string, SectionStats>();\n for (const key of orderedKeys(matrix, state, sectionOf)) {\n const k = sectionOf(key) ?? SECTION_COLLAPSE_KEY;\n const bucket = out.get(k) ?? { drift: 0, missing: 0, total: 0 };\n bucket.total += 1;\n let drifts = false;\n let missing = false;\n for (const file of matrix.files) {\n if (file === matrix.base) continue;\n const s = matrix.cell(key, file).state;\n if (s === 'missing') missing = true;\n if (s === 'differs' || s === 'missing' || s === 'extra') drifts = true;\n }\n if (drifts) bucket.drift += 1;\n if (missing) bucket.missing += 1;\n out.set(k, bucket);\n }\n return out;\n}\n\nexport function keyDrifts(matrix: Matrix, key: string): boolean {\n for (const file of matrix.files) {\n if (file === matrix.base) continue;\n const s = matrix.cell(key, file).state;\n if (s === 'differs' || s === 'missing' || s === 'extra') return true;\n }\n return false;\n}\n","import { basename } from 'pathe';\nimport { rebuildKvLine } from '@/core/serialize.ts';\nimport type { EnvFile, KvEntry } from '@/core/types.ts';\n\nexport function isValidEnvFileName(name: string): boolean {\n if (!name.startsWith('.env')) return false;\n if (name.includes('/') || name.includes('\\\\')) return false;\n if (name.endsWith('.swp') || name.endsWith('~') || name.endsWith('.bak'))\n return false;\n return true;\n}\n\nexport function createEmptyEnvFile(path: string): EnvFile {\n return {\n path,\n entries: [{ kind: 'comment', raw: `# ${basename(path)}` }],\n trailingNewline: true\n };\n}\n\nexport function appendKv(file: EnvFile, key: string, value: string): KvEntry {\n const entry: KvEntry = {\n kind: 'kv',\n key,\n rawValue: '',\n value,\n quoting: 'none',\n exportPrefix: false,\n inlineComment: '',\n raw: ''\n };\n rebuildKvLine(entry);\n file.entries.push(entry);\n // Round-trip semantics: serializeEnv joins with \\n and appends a trailing\n // newline if trailingNewline is set. Push alone gives us \"...\\nKEY=val\" when\n // trailingNewline=false, or \"...\\nKEY=val\\n\" when true. Either case is\n // sane; we make sure the file ends with a newline so editors don't complain.\n file.trailingNewline = true;\n return entry;\n}\n","import { buildMatrix } from '@/core/matrix.ts';\nimport type { EnvFile } from '@/core/types.ts';\nimport type { TuiContext } from '@tui/context.ts';\nimport { matchesFilter } from '@tui/format.ts';\nimport {\n keyDrifts,\n orderedKeys,\n SECTION_COLLAPSE_KEY,\n stepRow\n} from '@tui/grouping.ts';\nimport type { MatrixItem, UndoEntry } from '@tui/types.ts';\n\nexport function cellKey(key: string, file: EnvFile): string {\n return `${key}|${file.path}`;\n}\n\nexport function markModified(\n ctx: TuiContext,\n key: string,\n file: EnvFile\n): void {\n ctx.state.modified.add(cellKey(key, file));\n}\n\nexport function pushUndo(ctx: TuiContext, entry: UndoEntry): void {\n ctx.state.undo.push(entry);\n if (ctx.state.undo.length > ctx.config.tui.undoLimit) ctx.state.undo.shift();\n}\n\nexport function focusedKey(ctx: TuiContext): string | null {\n const item = ctx.state.visibleItems[ctx.state.rowIdx];\n return item && item.kind === 'key' ? item.ref : null;\n}\n\nexport function focusKey(ctx: TuiContext, key: string): void {\n const idx = ctx.state.visibleKeys.indexOf(key);\n if (idx >= 0) ctx.state.rowIdx = idx;\n}\n\nexport function recomputeVisibleKeys(ctx: TuiContext): void {\n const { state } = ctx;\n // Two parallel structures:\n // visibleKeys — just the key names (used by editing helpers)\n // visibleItems — dividers + visible keys, in render order\n // Dividers stay in the item list even when their section is collapsed,\n // so the user can navigate onto one and expand it with 'c'.\n const visibleKeys: string[] = [];\n const items: MatrixItem[] = [];\n const orderedAll = orderedKeys(ctx.matrix, state, ctx.sectionOf);\n const seen = new Set<string>();\n const focusedRef = state.visibleItems[state.rowIdx]?.ref;\n for (const k of orderedAll) {\n if (!matchesFilter(k, state.filter)) continue;\n if (state.driftOnly && !keyDrifts(ctx.matrix, k)) continue;\n const secKey = ctx.sectionOf(k) ?? SECTION_COLLAPSE_KEY;\n if (!seen.has(secKey)) {\n seen.add(secKey);\n items.push({ kind: 'divider', ref: secKey });\n }\n if (state.collapsed.has(secKey)) continue;\n items.push({ kind: 'key', ref: k });\n visibleKeys.push(k);\n }\n state.visibleKeys = visibleKeys;\n state.visibleItems = items;\n // Try to keep focus on the same item across rebuilds.\n if (focusedRef) {\n const i = items.findIndex((it) => it.ref === focusedRef);\n if (i >= 0) state.rowIdx = i;\n }\n if (state.rowIdx >= items.length) {\n state.rowIdx = Math.max(0, items.length - 1);\n }\n // Make sure we don't land on an expanded divider after a rebuild.\n if (\n items[state.rowIdx]?.kind === 'divider' &&\n !state.collapsed.has(items[state.rowIdx]!.ref)\n ) {\n const next = stepRow(state, 1);\n const prev = stepRow(state, -1);\n state.rowIdx = next !== state.rowIdx ? next : prev;\n }\n}\n\nexport function rebuildMatrix(ctx: TuiContext): void {\n const { state } = ctx;\n const enabledList = ctx.allFiles.filter((f) => state.enabled.has(f));\n if (!state.enabled.has(ctx.currentBase)) {\n // Base got disabled — promote the first enabled file.\n const next = enabledList[0];\n if (next) ctx.currentBase = next;\n }\n ctx.matrix = buildMatrix(enabledList, ctx.currentBase);\n if (state.colIdx >= ctx.matrix.files.length) {\n state.colIdx = Math.max(0, ctx.matrix.files.length - 1);\n }\n if (state.sidebarIdx >= ctx.allFiles.length) {\n state.sidebarIdx = Math.max(0, ctx.allFiles.length - 1);\n }\n recomputeVisibleKeys(ctx);\n}\n","import { rebuildKvLine } from '@/core/serialize.ts';\nimport { basename } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\nimport { appendKv } from '@tui/envfile.ts';\nimport { findKvEntry } from '@tui/format.ts';\nimport {\n focusedKey,\n markModified,\n pushUndo,\n rebuildMatrix\n} from '@tui/state/visible.ts';\n\nexport function applyToAllFiles(\n ctx: TuiContext,\n key: string,\n value: string\n): number {\n // Set key=value in every enabled file. Used by '=' in the matrix and\n // Ctrl-A from the edit prompt. Each per-file mutation is undone\n // individually (one Ctrl-Z per file) — not perfect but predictable.\n const { state } = ctx;\n let touched = 0;\n for (const file of ctx.matrix.files) {\n const existing = findKvEntry(file, key);\n if (existing) {\n if (existing.value === value) continue;\n pushUndo(ctx, {\n kind: 'edit',\n file,\n entry: existing,\n prevValue: existing.value,\n prevRaw: existing.raw\n });\n existing.value = value;\n rebuildKvLine(existing);\n } else {\n const added = appendKv(file, key, value);\n pushUndo(ctx, { kind: 'add-kv', file, entry: added });\n }\n state.dirty.add(file);\n markModified(ctx, key, file);\n touched++;\n }\n return touched;\n}\n\nexport function syncToAll(ctx: TuiContext): void {\n const { state } = ctx;\n const key = focusedKey(ctx);\n const file = ctx.matrix.files[state.colIdx];\n if (!key || !file) {\n state.message = 'Move onto a variable row to sync.';\n ctx.refresh();\n return;\n }\n const entry = findKvEntry(file, key);\n if (!entry) {\n state.message = `${key} has no value in ${basename(file.path)} to sync.`;\n ctx.refresh();\n return;\n }\n const touched = applyToAllFiles(ctx, key, entry.value);\n rebuildMatrix(ctx);\n state.message =\n touched > 0\n ? `Synced ${key} to ${touched} file(s). Ctrl-S to save.`\n : `${key} is already in sync.`;\n ctx.refresh();\n}\n\nexport function undo(ctx: TuiContext): void {\n const { state } = ctx;\n const last = state.undo.pop();\n if (!last) {\n state.message = 'Nothing to undo.';\n ctx.refresh();\n return;\n }\n switch (last.kind) {\n case 'edit':\n last.entry.value = last.prevValue;\n last.entry.raw = last.prevRaw;\n state.dirty.add(last.file);\n state.message = `Undid edit on ${last.entry.key} in ${basename(last.file.path)}.`;\n break;\n case 'add-kv': {\n const i = last.file.entries.indexOf(last.entry);\n if (i >= 0) last.file.entries.splice(i, 1);\n state.dirty.add(last.file);\n state.message = `Undid add of ${last.entry.key} in ${basename(last.file.path)}.`;\n break;\n }\n case 'delete-kv':\n last.file.entries.splice(last.idx, 0, last.entry);\n state.dirty.add(last.file);\n state.message = `Undid delete of ${last.entry.key} in ${basename(last.file.path)}.`;\n break;\n }\n rebuildMatrix(ctx);\n ctx.refresh();\n}\n\nexport function toggleEnabled(ctx: TuiContext): void {\n const { state } = ctx;\n const file = ctx.allFiles[state.sidebarIdx];\n if (!file) return;\n if (state.enabled.has(file)) {\n if (state.enabled.size === 1) {\n state.message = 'At least one file must stay enabled.';\n ctx.refresh();\n return;\n }\n state.enabled.delete(file);\n state.message = `Hidden ${basename(file.path)} from the matrix.`;\n } else {\n state.enabled.add(file);\n state.message = `Showing ${basename(file.path)} in the matrix.`;\n }\n rebuildMatrix(ctx);\n ctx.refresh();\n}\n\nexport function setBase(ctx: TuiContext): void {\n const { state } = ctx;\n const file = ctx.allFiles[state.sidebarIdx];\n if (!file) return;\n if (file === ctx.currentBase) {\n state.message = `${basename(file.path)} is already the base.`;\n ctx.refresh();\n return;\n }\n const wasDisabled = !state.enabled.has(file);\n if (wasDisabled) state.enabled.add(file);\n ctx.currentBase = file;\n rebuildMatrix(ctx);\n state.message = wasDisabled\n ? `${basename(file.path)} is now the base (re-enabled).`\n : `${basename(file.path)} is now the base.`;\n ctx.refresh();\n}\n","import { writeFile } from 'node:fs/promises';\nimport { serializeEnv } from '@/core/serialize.ts';\nimport { basename } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\n\nexport async function saveDirty(ctx: TuiContext): Promise<void> {\n const { state } = ctx;\n if (state.dirty.size === 0) {\n state.message = 'Nothing to save.';\n ctx.refresh();\n return;\n }\n const count = state.dirty.size;\n const errors: string[] = [];\n for (const file of state.dirty) {\n try {\n await writeFile(file.path, serializeEnv(file), 'utf8');\n } catch (err) {\n errors.push(\n `${basename(file.path)}: ${(err as Error).message ?? String(err)}`\n );\n }\n }\n if (errors.length === 0) {\n state.dirty.clear();\n state.modified.clear();\n state.message = `Saved ${count} file${count === 1 ? '' : 's'}.`;\n } else {\n state.message = `Save failed: ${errors.join('; ')}`;\n }\n ctx.refresh();\n}\n","import type { RGBA } from '@opentui/core';\nimport type { EnvFile, KvEntry } from '@/core/types.ts';\n\nexport type Mode = 'browse' | 'filter' | 'prompt';\n\nexport type Prompt =\n | { kind: 'edit'; key: string; file: EnvFile }\n | { kind: 'add-key'; file: EnvFile }\n | { kind: 'add-value'; key: string; file: EnvFile }\n | { kind: 'new-file' };\n\nexport type Grouping = 'banner' | 'prefix';\n\nexport type UndoEntry =\n | {\n kind: 'edit';\n file: EnvFile;\n entry: KvEntry;\n prevValue: string;\n prevRaw: string;\n }\n | { kind: 'add-kv'; file: EnvFile; entry: KvEntry }\n | { kind: 'delete-kv'; file: EnvFile; entry: KvEntry; idx: number };\n\nexport type Pane = 'matrix' | 'sidebar';\n\nexport type ItemKind = 'key' | 'divider';\nexport interface MatrixItem {\n kind: ItemKind;\n // For 'key': the variable name; for 'divider': the section's lookup name\n // (or '__other__'). Holding the raw key/section here keeps focus stable\n // across rebuilds.\n ref: string;\n}\n\nexport interface State {\n mode: Mode;\n filter: string;\n rowIdx: number;\n colIdx: number;\n prompt: Prompt | null;\n dirty: Set<EnvFile>;\n visibleKeys: string[]; // kept for callers that just want the keys\n visibleItems: MatrixItem[];\n message: string | null;\n driftOnly: boolean;\n confirmQuit: boolean;\n grouping: Grouping;\n helpOpen: boolean;\n undo: UndoEntry[];\n pane: Pane;\n sidebarIdx: number;\n enabled: Set<EnvFile>;\n showSecrets: boolean;\n collapsed: Set<string>;\n // (key + \"|\" + file.path) of cells the user has touched in this session.\n // Drives a green ● marker so unsaved local changes are visually distinct\n // from \"this file disagrees with base\", which uses the diff icons.\n modified: Set<string>;\n // Current value of the prompt input. We accumulate characters ourselves\n // in the global key handler instead of relying on opentui's InputRenderable,\n // because the InputRenderable swallows Esc (it interprets it as \"blur\").\n promptInput: string;\n}\n\nexport const KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport type HelpLine =\n | { kind: 'header'; text: string }\n | { kind: 'entry'; text: string }\n | { kind: 'legend'; symbol: string; color: RGBA; description: string }\n | { kind: 'blank' };\n","import { rebuildKvLine } from '@/core/serialize.ts';\nimport { basename, dirname, join } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\nimport {\n appendKv,\n createEmptyEnvFile,\n isValidEnvFileName\n} from '@tui/envfile.ts';\nimport { findKvEntry } from '@tui/format.ts';\nimport {\n focusedKey,\n focusKey,\n markModified,\n pushUndo,\n rebuildMatrix\n} from '@tui/state/visible.ts';\nimport { KEY_RE, type Prompt } from '@tui/types.ts';\n\nexport function openPrompt(ctx: TuiContext, prompt: Prompt, value = ''): void {\n const { state } = ctx;\n state.prompt = prompt;\n state.mode = 'prompt';\n state.message = null;\n state.promptInput = value;\n ctx.refresh();\n}\n\nexport function closePrompt(ctx: TuiContext, msg: string | null = null): void {\n const { state } = ctx;\n state.prompt = null;\n state.mode = 'browse';\n state.promptInput = '';\n state.message = msg;\n ctx.refresh();\n}\n\nexport function cancelPrompt(ctx: TuiContext): void {\n closePrompt(ctx, 'Cancelled.');\n}\n\nexport function startEdit(ctx: TuiContext): void {\n const { state } = ctx;\n const key = focusedKey(ctx);\n const file = ctx.matrix.files[state.colIdx];\n if (!key || !file) {\n state.message = 'Move onto a variable row to edit.';\n ctx.refresh();\n return;\n }\n // Edit works on missing cells too — on commit we either update the\n // existing entry or append a new one.\n const entry = findKvEntry(file, key);\n openPrompt(ctx, { kind: 'edit', key, file }, entry?.value ?? '');\n}\n\nexport function startAdd(ctx: TuiContext): void {\n const file = ctx.matrix.files[ctx.state.colIdx];\n if (!file) return;\n openPrompt(ctx, { kind: 'add-key', file });\n}\n\nexport function startNewFile(ctx: TuiContext): void {\n openPrompt(ctx, { kind: 'new-file' });\n}\n\nexport function startDelete(ctx: TuiContext): void {\n const { state } = ctx;\n const key = focusedKey(ctx);\n const file = ctx.matrix.files[state.colIdx];\n if (!key || !file) {\n state.message = 'Move onto a variable row to delete.';\n ctx.refresh();\n return;\n }\n const entry = findKvEntry(file, key);\n if (!entry) {\n state.message = `${key} is not present in ${basename(file.path)}.`;\n ctx.refresh();\n return;\n }\n const idx = file.entries.indexOf(entry);\n if (idx >= 0) {\n pushUndo(ctx, { kind: 'delete-kv', file, entry, idx });\n file.entries.splice(idx, 1);\n }\n state.dirty.add(file);\n markModified(ctx, key, file);\n rebuildMatrix(ctx);\n state.message = `Deleted ${key} from ${basename(file.path)}. Ctrl-S to save.`;\n ctx.refresh();\n}\n\nexport function commitPrompt(ctx: TuiContext): void {\n const { state } = ctx;\n if (!state.prompt) return;\n const p = state.prompt;\n const raw = state.promptInput;\n\n if (p.kind === 'edit') {\n const existing = findKvEntry(p.file, p.key);\n if (existing) {\n pushUndo(ctx, {\n kind: 'edit',\n file: p.file,\n entry: existing,\n prevValue: existing.value,\n prevRaw: existing.raw\n });\n existing.value = raw;\n rebuildKvLine(existing);\n state.dirty.add(p.file);\n markModified(ctx, p.key, p.file);\n rebuildMatrix(ctx);\n closePrompt(\n ctx,\n `Edited ${p.key} in ${basename(p.file.path)}. Ctrl-S to save.`\n );\n } else {\n // Missing cell: add the key with the typed value.\n const added = appendKv(p.file, p.key, raw);\n pushUndo(ctx, { kind: 'add-kv', file: p.file, entry: added });\n state.dirty.add(p.file);\n markModified(ctx, p.key, p.file);\n rebuildMatrix(ctx);\n closePrompt(\n ctx,\n `Added ${p.key} to ${basename(p.file.path)}. Ctrl-S to save.`\n );\n }\n return;\n }\n\n if (p.kind === 'add-key') {\n const key = raw.trim();\n if (!KEY_RE.test(key)) {\n state.message = `Invalid key \"${key}\". Must match ${KEY_RE.source}.`;\n ctx.refresh();\n return;\n }\n if (findKvEntry(p.file, key)) {\n state.message = `${key} already exists in ${basename(p.file.path)}. Use edit instead.`;\n ctx.refresh();\n return;\n }\n openPrompt(ctx, { kind: 'add-value', key, file: p.file });\n return;\n }\n\n if (p.kind === 'add-value') {\n const added = appendKv(p.file, p.key, raw);\n pushUndo(ctx, { kind: 'add-kv', file: p.file, entry: added });\n state.dirty.add(p.file);\n markModified(ctx, p.key, p.file);\n rebuildMatrix(ctx);\n focusKey(ctx, p.key);\n state.colIdx = ctx.matrix.files.indexOf(p.file);\n closePrompt(\n ctx,\n `Added ${p.key} to ${basename(p.file.path)}. Ctrl-S to save.`\n );\n return;\n }\n\n if (p.kind === 'new-file') {\n const name = raw.trim();\n if (!isValidEnvFileName(name)) {\n state.message =\n name.length === 0\n ? 'Filename cannot be empty.'\n : !name.startsWith('.env')\n ? `Filename must start with \".env\" (got \"${name}\").`\n : `\"${name}\" is not a valid env filename.`;\n ctx.refresh();\n return;\n }\n const newPath = join(dirname(ctx.currentBase.path), name);\n if (ctx.allFiles.some((f) => f.path === newPath)) {\n state.message = `${name} already exists.`;\n ctx.refresh();\n return;\n }\n const newFile = createEmptyEnvFile(newPath);\n ctx.allFiles.push(newFile);\n state.enabled.add(newFile);\n state.dirty.add(newFile);\n rebuildMatrix(ctx);\n state.colIdx = ctx.matrix.files.indexOf(newFile);\n closePrompt(ctx, `Created ${name}. Ctrl-S to write to disk.`);\n return;\n }\n}\n","import { setBase, syncToAll, toggleEnabled, undo } from '@tui/actions/batch.ts';\nimport { saveDirty } from '@tui/actions/io.ts';\nimport {\n startAdd,\n startDelete,\n startEdit,\n startNewFile\n} from '@tui/actions/prompt.ts';\nimport type { TuiContext } from '@tui/context.ts';\nimport { SECTION_COLLAPSE_KEY, stepRow } from '@tui/grouping.ts';\nimport type { KeyEvent } from '@tui/keys/event.ts';\nimport { recomputeVisibleKeys } from '@tui/state/visible.ts';\n\nexport function handleBrowseKey(\n ctx: TuiContext,\n key: KeyEvent,\n cleanup: () => void\n): void {\n const { state } = ctx;\n const refresh = ctx.refresh;\n\n if (key.ctrl && key.name === 'c') return cleanup();\n if (key.ctrl && key.name === 's') {\n state.confirmQuit = false;\n return void saveDirty(ctx);\n }\n if (key.ctrl && key.name === 'z') {\n state.confirmQuit = false;\n return undo(ctx);\n }\n if (key.ctrl && key.name === 't') {\n state.showSecrets = !state.showSecrets;\n state.message = state.showSecrets\n ? 'Showing secret values in plain text.'\n : 'Masking secret values.';\n return refresh();\n }\n\n const tryQuit = () => {\n if (state.dirty.size > 0 && !state.confirmQuit) {\n state.confirmQuit = true;\n state.message = `${state.dirty.size} unsaved file(s). Press 'q' again to quit without saving, or Ctrl-S to save first.`;\n refresh();\n return;\n }\n cleanup();\n };\n // Any key other than q clears a pending quit confirmation.\n if (state.confirmQuit && key.name !== 'q') {\n state.confirmQuit = false;\n state.message = null;\n }\n\n if (state.pane === 'sidebar') {\n switch (key.name) {\n case 'q':\n return tryQuit();\n case 'tab':\n state.pane = 'matrix';\n return refresh();\n case 'right':\n state.pane = 'matrix';\n return refresh();\n case 'up':\n state.sidebarIdx = Math.max(0, state.sidebarIdx - 1);\n return refresh();\n case 'down':\n state.sidebarIdx = Math.min(\n ctx.allFiles.length - 1,\n state.sidebarIdx + 1\n );\n return refresh();\n case 'space':\n return toggleEnabled(ctx);\n case 'b':\n return setBase(ctx);\n }\n if (key.sequence === ' ') return toggleEnabled(ctx);\n if (key.sequence === '?' || key.sequence === 'ß') {\n state.helpOpen = true;\n return refresh();\n }\n return;\n }\n\n switch (key.name) {\n case 'q':\n return tryQuit();\n case 'tab':\n state.pane = 'sidebar';\n return refresh();\n case 'up':\n state.rowIdx = stepRow(state, -1);\n return refresh();\n case 'down':\n state.rowIdx = stepRow(state, 1);\n return refresh();\n case 'left':\n if (state.colIdx === 0) {\n // Already at the leftmost matrix column — hand focus to the sidebar.\n state.pane = 'sidebar';\n return refresh();\n }\n state.colIdx = Math.max(0, state.colIdx - 1);\n return refresh();\n case 'right':\n state.colIdx = Math.min(ctx.matrix.files.length - 1, state.colIdx + 1);\n return refresh();\n case 'e':\n case 'return':\n return startEdit(ctx);\n case 'a':\n return startAdd(ctx);\n case 'd':\n return startDelete(ctx);\n case 'n':\n return startNewFile(ctx);\n case 'v':\n state.driftOnly = !state.driftOnly;\n state.message = state.driftOnly\n ? 'Drift-only view (only keys with differences).'\n : 'Full view.';\n recomputeVisibleKeys(ctx);\n return refresh();\n case 'c': {\n if (key.shift) {\n // Capital C — expand every collapsed section. Use this when all\n // keys you'd navigate to are hidden behind a fold.\n if (state.collapsed.size === 0) {\n state.message = 'Nothing collapsed.';\n return refresh();\n }\n const count = state.collapsed.size;\n state.collapsed.clear();\n state.message = `Expanded ${count} section(s).`;\n recomputeVisibleKeys(ctx);\n return refresh();\n }\n // Collapse / expand the section of the focused item. Works on\n // both key rows and section dividers; on a divider this is the\n // only way back into a collapsed section.\n const item = state.visibleItems[state.rowIdx];\n if (!item) return;\n const sectionKey =\n item.kind === 'divider'\n ? item.ref\n : (ctx.sectionOf(item.ref) ?? SECTION_COLLAPSE_KEY);\n const label =\n sectionKey === SECTION_COLLAPSE_KEY ? '(other)' : sectionKey;\n if (state.collapsed.has(sectionKey)) {\n state.collapsed.delete(sectionKey);\n state.message = `Expanded \"${label}\".`;\n } else {\n state.collapsed.add(sectionKey);\n state.message = `Collapsed \"${label}\". Press Shift-C to expand all.`;\n }\n recomputeVisibleKeys(ctx);\n return refresh();\n }\n case 'g': {\n // Preserve focus across the rebuild — focusedRef in\n // recomputeVisibleKeys finds the same item by ref.\n state.grouping = state.grouping === 'banner' ? 'prefix' : 'banner';\n recomputeVisibleKeys(ctx);\n state.message =\n state.grouping === 'banner'\n ? 'Group by comment banners.'\n : 'Group by key prefix (first underscore segment).';\n return refresh();\n }\n }\n\n if (key.sequence === '/' || key.name === 'slash') {\n state.mode = 'filter';\n state.message = null;\n refresh();\n return;\n }\n\n // = sync-to-all. opentui's key.name for \"=\" is inconsistent across\n // platforms so we check the sequence directly.\n if (key.sequence === '=') return syncToAll(ctx);\n\n if (key.sequence === '?' || key.sequence === 'ß') {\n state.helpOpen = true;\n refresh();\n }\n}\n","import type { TuiContext } from '@tui/context.ts';\nimport type { KeyEvent } from '@tui/keys/event.ts';\nimport { recomputeVisibleKeys } from '@tui/state/visible.ts';\n\nexport function handleFilterKey(ctx: TuiContext, key: KeyEvent): void {\n const { state } = ctx;\n if (key.name === 'escape') {\n state.filter = '';\n state.mode = 'browse';\n recomputeVisibleKeys(ctx);\n ctx.refresh();\n return;\n }\n if (key.name === 'return') {\n state.mode = 'browse';\n ctx.refresh();\n return;\n }\n if (key.name === 'backspace') {\n if (state.filter.length > 0) {\n state.filter = state.filter.slice(0, -1);\n recomputeVisibleKeys(ctx);\n ctx.refresh();\n }\n return;\n }\n // Append any printable character. opentui's KeyEvent puts the actual\n // char into `sequence` for normal keystrokes.\n const seq = key.sequence ?? '';\n if (seq.length === 1 && seq >= ' ' && seq !== '\\x7f') {\n state.filter += seq;\n recomputeVisibleKeys(ctx);\n ctx.refresh();\n }\n}\n","import type { TuiContext } from '@tui/context.ts';\nimport type { KeyEvent } from '@tui/keys/event.ts';\n\nexport function handleHelpKey(ctx: TuiContext, key: KeyEvent): void {\n if (\n key.name === 'escape' ||\n key.sequence === '?' ||\n key.sequence === 'ß' ||\n key.name === 'q'\n ) {\n ctx.state.helpOpen = false;\n ctx.refresh();\n }\n}\n","import { applyToAllFiles } from '@tui/actions/batch.ts';\nimport {\n cancelPrompt,\n closePrompt,\n commitPrompt\n} from '@tui/actions/prompt.ts';\nimport type { TuiContext } from '@tui/context.ts';\nimport type { KeyEvent } from '@tui/keys/event.ts';\nimport { rebuildMatrix } from '@tui/state/visible.ts';\n\nexport function handlePromptKey(ctx: TuiContext, key: KeyEvent): void {\n const { state } = ctx;\n if (key.name === 'escape') {\n cancelPrompt(ctx);\n return;\n }\n if (key.name === 'return') {\n commitPrompt(ctx);\n return;\n }\n if (key.name === 'backspace') {\n if (state.promptInput.length > 0) {\n state.promptInput = state.promptInput.slice(0, -1);\n ctx.refresh();\n }\n return;\n }\n if (key.ctrl && key.name === 't') {\n state.showSecrets = !state.showSecrets;\n ctx.refresh();\n return;\n }\n if (key.ctrl && key.name === 'a' && state.prompt) {\n const p = state.prompt;\n if (p.kind === 'edit' || p.kind === 'add-value') {\n const touched = applyToAllFiles(ctx, p.key, state.promptInput);\n rebuildMatrix(ctx);\n closePrompt(\n ctx,\n touched > 0\n ? `Set ${p.key} in ${touched} file(s). Ctrl-S to save.`\n : `${p.key} already had that value everywhere.`\n );\n }\n return;\n }\n const seq = key.sequence ?? '';\n if (!key.ctrl && seq.length === 1 && seq >= ' ' && seq !== '\\x7f') {\n state.promptInput += seq;\n ctx.refresh();\n }\n}\n","import type { TuiContext } from '@tui/context.ts';\nimport { handleBrowseKey } from '@tui/keys/browse.ts';\nimport type { KeyEvent } from '@tui/keys/event.ts';\nimport { handleFilterKey } from '@tui/keys/filter.ts';\nimport { handleHelpKey } from '@tui/keys/help.ts';\nimport { handlePromptKey } from '@tui/keys/prompt.ts';\n\n/**\n * Build the global keypress handler. Dispatches by current mode; `cleanup`\n * tears down the renderer and resolves the run promise (used by Ctrl-C and\n * the quit-confirm path in browse mode).\n */\nexport function createOnKey(\n ctx: TuiContext,\n cleanup: () => void\n): (key: KeyEvent) => void {\n return (key: KeyEvent) => {\n if (ctx.state.helpOpen) return handleHelpKey(ctx, key);\n if (ctx.state.mode === 'prompt') return handlePromptKey(ctx, key);\n if (ctx.state.mode === 'filter') return handleFilterKey(ctx, key);\n handleBrowseKey(ctx, key, cleanup);\n };\n}\n","import {\n BoxRenderable,\n type CliRenderer,\n RGBA,\n ScrollBoxRenderable,\n TextRenderable\n} from '@opentui/core';\nimport type { TuiElements } from '@tui/context.ts';\nimport type { ResolvedLayout, ResolvedTheme } from '@tui/theme.ts';\n\n/**\n * Build the static element tree once and return stable handles. Content is\n * (re)populated later by the refreshers; this only establishes the layout\n * skeleton and parent/child wiring.\n */\nexport function buildLayout(\n renderer: CliRenderer,\n theme: ResolvedTheme,\n layout: ResolvedLayout\n): TuiElements {\n const root = new BoxRenderable(renderer, {\n id: 'root',\n flexDirection: 'column',\n width: '100%',\n height: '100%'\n });\n renderer.root.add(root);\n\n const body = new BoxRenderable(renderer, {\n id: 'body',\n flexDirection: 'row',\n flexGrow: 1\n });\n root.add(body);\n\n const sidebar = new BoxRenderable(renderer, {\n id: 'sidebar',\n border: true,\n borderStyle: 'rounded',\n title: '',\n flexDirection: 'column',\n width: layout.SIDEBAR_WIDTH,\n flexShrink: 0,\n paddingX: 1\n });\n body.add(sidebar);\n\n const matrixBox = new BoxRenderable(renderer, {\n id: 'matrix',\n border: true,\n borderStyle: 'rounded',\n title: '',\n flexDirection: 'column',\n flexGrow: 1,\n paddingX: 1,\n // Reserve a row at the bottom so the ScrollBox's horizontal scrollbar\n // does not overlap the matrix box's bottom border.\n paddingBottom: 1\n });\n body.add(matrixBox);\n\n // Header sits above the scrollable region so it doesn't scroll out of view.\n const headerHost = new BoxRenderable(renderer, {\n id: 'header-host',\n flexDirection: 'column',\n flexShrink: 0,\n // Match the ScrollBox viewport padding so the header column boundaries\n // line up with the data rows below.\n paddingRight: 1\n });\n matrixBox.add(headerHost);\n\n const scrollBox = new ScrollBoxRenderable(renderer, {\n id: 'matrix-scroll',\n flexGrow: 1,\n scrollX: true,\n scrollY: true,\n // Reserve a column on the right so the vertical scrollbar doesn't sit on\n // top of cell content, and a row at the bottom for the horizontal one.\n viewportOptions: { paddingRight: 1, paddingBottom: 1 },\n contentOptions: { flexDirection: 'column', rowGap: layout.ROW_GAP }\n });\n matrixBox.add(scrollBox);\n\n const footer = new BoxRenderable(renderer, {\n id: 'footer',\n flexDirection: 'column',\n flexShrink: 0,\n paddingX: 1\n });\n root.add(footer);\n\n const hintA = new BoxRenderable(renderer, {\n id: 'hint-a',\n flexDirection: 'row',\n height: 1,\n flexShrink: 0\n });\n footer.add(hintA);\n\n const hintB = new BoxRenderable(renderer, {\n id: 'hint-b',\n flexDirection: 'row',\n height: 1,\n flexShrink: 0\n });\n footer.add(hintB);\n\n const status = new TextRenderable(renderer, {\n id: 'status',\n content: '',\n fg: theme.fgDim,\n wrapMode: 'none',\n height: 1\n });\n footer.add(status);\n\n // Filter has its own popover so we don't fight opentui's input-focus\n // behaviour. state.filter is the source of truth; characters are\n // accumulated by the global keypress handler when state.mode === 'filter'.\n const filterBox = new BoxRenderable(renderer, {\n id: 'filter-box',\n position: 'absolute',\n top: '15%',\n left: '20%',\n right: '20%',\n height: 'auto',\n zIndex: 60,\n border: true,\n borderStyle: 'rounded',\n title: ' Filter keys ',\n paddingX: 2,\n paddingY: 1,\n visible: false,\n backgroundColor: RGBA.fromHex('#1a1a1a'),\n flexDirection: 'column'\n });\n const filterField = new TextRenderable(renderer, {\n id: 'filter-field',\n content: '',\n fg: theme.fg,\n height: 1,\n wrapMode: 'none'\n });\n const filterStatus = new TextRenderable(renderer, {\n id: 'filter-status',\n content: '',\n fg: theme.fgDim,\n height: 1,\n marginTop: 1,\n wrapMode: 'none'\n });\n const filterHint = new TextRenderable(renderer, {\n id: 'filter-hint',\n content: 'Enter · keep filter Esc · clear & close',\n fg: theme.fg,\n height: 1,\n marginTop: 1,\n wrapMode: 'none'\n });\n filterBox.add(filterField);\n filterBox.add(filterStatus);\n filterBox.add(filterHint);\n renderer.root.add(filterBox);\n\n // --- Prompt modal (used for edit / add / new-file) ---\n const promptBox = new BoxRenderable(renderer, {\n id: 'prompt-box',\n position: 'absolute',\n top: '20%',\n left: '15%',\n right: '15%',\n height: 'auto',\n zIndex: 50,\n border: true,\n borderStyle: 'rounded',\n title: '',\n paddingX: 2,\n paddingY: 1,\n visible: false,\n backgroundColor: RGBA.fromHex('#1a1a1a'),\n flexDirection: 'column'\n });\n // Body of the modal is rebuilt on every refresh — either the context table\n // (edit / add-value) or just a single input row (add-key / new-file).\n const promptBody = new BoxRenderable(renderer, {\n id: 'prompt-body',\n flexDirection: 'column',\n flexGrow: 1\n });\n const promptHint = new TextRenderable(renderer, {\n id: 'prompt-hint',\n content: '',\n fg: theme.fg,\n height: 1,\n marginTop: 2,\n wrapMode: 'none'\n });\n promptBox.add(promptBody);\n promptBox.add(promptHint);\n renderer.root.add(promptBox);\n\n // Full-screen dim layer drawn below the prompt and help overlays so the\n // matrix fades back when a modal is active. Solid dark backgroundColor at\n // reduced opacity feels like a real dim/scrim.\n const dimOverlay = new BoxRenderable(renderer, {\n id: 'dim-overlay',\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 40,\n backgroundColor: RGBA.fromHex('#000000'),\n opacity: 0.6,\n visible: false\n });\n renderer.root.add(dimOverlay);\n\n // Help overlay — outer Box stays absolute-positioned; the body is rebuilt\n // every time it opens so we can switch between a one-column scrollable\n // layout (small terminals) and a two-column grid (wide terminals).\n const helpBox = new BoxRenderable(renderer, {\n id: 'help-overlay',\n position: 'absolute',\n top: 2,\n bottom: 2,\n left: '8%',\n right: '8%',\n zIndex: 100,\n border: true,\n borderStyle: 'rounded',\n title: ' Keybindings — press ? or Esc to close ',\n paddingX: 2,\n paddingY: 1,\n visible: false,\n backgroundColor: RGBA.fromHex('#1a1a1a'),\n flexDirection: 'column'\n });\n renderer.root.add(helpBox);\n\n return {\n root,\n body,\n sidebar,\n matrixBox,\n headerHost,\n scrollBox,\n footer,\n hintA,\n hintB,\n status,\n filterBox,\n filterField,\n filterStatus,\n promptBox,\n promptBody,\n promptHint,\n helpBox,\n dimOverlay\n };\n}\n","import type { TuiContext } from '@tui/context.ts';\n\nexport function refreshFilter(ctx: TuiContext): void {\n const {\n el: { filterBox, filterField, filterStatus },\n matrix,\n state\n } = ctx;\n const open = state.mode === 'filter';\n filterBox.visible = open;\n if (!open) return;\n // Show the current filter with a fake cursor at the end. visibleKeys is\n // already filtered, so its length is the live match count.\n filterField.content = `▸ ${state.filter}▏`;\n const matches = state.visibleKeys.length;\n const total = matrix.keys.length;\n filterStatus.content =\n state.filter.length === 0\n ? 'Type to filter the keys list.'\n : `Matching ${matches} of ${total} keys.`;\n}\n","import type { BoxRenderable } from '@opentui/core';\n\nexport function removeAllChildren(node: BoxRenderable): void {\n const children = [...node.getChildren()];\n for (const child of children) node.remove(child);\n}\n","import {\n type BoxRenderable,\n type CliRenderer,\n type RGBA,\n TextRenderable\n} from '@opentui/core';\nimport type { TuiContext } from '@tui/context.ts';\nimport { removeAllChildren } from '@tui/render/dom.ts';\nimport type { ResolvedTheme } from '@tui/theme.ts';\n\nexport interface FooterSeg {\n text: string;\n fg: RGBA;\n}\n\nfunction bindings(\n specs: { key: string; label: string }[],\n theme: ResolvedTheme\n): FooterSeg[] {\n // \"[key] label\" with the brackets dim and the key + label in normal fg.\n // Segments separated by dim \" · \".\n const out: FooterSeg[] = [];\n specs.forEach((spec, i) => {\n if (i > 0) out.push({ text: ' · ', fg: theme.fgDim });\n out.push({ text: '[', fg: theme.fgDim });\n out.push({ text: spec.key, fg: theme.fg });\n out.push({ text: '] ', fg: theme.fgDim });\n out.push({ text: spec.label, fg: theme.fg });\n });\n return out;\n}\n\nexport function renderHintBox(\n box: BoxRenderable,\n renderer: CliRenderer,\n segs: FooterSeg[]\n): void {\n removeAllChildren(box);\n segs.forEach((seg, i) => {\n box.add(\n new TextRenderable(renderer, {\n id: `${box.id}-seg-${i}`,\n content: seg.text,\n fg: seg.fg,\n height: 1,\n wrapMode: 'none'\n })\n );\n });\n}\n\nexport function refreshFooter(ctx: TuiContext): void {\n const {\n el: { hintA, hintB, status },\n renderer,\n state,\n theme\n } = ctx;\n const dirty = state.dirty.size;\n const dirtyTail: FooterSeg[] =\n dirty > 0\n ? [\n { text: ' ', fg: theme.fgDim },\n { text: '●', fg: theme.modified },\n { text: ` ${dirty} unsaved`, fg: theme.fg }\n ]\n : [];\n\n if (state.mode === 'filter') {\n renderHintBox(hintA, renderer, [\n ...bindings(\n [\n { key: 'Enter', label: 'keep filter' },\n { key: 'Esc', label: 'clear' }\n ],\n theme\n ),\n ...dirtyTail\n ]);\n renderHintBox(hintB, renderer, [{ text: ' Filter:', fg: theme.fgDim }]);\n } else if (state.mode === 'prompt') {\n renderHintBox(hintA, renderer, []);\n renderHintBox(hintB, renderer, []);\n } else if (state.pane === 'sidebar') {\n renderHintBox(hintA, renderer, [\n ...bindings(\n [\n { key: '↑↓', label: 'move' },\n { key: 'Space', label: 'toggle' },\n { key: 'b', label: 'set base' },\n { key: 'Tab/→', label: 'matrix' },\n { key: '^S', label: 'save' },\n { key: '?', label: 'help' },\n { key: 'q', label: 'quit' }\n ],\n theme\n ),\n ...dirtyTail\n ]);\n renderHintBox(hintB, renderer, [{ text: 'Files pane', fg: theme.fgDim }]);\n } else {\n renderHintBox(hintA, renderer, [\n ...bindings(\n [\n { key: '↑↓←→', label: 'move' },\n { key: 'Tab', label: 'files' },\n { key: 'e', label: 'edit' },\n { key: 'a', label: 'add var' },\n { key: 'd', label: 'del var' },\n { key: 'n', label: 'new file' },\n { key: '=', label: 'sync to all' },\n { key: 'c', label: 'collapse' },\n { key: '^T', label: 'secrets' },\n { key: '^Z', label: 'undo' },\n { key: '^S', label: 'save' },\n { key: '/', label: 'filter' },\n { key: '?/ß', label: 'help' },\n { key: 'q', label: 'quit' }\n ],\n theme\n ),\n ...dirtyTail\n ]);\n renderHintBox(hintB, renderer, [\n { text: 'view: ', fg: theme.fgDim },\n { text: state.driftOnly ? 'drift' : 'all', fg: theme.fg },\n { text: ' · group: ', fg: theme.fgDim },\n { text: state.grouping, fg: theme.fg },\n { text: ' · secrets: ', fg: theme.fgDim },\n { text: state.showSecrets ? 'shown' : 'masked', fg: theme.fg }\n ]);\n }\n status.content = state.message ?? '';\n}\n","import { RGBA } from '@opentui/core';\nimport type { HelpLine } from '@tui/types.ts';\n\nexport function buildHelpLines(): HelpLine[] {\n return [\n { kind: 'header', text: 'Panes' },\n {\n kind: 'entry',\n text: ' Tab Switch matrix ↔ files sidebar'\n },\n {\n kind: 'entry',\n text: ' ← (leftmost col) Hop from matrix into the sidebar'\n },\n { kind: 'blank' },\n { kind: 'header', text: 'Matrix navigation' },\n { kind: 'entry', text: ' ↑ ↓ ← → Move focused cell' },\n { kind: 'entry', text: ' Mouse wheel Scroll (both axes)' },\n { kind: 'blank' },\n { kind: 'header', text: 'Files sidebar' },\n { kind: 'entry', text: ' ↑ ↓ Move selection' },\n { kind: 'entry', text: ' Space Enable / disable file' },\n { kind: 'entry', text: ' b Make selected file the base' },\n { kind: 'entry', text: ' Tab / → Back to matrix' },\n { kind: 'blank' },\n { kind: 'header', text: 'Editing' },\n { kind: 'entry', text: ' e / Enter Edit focused cell value' },\n { kind: 'entry', text: ' a Add a new variable here' },\n {\n kind: 'entry',\n text: ' d Delete the variable from this file'\n },\n { kind: 'entry', text: ' n Create a new .env* file' },\n {\n kind: 'entry',\n text: ' = Sync focused value to every file'\n },\n {\n kind: 'entry',\n text: ' Ctrl-A (in edit) Apply typed value to every file'\n },\n { kind: 'entry', text: ' Ctrl-Z Undo last edit/add/delete' },\n { kind: 'entry', text: ' Ctrl-S Write all dirty files' },\n {\n kind: 'entry',\n text: ' c Collapse / expand focused section'\n },\n {\n kind: 'entry',\n text: ' Shift-C Expand every collapsed section'\n },\n { kind: 'blank' },\n { kind: 'header', text: 'View' },\n { kind: 'entry', text: ' / Filter keys' },\n { kind: 'entry', text: ' v All keys ↔ drift-only' },\n { kind: 'entry', text: ' g Group by prefix ↔ banner' },\n { kind: 'entry', text: ' Ctrl-T Show / mask secret values' },\n { kind: 'blank' },\n { kind: 'header', text: 'Help & exit' },\n { kind: 'entry', text: ' ? / ß Toggle this overlay' },\n { kind: 'entry', text: ' q Quit (twice if dirty)' },\n { kind: 'entry', text: ' Ctrl-C Force quit' },\n { kind: 'blank' },\n { kind: 'header', text: 'Cell icons' },\n {\n kind: 'legend',\n symbol: '≠ value',\n color: RGBA.fromHex('#ffd866'),\n description: 'value differs from base'\n },\n {\n kind: 'legend',\n symbol: '✗ missing',\n color: RGBA.fromHex('#ff6b6b'),\n description: 'this file has no value for the key'\n },\n {\n kind: 'legend',\n symbol: '★ value',\n color: RGBA.fromHex('#ffd866'),\n description: 'key is not in the base'\n },\n {\n kind: 'legend',\n symbol: '•••• (N)',\n color: RGBA.fromHex('#cccccc'),\n description: 'secret-suspect value masked by length'\n },\n {\n kind: 'legend',\n symbol: '⚠ TODO',\n color: RGBA.fromHex('#ffd866'),\n description: 'placeholder value (TODO, CHANGEME, xxx, …)'\n },\n {\n kind: 'legend',\n symbol: 'value ●',\n color: RGBA.fromHex('#7fce6a'),\n description: 'modified in this session — Ctrl-S to persist'\n }\n ];\n}\n","import {\n BoxRenderable,\n type CliRenderer,\n RGBA,\n TextRenderable\n} from '@opentui/core';\nimport type { CellState } from '@/core/matrix.ts';\nimport { formatValue, truncate } from '@tui/format.ts';\nimport type { SectionStats } from '@tui/grouping.ts';\nimport type { ResolvedTheme } from '@tui/theme.ts';\nimport type { HelpLine } from '@tui/types.ts';\n\nexport interface CellSpec {\n text: string;\n fg: RGBA;\n width: number;\n bg?: RGBA;\n // Optional coloured prefix — rendered in its own Text span so only the\n // icon carries the state colour, the text stays neutral.\n icon?: { char: string; fg: RGBA };\n // Optional coloured marker that sits at the right edge of the cell.\n // Used for the modified-since-load indicator.\n trailing?: { char: string; fg: RGBA };\n}\n\nexport function buildValueCell(\n cell: { state: CellState; value: string | undefined },\n secret: boolean,\n width: number,\n focused: boolean,\n modified: boolean,\n theme: ResolvedTheme,\n isPlaceholder: (value: string) => boolean\n): CellSpec {\n const bg = focused ? theme.focusBg : undefined;\n const trailing = modified ? { char: '●', fg: theme.modified } : undefined;\n if (cell.state === 'missing') {\n return {\n text: 'missing',\n fg: theme.fgDim,\n width,\n bg,\n icon: { char: '✗', fg: theme.missing },\n trailing\n };\n }\n const value = cell.value ?? '';\n if (value !== '' && isPlaceholder(value)) {\n return {\n text: value,\n fg: theme.fg,\n width,\n bg,\n icon: { char: '⚠', fg: theme.placeholder },\n trailing\n };\n }\n const isEmpty = value === '' && !secret;\n const displayText = isEmpty ? '(empty)' : formatValue(value, secret);\n const displayFg = isEmpty ? theme.fgDim : theme.fg;\n if (cell.state === 'differs') {\n return {\n text: displayText,\n fg: displayFg,\n width,\n bg,\n icon: { char: '≠', fg: theme.differs },\n trailing\n };\n }\n if (cell.state === 'extra') {\n return {\n text: displayText,\n fg: displayFg,\n width,\n bg,\n icon: { char: '★', fg: theme.extra },\n trailing\n };\n }\n return { text: displayText, fg: displayFg, width, bg, trailing };\n}\n\nexport function buildHelpRow(\n renderer: CliRenderer,\n id: string,\n line: HelpLine,\n theme: ResolvedTheme\n): BoxRenderable {\n const row = new BoxRenderable(renderer, {\n id,\n flexDirection: 'row',\n height: 1,\n flexShrink: 0\n });\n if (line.kind === 'header') {\n row.add(\n new TextRenderable(renderer, {\n id: `${id}-t`,\n content: line.text,\n fg: theme.fgSection,\n wrapMode: 'none',\n height: 1\n })\n );\n } else if (line.kind === 'entry') {\n row.add(\n new TextRenderable(renderer, {\n id: `${id}-t`,\n content: line.text,\n fg: theme.fg,\n wrapMode: 'none',\n height: 1\n })\n );\n } else if (line.kind === 'legend') {\n row.add(\n new TextRenderable(renderer, {\n id: `${id}-sym`,\n content: ` ${line.symbol.padEnd(12)}`,\n fg: line.color,\n wrapMode: 'none',\n height: 1\n })\n );\n row.add(\n new TextRenderable(renderer, {\n id: `${id}-desc`,\n content: line.description,\n fg: theme.fgDim,\n wrapMode: 'none',\n height: 1\n })\n );\n }\n return row;\n}\n\nexport function buildSectionDivider(\n renderer: CliRenderer,\n id: string,\n name: string | undefined,\n width: number,\n meta: SectionStats & { collapsed: boolean; focused?: boolean },\n theme: ResolvedTheme\n): BoxRenderable {\n // Multi-segment divider so colours can encode meaning:\n // gray ─── blue ▾ Name dim · stats gray ───\n // Drift counts go yellow; if any key in the section is missing in any\n // non-base file we surface that explicitly in red (\"✗ N missing\"), even\n // when the section also has plain differs.\n const baseName = name ?? '(other)';\n const indicator = meta.collapsed ? '▸' : '▾';\n // Icons + numbers carry colour (red for missing, yellow for drift). Name\n // and descriptive words render in the normal foreground; the \"/\" and\n // trailing whitespace stay dim.\n type Seg = { text: string; fg: RGBA };\n const segs: Seg[] = [\n { text: ` ${indicator} `, fg: theme.fgDim },\n { text: baseName, fg: theme.fg },\n { text: ' ', fg: theme.fgDim }\n ];\n if (meta.missing > 0) {\n segs.push({ text: '✗ ', fg: theme.missing });\n segs.push({ text: `${meta.missing}`, fg: theme.missing });\n segs.push({ text: ' missing ', fg: theme.fg });\n }\n if (meta.drift > 0) {\n segs.push({ text: '≠ ', fg: theme.differs });\n segs.push({ text: `${meta.drift}`, fg: theme.differs });\n segs.push({ text: '/', fg: theme.fgDim });\n segs.push({ text: `${meta.total}`, fg: theme.differs });\n segs.push({ text: ' drift ', fg: theme.fg });\n }\n if (meta.missing === 0 && meta.drift === 0) {\n segs.push({ text: `${meta.total}`, fg: theme.fgDim });\n segs.push({ text: ' keys ', fg: theme.fg });\n }\n segs.push({ text: ' ', fg: theme.fgDim });\n\n const labelLength = segs.reduce((sum, s) => sum + s.text.length, 0);\n const rule = '─';\n const visible = Math.max(0, width - 2);\n const beforeLen = Math.max(2, Math.floor((visible - labelLength) / 2));\n const afterLen = Math.max(0, visible - beforeLen - labelLength);\n\n const box = new BoxRenderable(renderer, {\n id,\n flexDirection: 'row',\n flexShrink: 0,\n height: 1,\n paddingX: 1,\n ...(meta.focused ? { backgroundColor: theme.focusBg } : {})\n });\n box.add(\n new TextRenderable(renderer, {\n id: `${id}-lead`,\n content: rule.repeat(beforeLen),\n fg: theme.fgDim,\n height: 1,\n wrapMode: 'none'\n })\n );\n segs.forEach((seg, i) => {\n box.add(\n new TextRenderable(renderer, {\n id: `${id}-seg-${i}`,\n content: seg.text,\n fg: seg.fg,\n height: 1,\n wrapMode: 'none'\n })\n );\n });\n box.add(\n new TextRenderable(renderer, {\n id: `${id}-trail`,\n content: rule.repeat(afterLen),\n fg: theme.fgDim,\n height: 1,\n wrapMode: 'none'\n })\n );\n return box;\n}\n\nexport function buildRow(\n renderer: CliRenderer,\n idPrefix: string,\n cells: CellSpec[],\n padX: number\n): BoxRenderable {\n const row = new BoxRenderable(renderer, {\n id: idPrefix,\n flexDirection: 'row',\n flexShrink: 0,\n height: 1\n });\n cells.forEach((cell, i) => {\n const cellOpts: ConstructorParameters<typeof BoxRenderable>[1] = {\n id: `${idPrefix}-c${i}`,\n width: cell.width,\n height: 1,\n flexDirection: 'row',\n flexShrink: 0,\n paddingX: padX\n };\n if (cell.bg) cellOpts.backgroundColor = cell.bg;\n const cellBox = new BoxRenderable(renderer, cellOpts);\n const innerWidth = Math.max(0, cell.width - padX * 2);\n const iconLen = cell.icon ? cell.icon.char.length + 1 : 0;\n const trailingLen = cell.trailing ? cell.trailing.char.length + 1 : 0;\n const textWidth = Math.max(0, innerWidth - iconLen - trailingLen);\n if (cell.icon) {\n cellBox.add(\n new TextRenderable(renderer, {\n id: `${idPrefix}-c${i}-icon`,\n content: `${cell.icon.char} `,\n fg: cell.icon.fg,\n height: 1,\n wrapMode: 'none'\n })\n );\n }\n cellBox.add(\n new TextRenderable(renderer, {\n id: `${idPrefix}-c${i}-t`,\n content: truncate(cell.text, textWidth),\n fg: cell.fg,\n height: 1,\n flexGrow: 1,\n wrapMode: 'none'\n })\n );\n if (cell.trailing) {\n cellBox.add(\n new TextRenderable(renderer, {\n id: `${idPrefix}-c${i}-trail`,\n content: ` ${cell.trailing.char}`,\n fg: cell.trailing.fg,\n height: 1,\n wrapMode: 'none'\n })\n );\n }\n row.add(cellBox);\n });\n return row;\n}\n","import { BoxRenderable, ScrollBoxRenderable } from '@opentui/core';\nimport type { TuiContext } from '@tui/context.ts';\nimport { buildHelpLines } from '@tui/help.ts';\nimport { buildHelpRow } from '@tui/render/builders.ts';\nimport { removeAllChildren } from '@tui/render/dom.ts';\n\nexport function refreshHelp(ctx: TuiContext): void {\n const {\n el: { helpBox },\n renderer,\n state,\n theme\n } = ctx;\n helpBox.visible = state.helpOpen;\n if (!state.helpOpen) return;\n removeAllChildren(helpBox);\n const lines = buildHelpLines();\n // Use one scrollable column when the terminal is narrow or short.\n const narrow = renderer.terminalWidth < 100;\n const short = renderer.terminalHeight < 36;\n const oneColumn = narrow || short;\n if (oneColumn) {\n const scroll = new ScrollBoxRenderable(renderer, {\n id: 'help-scroll',\n flexGrow: 1,\n scrollX: false,\n scrollY: true,\n viewportOptions: { paddingRight: 1 },\n contentOptions: { flexDirection: 'column' }\n });\n helpBox.add(scroll);\n lines.forEach((line, i) => {\n scroll.content.add(buildHelpRow(renderer, `help-${i}`, line, theme));\n });\n return;\n }\n // Two-column grid.\n const grid = new BoxRenderable(renderer, {\n id: 'help-grid',\n flexDirection: 'row',\n flexGrow: 1,\n columnGap: 3\n });\n const left = new BoxRenderable(renderer, {\n id: 'help-left',\n flexDirection: 'column',\n flexGrow: 1,\n flexBasis: 0\n });\n const right = new BoxRenderable(renderer, {\n id: 'help-right',\n flexDirection: 'column',\n flexGrow: 1,\n flexBasis: 0\n });\n const half = Math.floor(lines.length / 2);\n let splitIdx = half;\n for (let i = half; i < lines.length; i++) {\n if (lines[i]?.kind === 'blank') {\n splitIdx = i + 1;\n break;\n }\n }\n lines\n .slice(0, splitIdx)\n .forEach((line, i) =>\n left.add(buildHelpRow(renderer, `help-l-${i}`, line, theme))\n );\n lines\n .slice(splitIdx)\n .forEach((line, i) =>\n right.add(buildHelpRow(renderer, `help-r-${i}`, line, theme))\n );\n grid.add(left);\n grid.add(right);\n helpBox.add(grid);\n}\n","import type { Matrix } from '@/core/matrix.ts';\nimport { basename } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\nimport { sectionMetadata } from '@tui/grouping.ts';\nimport {\n buildRow,\n buildSectionDivider,\n buildValueCell,\n type CellSpec\n} from '@tui/render/builders.ts';\nimport { removeAllChildren } from '@tui/render/dom.ts';\nimport type { State } from '@tui/types.ts';\n\nexport function matrixTitle(matrix: Matrix, state: State): string {\n const visible = state.visibleKeys.length;\n const total = matrix.keys.length;\n const parts: string[] = [`${total} keys`];\n if (state.driftOnly) parts.push(`drift ${visible}/${total}`);\n else if (state.filter && visible !== total) {\n parts.push(`\"${state.filter}\" ${visible}/${total}`);\n }\n return ` Matrix · ${parts.join(' · ')} `;\n}\n\n/**\n * Available width inside the matrix box (subtract sidebar, both borders and the\n * matrix's horizontal padding). If columns would shrink below VALUE_COL_MIN to\n * fit, keep them at the minimum and let the ScrollBox handle the overflow.\n */\nexport function computeValueColWidth(ctx: TuiContext): number {\n const { renderer, matrix, layout } = ctx;\n const available = Math.max(\n 0,\n renderer.terminalWidth - layout.SIDEBAR_WIDTH - 6 - layout.KEY_COL_WIDTH\n );\n const fair = matrix.files.length\n ? Math.floor(available / matrix.files.length)\n : layout.VALUE_COL_MIN;\n return Math.max(layout.VALUE_COL_MIN, fair);\n}\n\nexport function refreshMatrix(ctx: TuiContext): void {\n const {\n el: { matrixBox, headerHost, scrollBox },\n renderer,\n matrix,\n state,\n theme,\n layout,\n heuristics\n } = ctx;\n const sectionOf = ctx.sectionOf;\n const valueColWidth = computeValueColWidth(ctx);\n matrixBox.title = matrixTitle(matrix, state);\n removeAllChildren(headerHost);\n removeAllChildren(scrollBox.content);\n\n headerHost.add(\n buildRow(\n renderer,\n 'header',\n [\n { text: 'KEY', fg: theme.fgHeader, width: layout.KEY_COL_WIDTH },\n ...matrix.files.map((f) => ({\n text: basename(f.path),\n fg: theme.fgHeader,\n width: valueColWidth\n }))\n ],\n layout.CELL_PAD_X\n )\n );\n\n // Walk every key (including those hidden by a collapsed section) so we can\n // render section dividers for collapsed groups too. Within an expanded\n // group we render the cell rows; within a collapsed one we render nothing\n // beyond the header.\n const totalWidth = layout.KEY_COL_WIDTH + valueColWidth * matrix.files.length;\n const sectionStats = sectionMetadata(matrix, sectionOf, state);\n\n for (let r = 0; r < state.visibleItems.length; r++) {\n const item = state.visibleItems[r]!;\n if (item.kind === 'divider') {\n const sectionKey = item.ref;\n const sectionName = sectionKey === '__other__' ? undefined : sectionKey;\n const meta = sectionStats.get(sectionKey) ?? {\n drift: 0,\n missing: 0,\n total: 0\n };\n const focused = state.mode === 'browse' && r === state.rowIdx;\n scrollBox.content.add(\n buildSectionDivider(\n renderer,\n `row-${r}`,\n sectionName,\n totalWidth,\n {\n ...meta,\n collapsed: state.collapsed.has(sectionKey),\n focused\n },\n theme\n )\n );\n continue;\n }\n const key = item.ref;\n const secret = heuristics.isSecretKey(key) && !state.showSecrets;\n const cells: CellSpec[] = [\n { text: key, fg: theme.fg, width: layout.KEY_COL_WIDTH }\n ];\n for (let c = 0; c < matrix.files.length; c++) {\n const file = matrix.files[c]!;\n const cell = matrix.cell(key, file);\n const focused =\n state.mode === 'browse' && r === state.rowIdx && c === state.colIdx;\n const isModified = state.modified.has(`${key}|${file.path}`);\n cells.push(\n buildValueCell(\n cell,\n secret,\n valueColWidth,\n focused,\n isModified,\n theme,\n heuristics.isPlaceholderValue\n )\n );\n }\n scrollBox.content.add(\n buildRow(renderer, `row-${r}`, cells, layout.CELL_PAD_X)\n );\n }\n\n // Keep the focused row in view. Single deferred call so layout has been\n // computed before we ask for a scroll target; doing it twice (sync +\n // deferred) was causing visible \"jumps\" because the two calls landed on\n // slightly different layouts.\n if (state.mode === 'browse' && state.visibleItems.length > 0) {\n const target = `row-${state.rowIdx}`;\n setImmediate(() => {\n try {\n scrollBox.scrollChildIntoView(target);\n } catch {\n /* row not laid out yet — next refresh will retry */\n }\n });\n }\n}\n","import { BoxRenderable, TextRenderable } from '@opentui/core';\nimport { basename } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\nimport { findKvEntry, formatValue } from '@tui/format.ts';\nimport { removeAllChildren } from '@tui/render/dom.ts';\nimport type { Prompt } from '@tui/types.ts';\n\nexport function promptLabelText(p: Prompt): string {\n switch (p.kind) {\n case 'edit':\n return ` Edit ${p.key} in ${basename(p.file.path)}:`;\n case 'add-key':\n return ` Add new key to ${basename(p.file.path)}:`;\n case 'add-value':\n return ` Value for ${p.key} in ${basename(p.file.path)}:`;\n case 'new-file':\n return ' New env file name (e.g. .env.local):';\n }\n}\n\nexport function refreshPrompt(ctx: TuiContext): void {\n const {\n el: { promptBox, promptBody, promptHint },\n renderer,\n matrix,\n state,\n theme,\n heuristics\n } = ctx;\n const open = state.mode === 'prompt' && state.prompt !== null;\n promptBox.visible = open;\n if (!open || !state.prompt) return;\n\n promptBox.title = promptLabelText(state.prompt);\n // Hint depends on which prompt is active — only edit/add-value support\n // the apply-to-all + show-secrets shortcuts.\n const p = state.prompt;\n if (p.kind === 'edit' || p.kind === 'add-value') {\n promptHint.content =\n 'Enter · confirm Ctrl-A · apply to all ' +\n 'Ctrl-T · show/mask secrets Esc · cancel';\n } else {\n promptHint.content = 'Enter · confirm Esc · cancel';\n }\n\n // Body layout: full-width input on top, then a context table of every file\n // and its current value (read-only). For add-key / new-file there's no\n // context to show — just the input.\n removeAllChildren(promptBody);\n // Input is rendered as plain text so we can guarantee char + Esc handling\n // ourselves (opentui's InputRenderable swallows Esc as \"blur\").\n promptBody.add(\n new TextRenderable(renderer, {\n id: 'prompt-input-text',\n content: `▸ ${state.promptInput}▏`,\n fg: theme.fg,\n height: 1,\n wrapMode: 'none'\n })\n );\n // Show validation errors inside the modal so they aren't hidden behind\n // the dim overlay. state.message is set by commitPrompt when input is\n // invalid (and cleared on each fresh openPrompt).\n if (state.message) {\n promptBody.add(\n new TextRenderable(renderer, {\n id: 'prompt-error',\n content: `! ${state.message}`,\n fg: theme.missing,\n height: 1,\n marginTop: 1,\n wrapMode: 'none'\n })\n );\n }\n\n if (p.kind === 'edit' || p.kind === 'add-value') {\n const secret = heuristics.isSecretKey(p.key) && !state.showSecrets;\n const nameWidth = Math.min(\n 26,\n Math.max(...matrix.files.map((f) => basename(f.path).length + 2))\n );\n\n promptBody.add(\n new TextRenderable(renderer, {\n id: 'prompt-table-header',\n content: 'Current values',\n fg: theme.fgSection,\n wrapMode: 'none',\n height: 1,\n marginTop: 1\n })\n );\n\n for (const file of matrix.files) {\n const isTarget = file === p.file;\n const row = new BoxRenderable(renderer, {\n id: `prompt-row-${file.path}`,\n flexDirection: 'row',\n height: 1,\n flexShrink: 0\n });\n row.add(\n new TextRenderable(renderer, {\n id: `prompt-row-${file.path}-name`,\n content: `${isTarget ? '▸' : ' '} ${basename(file.path)}`.padEnd(\n nameWidth\n ),\n fg: isTarget ? theme.fgBase : theme.fgDim,\n height: 1,\n wrapMode: 'none'\n })\n );\n const entry = findKvEntry(file, p.key);\n const current = entry ? formatValue(entry.value, secret) : '✗ missing';\n row.add(\n new TextRenderable(renderer, {\n id: `prompt-row-${file.path}-value`,\n content: current,\n fg: !entry ? theme.missing : isTarget ? theme.fg : theme.fgDim,\n height: 1,\n wrapMode: 'none'\n })\n );\n promptBody.add(row);\n }\n }\n}\n","import { BoxRenderable, type RGBA, TextRenderable } from '@opentui/core';\nimport { basename } from 'pathe';\nimport type { TuiContext } from '@tui/context.ts';\nimport { removeAllChildren } from '@tui/render/dom.ts';\n\nexport function refreshSidebar(ctx: TuiContext): void {\n const {\n el: { sidebar },\n renderer,\n matrix,\n allFiles,\n state,\n theme\n } = ctx;\n const total = allFiles.length;\n const enabled = state.enabled.size;\n sidebar.title =\n state.pane === 'sidebar'\n ? ` Files ${enabled}/${total} • focused `\n : ` Files ${enabled}/${total} `;\n removeAllChildren(sidebar);\n for (let i = 0; i < allFiles.length; i++) {\n const file = allFiles[i]!;\n const isBase = file === matrix.base;\n const isDirty = state.dirty.has(file);\n const isEnabled = state.enabled.has(file);\n const matrixIdx = matrix.files.indexOf(file);\n const isFocusCol = isEnabled && matrixIdx === state.colIdx;\n const isPaneFocus = state.pane === 'sidebar' && i === state.sidebarIdx;\n const nameFg = !isEnabled ? theme.fgDim : isBase ? theme.fgBase : theme.fg;\n\n const row = new BoxRenderable(renderer, {\n id: `file-${file.path}`,\n flexDirection: 'row',\n height: 1,\n flexShrink: 0,\n ...(isPaneFocus ? { backgroundColor: theme.focusBg } : {})\n });\n const span = (id: string, text: string, fg: RGBA) =>\n new TextRenderable(renderer, {\n id: `${row.id}-${id}`,\n content: text,\n fg,\n height: 1,\n wrapMode: 'none'\n });\n row.add(span('focus', `${isPaneFocus ? '▶' : ' '} `, theme.fg));\n row.add(\n span(\n 'dirty',\n `${isDirty ? '●' : ' '} `,\n isDirty ? theme.fgDirty : theme.fgDim\n )\n );\n row.add(\n span(\n 'base',\n `${isBase ? '★' : ' '} `,\n isBase ? theme.fgBase : theme.fgDim\n )\n );\n row.add(span('col', `${isFocusCol ? '▸' : ' '} `, theme.fgDim));\n row.add(span('enabled', `${isEnabled ? '✓' : '☐'} `, theme.fgDim));\n row.add(span('name', basename(file.path), nameFg));\n sidebar.add(row);\n }\n}\n","import type { TuiContext } from '@tui/context.ts';\nimport { refreshFilter } from '@tui/render/filter.ts';\nimport { refreshFooter } from '@tui/render/footer.ts';\nimport { refreshHelp } from '@tui/render/help.ts';\nimport { refreshMatrix } from '@tui/render/matrix.ts';\nimport { refreshPrompt } from '@tui/render/prompt.ts';\nimport { refreshSidebar } from '@tui/render/sidebar.ts';\n\n/**\n * Full synchronous render of every region. Reads `ctx.matrix` fresh so a\n * `rebuildMatrix` that ran between scheduling and this flush is reflected.\n */\nexport function refreshAll(ctx: TuiContext): void {\n const { state } = ctx;\n refreshSidebar(ctx);\n refreshMatrix(ctx);\n refreshFooter(ctx);\n refreshPrompt(ctx);\n refreshHelp(ctx);\n refreshFilter(ctx);\n ctx.el.dimOverlay.visible =\n state.helpOpen || state.mode === 'prompt' || state.mode === 'filter';\n}\n","import { RGBA } from '@opentui/core';\nimport { DEFAULT_THEME_HEX, resolveThemeHex } from '@/config/resolve.ts';\nimport type { LayoutConfig, ThemeConfig, ThemeKey } from '@/config/schema.ts';\n\n// Three semantic colours only. Everything else is grayscale so the eye\n// doesn't get pulled in five directions. The hex source of truth lives in\n// resolve.ts (DEFAULT_THEME_HEX) so the merge logic stays RGBA-free.\n\nexport type ResolvedTheme = Record<ThemeKey, RGBA>;\n\n/** Resolve a partial hex theme into RGBA values (gaps + invalid → defaults). */\nexport function resolveTheme(\n theme: ThemeConfig = {},\n warn?: (msg: string) => void\n): ResolvedTheme {\n const hex = resolveThemeHex(theme, warn);\n const out = {} as ResolvedTheme;\n for (const key of Object.keys(DEFAULT_THEME_HEX) as ThemeKey[]) {\n out[key] = RGBA.fromHex(hex[key]);\n }\n return out;\n}\n\n/** The default resolved palette (was previously the `COLORS` constant). */\nexport const DEFAULT_THEME: ResolvedTheme = resolveTheme();\n\nexport interface ResolvedLayout {\n KEY_COL_WIDTH: number;\n VALUE_COL_MIN: number;\n SIDEBAR_WIDTH: number;\n ROW_GAP: number;\n CELL_PAD_X: number;\n}\n\nexport function resolveLayout(layout: LayoutConfig): ResolvedLayout {\n return {\n KEY_COL_WIDTH: layout.keyColWidth,\n VALUE_COL_MIN: layout.valueColMin,\n SIDEBAR_WIDTH: layout.sidebarWidth,\n ROW_GAP: layout.rowGap,\n CELL_PAD_X: layout.cellPadX\n };\n}\n","import { createCliRenderer } from '@opentui/core';\nimport type { Matrix } from '@/core/matrix.ts';\nimport { DEFAULT_CONFIG, type EnvprismConfig } from '@/config/schema.ts';\nimport { resolveHeuristics } from '@/config/resolve.ts';\nimport type { State } from '@tui/types.ts';\nimport { prefixSection } from '@tui/grouping.ts';\nimport type { TuiContext } from '@tui/context.ts';\nimport { createOnKey } from '@tui/keys/onKey.ts';\nimport { buildLayout } from '@tui/render/layout.ts';\nimport { refreshAll } from '@tui/render/index.ts';\nimport { resolveLayout, resolveTheme } from '@tui/theme.ts';\nimport { recomputeVisibleKeys } from '@tui/state/visible.ts';\n\nexport async function runMatrixTui(\n initialMatrix: Matrix,\n config: EnvprismConfig = DEFAULT_CONFIG\n): Promise<void> {\n const renderer = await createCliRenderer({ useMouse: true });\n const theme = resolveTheme(config.tui.theme);\n const layout = resolveLayout(config.tui.layout);\n const heuristics = resolveHeuristics(config);\n // The full discovered file list never changes; the matrix is rebuilt from\n // the currently *enabled* subset whenever the user toggles a file.\n const allFiles = initialMatrix.files.slice();\n\n // 'auto' prefers banner grouping when the base file has section banners;\n // otherwise prefix grouping is more useful out of the box. An explicit\n // config grouping overrides the heuristic.\n const hasBanners = initialMatrix.keys.some(\n (k) => initialMatrix.sectionOf(k) !== undefined\n );\n const grouping =\n heuristics.grouping === 'auto'\n ? hasBanners\n ? 'banner'\n : 'prefix'\n : heuristics.grouping;\n\n const state: State = {\n mode: 'browse',\n filter: '',\n rowIdx: 0,\n colIdx: 0,\n prompt: null,\n dirty: new Set(),\n visibleKeys: initialMatrix.keys.slice(),\n visibleItems: [],\n message: null,\n driftOnly: false,\n confirmQuit: false,\n grouping,\n helpOpen: false,\n undo: [],\n pane: 'matrix',\n sidebarIdx: 0,\n enabled: new Set(allFiles),\n showSecrets: !config.tui.maskSecrets,\n collapsed: new Set(),\n modified: new Set(),\n promptInput: ''\n };\n\n const el = buildLayout(renderer, theme, layout);\n\n // Coalesce burst-y refreshes (held arrow keys, fast filter typing) into one\n // render per microtask flush. refreshAll rebuilds every matrix row, which is\n // expensive per keystroke; batching keeps held keys in opentui's own redraw\n // loop instead of our re-render.\n let refreshScheduled = false;\n const ctx: TuiContext = {\n renderer,\n state,\n allFiles,\n el,\n config,\n theme,\n layout,\n heuristics,\n matrix: initialMatrix,\n currentBase: initialMatrix.base,\n refresh: () => {\n if (refreshScheduled) return;\n refreshScheduled = true;\n queueMicrotask(() => {\n refreshScheduled = false;\n refreshAll(ctx);\n });\n },\n refreshNow: () => refreshAll(ctx),\n sectionOf: (key: string): string | undefined =>\n state.grouping === 'banner'\n ? ctx.matrix.sectionOf(key)\n : prefixSection(key)\n };\n\n recomputeVisibleKeys(ctx);\n ctx.refreshNow();\n\n // --- Interaction ---\n return new Promise<void>((resolve) => {\n const cleanup = () => {\n renderer._internalKeyInput.offInternal('keypress', onKey);\n renderer.destroy?.();\n resolve();\n };\n\n const onKey = createOnKey(ctx, cleanup);\n\n // Use the internal channel so our handler runs *before* the focused\n // renderable processes the event. That lets us intercept Esc / Enter\n // before opentui's InputRenderable swallows them (Esc would otherwise\n // just blur the input instead of closing the modal).\n renderer._internalKeyInput.onInternal('keypress', onKey);\n renderer.on('resize', ctx.refresh);\n });\n}\n"],"mappings":";;;;;;AAKA,IAAa,uBAAuB;AAEpC,SAAgB,cAAc,KAAiC;CAC7D,MAAM,MAAM,IAAI,QAAQ,GAAG;CAC3B,IAAI,OAAO,GAAG,OAAO,KAAA;CACrB,OAAO,IAAI,MAAM,GAAG,GAAG;AACzB;;;;;;AAOA,SAAgB,cAAc,MAA0B;CACtD,MAAM,yBAAS,IAAI,IAAsB;CACzC,MAAM,QAAkB,CAAC;CACzB,MAAM,QAAQ;CACd,KAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,cAAc,CAAC,KAAK;EAC9B,IAAI,SAAS,OAAO,IAAI,CAAC;EACzB,IAAI,CAAC,QAAQ;GACX,SAAS,CAAC;GACV,OAAO,IAAI,GAAG,MAAM;GACpB,IAAI,MAAM,OAAO,MAAM,KAAK,CAAC;EAC/B;EACA,OAAO,KAAK,CAAC;CACf;CACA,IAAI,OAAO,IAAI,KAAK,GAAG,MAAM,KAAK,KAAK;CACvC,OAAO,MAAM,SAAS,MAAM,OAAO,IAAI,CAAC,CAAE;AAC5C;;;;;;;AAQA,SAAgB,QAAQ,OAAc,OAAuB;CAC3D,MAAM,QAAQ,MAAM;CACpB,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,YAAY,MAAc;EAC9B,MAAM,KAAK,MAAM;EACjB,IAAI,CAAC,IAAI,OAAO;EAChB,IAAI,GAAG,SAAS,OAAO,OAAO;EAE9B,OAAO,MAAM,UAAU,IAAI,GAAG,GAAG;CACnC;CACA,IAAI,IAAI,MAAM,SAAS;CACvB,OAAO,KAAK,KAAK,IAAI,MAAM,QAAQ;EACjC,IAAI,SAAS,CAAC,GAAG,OAAO;EACxB,KAAK;CACP;CAEA,OAAO,MAAM;AACf;AAEA,SAAgB,YACd,QACA,OACA,WACU;CAEV,MAAM,WAAW,OAAO,KAAK,QAAQ,MAAM;EACzC,IAAI,CAAC,cAAc,GAAG,MAAM,MAAM,GAAG,OAAO;EAC5C,IAAI,MAAM,aAAa,CAAC,UAAU,QAAQ,CAAC,GAAG,OAAO;EACrD,OAAO;CACT,CAAC;CACD,OAAO,MAAM,aAAa,WAAW,cAAc,QAAQ,IAAI;AACjE;AAQA,SAAgB,gBACd,QACA,WACA,OAC2B;CAC3B,MAAM,sBAAM,IAAI,IAA0B;CAC1C,KAAK,MAAM,OAAO,YAAY,QAAQ,OAAO,SAAS,GAAG;EACvD,MAAM,IAAI,UAAU,GAAG,KAAA;EACvB,MAAM,SAAS,IAAI,IAAI,CAAC,KAAK;GAAE,OAAO;GAAG,SAAS;GAAG,OAAO;EAAE;EAC9D,OAAO,SAAS;EAChB,IAAI,SAAS;EACb,IAAI,UAAU;EACd,KAAK,MAAM,QAAQ,OAAO,OAAO;GAC/B,IAAI,SAAS,OAAO,MAAM;GAC1B,MAAM,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC;GACjC,IAAI,MAAM,WAAW,UAAU;GAC/B,IAAI,MAAM,aAAa,MAAM,aAAa,MAAM,SAAS,SAAS;EACpE;EACA,IAAI,QAAQ,OAAO,SAAS;EAC5B,IAAI,SAAS,OAAO,WAAW;EAC/B,IAAI,IAAI,GAAG,MAAM;CACnB;CACA,OAAO;AACT;AAEA,SAAgB,UAAU,QAAgB,KAAsB;CAC9D,KAAK,MAAM,QAAQ,OAAO,OAAO;EAC/B,IAAI,SAAS,OAAO,MAAM;EAC1B,MAAM,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC;EACjC,IAAI,MAAM,aAAa,MAAM,aAAa,MAAM,SAAS,OAAO;CAClE;CACA,OAAO;AACT;;;AC7GA,SAAgB,mBAAmB,MAAuB;CACxD,IAAI,CAAC,KAAK,WAAW,MAAM,GAAG,OAAO;CACrC,IAAI,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,GAAG,OAAO;CACtD,IAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,MAAM,GACrE,OAAO;CACT,OAAO;AACT;AAEA,SAAgB,mBAAmB,MAAuB;CACxD,OAAO;EACL;EACA,SAAS,CAAC;GAAE,MAAM;GAAW,KAAK,KAAK,SAAS,IAAI;EAAI,CAAC;EACzD,iBAAiB;CACnB;AACF;AAEA,SAAgB,SAAS,MAAe,KAAa,OAAwB;CAC3E,MAAM,QAAiB;EACrB,MAAM;EACN;EACA,UAAU;EACV;EACA,SAAS;EACT,cAAc;EACd,eAAe;EACf,KAAK;CACP;CACA,cAAc,KAAK;CACnB,KAAK,QAAQ,KAAK,KAAK;CAKvB,KAAK,kBAAkB;CACvB,OAAO;AACT;;;AC3BA,SAAgB,QAAQ,KAAa,MAAuB;CAC1D,OAAO,GAAG,IAAI,GAAG,KAAK;AACxB;AAEA,SAAgB,aACd,KACA,KACA,MACM;CACN,IAAI,MAAM,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC;AAC3C;AAEA,SAAgB,SAAS,KAAiB,OAAwB;CAChE,IAAI,MAAM,KAAK,KAAK,KAAK;CACzB,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,IAAI,WAAW,IAAI,MAAM,KAAK,MAAM;AAC7E;AAEA,SAAgB,WAAW,KAAgC;CACzD,MAAM,OAAO,IAAI,MAAM,aAAa,IAAI,MAAM;CAC9C,OAAO,QAAQ,KAAK,SAAS,QAAQ,KAAK,MAAM;AAClD;AAEA,SAAgB,SAAS,KAAiB,KAAmB;CAC3D,MAAM,MAAM,IAAI,MAAM,YAAY,QAAQ,GAAG;CAC7C,IAAI,OAAO,GAAG,IAAI,MAAM,SAAS;AACnC;AAEA,SAAgB,qBAAqB,KAAuB;CAC1D,MAAM,EAAE,UAAU;CAMlB,MAAM,cAAwB,CAAC;CAC/B,MAAM,QAAsB,CAAC;CAC7B,MAAM,aAAa,YAAY,IAAI,QAAQ,OAAO,IAAI,SAAS;CAC/D,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,aAAa,MAAM,aAAa,MAAM,OAAO,EAAE;CACrD,KAAK,MAAM,KAAK,YAAY;EAC1B,IAAI,CAAC,cAAc,GAAG,MAAM,MAAM,GAAG;EACrC,IAAI,MAAM,aAAa,CAAC,UAAU,IAAI,QAAQ,CAAC,GAAG;EAClD,MAAM,SAAS,IAAI,UAAU,CAAC,KAAA;EAC9B,IAAI,CAAC,KAAK,IAAI,MAAM,GAAG;GACrB,KAAK,IAAI,MAAM;GACf,MAAM,KAAK;IAAE,MAAM;IAAW,KAAK;GAAO,CAAC;EAC7C;EACA,IAAI,MAAM,UAAU,IAAI,MAAM,GAAG;EACjC,MAAM,KAAK;GAAE,MAAM;GAAO,KAAK;EAAE,CAAC;EAClC,YAAY,KAAK,CAAC;CACpB;CACA,MAAM,cAAc;CACpB,MAAM,eAAe;CAErB,IAAI,YAAY;EACd,MAAM,IAAI,MAAM,WAAW,OAAO,GAAG,QAAQ,UAAU;EACvD,IAAI,KAAK,GAAG,MAAM,SAAS;CAC7B;CACA,IAAI,MAAM,UAAU,MAAM,QACxB,MAAM,SAAS,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC;CAG7C,IACE,MAAM,MAAM,OAAO,EAAE,SAAS,aAC9B,CAAC,MAAM,UAAU,IAAI,MAAM,MAAM,OAAO,CAAE,GAAG,GAC7C;EACA,MAAM,OAAO,QAAQ,OAAO,CAAC;EAC7B,MAAM,OAAO,QAAQ,OAAO,EAAE;EAC9B,MAAM,SAAS,SAAS,MAAM,SAAS,OAAO;CAChD;AACF;AAEA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EAAE,UAAU;CAClB,MAAM,cAAc,IAAI,SAAS,QAAQ,MAAM,MAAM,QAAQ,IAAI,CAAC,CAAC;CACnE,IAAI,CAAC,MAAM,QAAQ,IAAI,IAAI,WAAW,GAAG;EAEvC,MAAM,OAAO,YAAY;EACzB,IAAI,MAAM,IAAI,cAAc;CAC9B;CACA,IAAI,SAAS,YAAY,aAAa,IAAI,WAAW;CACrD,IAAI,MAAM,UAAU,IAAI,OAAO,MAAM,QACnC,MAAM,SAAS,KAAK,IAAI,GAAG,IAAI,OAAO,MAAM,SAAS,CAAC;CAExD,IAAI,MAAM,cAAc,IAAI,SAAS,QACnC,MAAM,aAAa,KAAK,IAAI,GAAG,IAAI,SAAS,SAAS,CAAC;CAExD,qBAAqB,GAAG;AAC1B;;;ACxFA,SAAgB,gBACd,KACA,KACA,OACQ;CAIR,MAAM,EAAE,UAAU;CAClB,IAAI,UAAU;CACd,KAAK,MAAM,QAAQ,IAAI,OAAO,OAAO;EACnC,MAAM,WAAW,YAAY,MAAM,GAAG;EACtC,IAAI,UAAU;GACZ,IAAI,SAAS,UAAU,OAAO;GAC9B,SAAS,KAAK;IACZ,MAAM;IACN;IACA,OAAO;IACP,WAAW,SAAS;IACpB,SAAS,SAAS;GACpB,CAAC;GACD,SAAS,QAAQ;GACjB,cAAc,QAAQ;EACxB,OAEE,SAAS,KAAK;GAAE,MAAM;GAAU;GAAM,OADxB,SAAS,MAAM,KAAK,KACW;EAAM,CAAC;EAEtD,MAAM,MAAM,IAAI,IAAI;EACpB,aAAa,KAAK,KAAK,IAAI;EAC3B;CACF;CACA,OAAO;AACT;AAEA,SAAgB,UAAU,KAAuB;CAC/C,MAAM,EAAE,UAAU;CAClB,MAAM,MAAM,WAAW,GAAG;CAC1B,MAAM,OAAO,IAAI,OAAO,MAAM,MAAM;CACpC,IAAI,CAAC,OAAO,CAAC,MAAM;EACjB,MAAM,UAAU;EAChB,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,QAAQ,YAAY,MAAM,GAAG;CACnC,IAAI,CAAC,OAAO;EACV,MAAM,UAAU,GAAG,IAAI,mBAAmB,SAAS,KAAK,IAAI,EAAE;EAC9D,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,UAAU,gBAAgB,KAAK,KAAK,MAAM,KAAK;CACrD,cAAc,GAAG;CACjB,MAAM,UACJ,UAAU,IACN,UAAU,IAAI,MAAM,QAAQ,6BAC5B,GAAG,IAAI;CACb,IAAI,QAAQ;AACd;AAEA,SAAgB,KAAK,KAAuB;CAC1C,MAAM,EAAE,UAAU;CAClB,MAAM,OAAO,MAAM,KAAK,IAAI;CAC5B,IAAI,CAAC,MAAM;EACT,MAAM,UAAU;EAChB,IAAI,QAAQ;EACZ;CACF;CACA,QAAQ,KAAK,MAAb;EACE,KAAK;GACH,KAAK,MAAM,QAAQ,KAAK;GACxB,KAAK,MAAM,MAAM,KAAK;GACtB,MAAM,MAAM,IAAI,KAAK,IAAI;GACzB,MAAM,UAAU,iBAAiB,KAAK,MAAM,IAAI,MAAM,SAAS,KAAK,KAAK,IAAI,EAAE;GAC/E;EACF,KAAK,UAAU;GACb,MAAM,IAAI,KAAK,KAAK,QAAQ,QAAQ,KAAK,KAAK;GAC9C,IAAI,KAAK,GAAG,KAAK,KAAK,QAAQ,OAAO,GAAG,CAAC;GACzC,MAAM,MAAM,IAAI,KAAK,IAAI;GACzB,MAAM,UAAU,gBAAgB,KAAK,MAAM,IAAI,MAAM,SAAS,KAAK,KAAK,IAAI,EAAE;GAC9E;EACF;EACA,KAAK;GACH,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,GAAG,KAAK,KAAK;GAChD,MAAM,MAAM,IAAI,KAAK,IAAI;GACzB,MAAM,UAAU,mBAAmB,KAAK,MAAM,IAAI,MAAM,SAAS,KAAK,KAAK,IAAI,EAAE;GACjF;CACJ;CACA,cAAc,GAAG;CACjB,IAAI,QAAQ;AACd;AAEA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EAAE,UAAU;CAClB,MAAM,OAAO,IAAI,SAAS,MAAM;CAChC,IAAI,CAAC,MAAM;CACX,IAAI,MAAM,QAAQ,IAAI,IAAI,GAAG;EAC3B,IAAI,MAAM,QAAQ,SAAS,GAAG;GAC5B,MAAM,UAAU;GAChB,IAAI,QAAQ;GACZ;EACF;EACA,MAAM,QAAQ,OAAO,IAAI;EACzB,MAAM,UAAU,UAAU,SAAS,KAAK,IAAI,EAAE;CAChD,OAAO;EACL,MAAM,QAAQ,IAAI,IAAI;EACtB,MAAM,UAAU,WAAW,SAAS,KAAK,IAAI,EAAE;CACjD;CACA,cAAc,GAAG;CACjB,IAAI,QAAQ;AACd;AAEA,SAAgB,QAAQ,KAAuB;CAC7C,MAAM,EAAE,UAAU;CAClB,MAAM,OAAO,IAAI,SAAS,MAAM;CAChC,IAAI,CAAC,MAAM;CACX,IAAI,SAAS,IAAI,aAAa;EAC5B,MAAM,UAAU,GAAG,SAAS,KAAK,IAAI,EAAE;EACvC,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,cAAc,CAAC,MAAM,QAAQ,IAAI,IAAI;CAC3C,IAAI,aAAa,MAAM,QAAQ,IAAI,IAAI;CACvC,IAAI,cAAc;CAClB,cAAc,GAAG;CACjB,MAAM,UAAU,cACZ,GAAG,SAAS,KAAK,IAAI,EAAE,kCACvB,GAAG,SAAS,KAAK,IAAI,EAAE;CAC3B,IAAI,QAAQ;AACd;;;ACtIA,eAAsB,UAAU,KAAgC;CAC9D,MAAM,EAAE,UAAU;CAClB,IAAI,MAAM,MAAM,SAAS,GAAG;EAC1B,MAAM,UAAU;EAChB,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,QAAQ,MAAM,MAAM;CAC1B,MAAM,SAAmB,CAAC;CAC1B,KAAK,MAAM,QAAQ,MAAM,OACvB,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,aAAa,IAAI,GAAG,MAAM;CACvD,SAAS,KAAK;EACZ,OAAO,KACL,GAAG,SAAS,KAAK,IAAI,EAAE,IAAK,IAAc,WAAW,OAAO,GAAG,GACjE;CACF;CAEF,IAAI,OAAO,WAAW,GAAG;EACvB,MAAM,MAAM,MAAM;EAClB,MAAM,SAAS,MAAM;EACrB,MAAM,UAAU,SAAS,MAAM,OAAO,UAAU,IAAI,KAAK,IAAI;CAC/D,OACE,MAAM,UAAU,gBAAgB,OAAO,KAAK,IAAI;CAElD,IAAI,QAAQ;AACd;;;ACkCA,IAAa,SAAS;;;AC/CtB,SAAgB,WAAW,KAAiB,QAAgB,QAAQ,IAAU;CAC5E,MAAM,EAAE,UAAU;CAClB,MAAM,SAAS;CACf,MAAM,OAAO;CACb,MAAM,UAAU;CAChB,MAAM,cAAc;CACpB,IAAI,QAAQ;AACd;AAEA,SAAgB,YAAY,KAAiB,MAAqB,MAAY;CAC5E,MAAM,EAAE,UAAU;CAClB,MAAM,SAAS;CACf,MAAM,OAAO;CACb,MAAM,cAAc;CACpB,MAAM,UAAU;CAChB,IAAI,QAAQ;AACd;AAEA,SAAgB,aAAa,KAAuB;CAClD,YAAY,KAAK,YAAY;AAC/B;AAEA,SAAgB,UAAU,KAAuB;CAC/C,MAAM,EAAE,UAAU;CAClB,MAAM,MAAM,WAAW,GAAG;CAC1B,MAAM,OAAO,IAAI,OAAO,MAAM,MAAM;CACpC,IAAI,CAAC,OAAO,CAAC,MAAM;EACjB,MAAM,UAAU;EAChB,IAAI,QAAQ;EACZ;CACF;CAGA,MAAM,QAAQ,YAAY,MAAM,GAAG;CACnC,WAAW,KAAK;EAAE,MAAM;EAAQ;EAAK;CAAK,GAAG,OAAO,SAAS,EAAE;AACjE;AAEA,SAAgB,SAAS,KAAuB;CAC9C,MAAM,OAAO,IAAI,OAAO,MAAM,IAAI,MAAM;CACxC,IAAI,CAAC,MAAM;CACX,WAAW,KAAK;EAAE,MAAM;EAAW;CAAK,CAAC;AAC3C;AAEA,SAAgB,aAAa,KAAuB;CAClD,WAAW,KAAK,EAAE,MAAM,WAAW,CAAC;AACtC;AAEA,SAAgB,YAAY,KAAuB;CACjD,MAAM,EAAE,UAAU;CAClB,MAAM,MAAM,WAAW,GAAG;CAC1B,MAAM,OAAO,IAAI,OAAO,MAAM,MAAM;CACpC,IAAI,CAAC,OAAO,CAAC,MAAM;EACjB,MAAM,UAAU;EAChB,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,QAAQ,YAAY,MAAM,GAAG;CACnC,IAAI,CAAC,OAAO;EACV,MAAM,UAAU,GAAG,IAAI,qBAAqB,SAAS,KAAK,IAAI,EAAE;EAChE,IAAI,QAAQ;EACZ;CACF;CACA,MAAM,MAAM,KAAK,QAAQ,QAAQ,KAAK;CACtC,IAAI,OAAO,GAAG;EACZ,SAAS,KAAK;GAAE,MAAM;GAAa;GAAM;GAAO;EAAI,CAAC;EACrD,KAAK,QAAQ,OAAO,KAAK,CAAC;CAC5B;CACA,MAAM,MAAM,IAAI,IAAI;CACpB,aAAa,KAAK,KAAK,IAAI;CAC3B,cAAc,GAAG;CACjB,MAAM,UAAU,WAAW,IAAI,QAAQ,SAAS,KAAK,IAAI,EAAE;CAC3D,IAAI,QAAQ;AACd;AAEA,SAAgB,aAAa,KAAuB;CAClD,MAAM,EAAE,UAAU;CAClB,IAAI,CAAC,MAAM,QAAQ;CACnB,MAAM,IAAI,MAAM;CAChB,MAAM,MAAM,MAAM;CAElB,IAAI,EAAE,SAAS,QAAQ;EACrB,MAAM,WAAW,YAAY,EAAE,MAAM,EAAE,GAAG;EAC1C,IAAI,UAAU;GACZ,SAAS,KAAK;IACZ,MAAM;IACN,MAAM,EAAE;IACR,OAAO;IACP,WAAW,SAAS;IACpB,SAAS,SAAS;GACpB,CAAC;GACD,SAAS,QAAQ;GACjB,cAAc,QAAQ;GACtB,MAAM,MAAM,IAAI,EAAE,IAAI;GACtB,aAAa,KAAK,EAAE,KAAK,EAAE,IAAI;GAC/B,cAAc,GAAG;GACjB,YACE,KACA,UAAU,EAAE,IAAI,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE,kBAC9C;EACF,OAAO;GAEL,MAAM,QAAQ,SAAS,EAAE,MAAM,EAAE,KAAK,GAAG;GACzC,SAAS,KAAK;IAAE,MAAM;IAAU,MAAM,EAAE;IAAM,OAAO;GAAM,CAAC;GAC5D,MAAM,MAAM,IAAI,EAAE,IAAI;GACtB,aAAa,KAAK,EAAE,KAAK,EAAE,IAAI;GAC/B,cAAc,GAAG;GACjB,YACE,KACA,SAAS,EAAE,IAAI,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE,kBAC7C;EACF;EACA;CACF;CAEA,IAAI,EAAE,SAAS,WAAW;EACxB,MAAM,MAAM,IAAI,KAAK;EACrB,IAAI,CAAC,OAAO,KAAK,GAAG,GAAG;GACrB,MAAM,UAAU,gBAAgB,IAAI,gBAAgB,OAAO,OAAO;GAClE,IAAI,QAAQ;GACZ;EACF;EACA,IAAI,YAAY,EAAE,MAAM,GAAG,GAAG;GAC5B,MAAM,UAAU,GAAG,IAAI,qBAAqB,SAAS,EAAE,KAAK,IAAI,EAAE;GAClE,IAAI,QAAQ;GACZ;EACF;EACA,WAAW,KAAK;GAAE,MAAM;GAAa;GAAK,MAAM,EAAE;EAAK,CAAC;EACxD;CACF;CAEA,IAAI,EAAE,SAAS,aAAa;EAC1B,MAAM,QAAQ,SAAS,EAAE,MAAM,EAAE,KAAK,GAAG;EACzC,SAAS,KAAK;GAAE,MAAM;GAAU,MAAM,EAAE;GAAM,OAAO;EAAM,CAAC;EAC5D,MAAM,MAAM,IAAI,EAAE,IAAI;EACtB,aAAa,KAAK,EAAE,KAAK,EAAE,IAAI;EAC/B,cAAc,GAAG;EACjB,SAAS,KAAK,EAAE,GAAG;EACnB,MAAM,SAAS,IAAI,OAAO,MAAM,QAAQ,EAAE,IAAI;EAC9C,YACE,KACA,SAAS,EAAE,IAAI,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE,kBAC7C;EACA;CACF;CAEA,IAAI,EAAE,SAAS,YAAY;EACzB,MAAM,OAAO,IAAI,KAAK;EACtB,IAAI,CAAC,mBAAmB,IAAI,GAAG;GAC7B,MAAM,UACJ,KAAK,WAAW,IACZ,8BACA,CAAC,KAAK,WAAW,MAAM,IACrB,yCAAyC,KAAK,OAC9C,IAAI,KAAK;GACjB,IAAI,QAAQ;GACZ;EACF;EACA,MAAM,UAAU,KAAK,QAAQ,IAAI,YAAY,IAAI,GAAG,IAAI;EACxD,IAAI,IAAI,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO,GAAG;GAChD,MAAM,UAAU,GAAG,KAAK;GACxB,IAAI,QAAQ;GACZ;EACF;EACA,MAAM,UAAU,mBAAmB,OAAO;EAC1C,IAAI,SAAS,KAAK,OAAO;EACzB,MAAM,QAAQ,IAAI,OAAO;EACzB,MAAM,MAAM,IAAI,OAAO;EACvB,cAAc,GAAG;EACjB,MAAM,SAAS,IAAI,OAAO,MAAM,QAAQ,OAAO;EAC/C,YAAY,KAAK,WAAW,KAAK,2BAA2B;EAC5D;CACF;AACF;;;ACjLA,SAAgB,gBACd,KACA,KACA,SACM;CACN,MAAM,EAAE,UAAU;CAClB,MAAM,UAAU,IAAI;CAEpB,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK,OAAO,QAAQ;CACjD,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK;EAChC,MAAM,cAAc;EACb,UAAe,GAAG;EAAzB;CACF;CACA,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK;EAChC,MAAM,cAAc;EACpB,OAAO,KAAK,GAAG;CACjB;CACA,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK;EAChC,MAAM,cAAc,CAAC,MAAM;EAC3B,MAAM,UAAU,MAAM,cAClB,yCACA;EACJ,OAAO,QAAQ;CACjB;CAEA,MAAM,gBAAgB;EACpB,IAAI,MAAM,MAAM,OAAO,KAAK,CAAC,MAAM,aAAa;GAC9C,MAAM,cAAc;GACpB,MAAM,UAAU,GAAG,MAAM,MAAM,KAAK;GACpC,QAAQ;GACR;EACF;EACA,QAAQ;CACV;CAEA,IAAI,MAAM,eAAe,IAAI,SAAS,KAAK;EACzC,MAAM,cAAc;EACpB,MAAM,UAAU;CAClB;CAEA,IAAI,MAAM,SAAS,WAAW;EAC5B,QAAQ,IAAI,MAAZ;GACE,KAAK,KACH,OAAO,QAAQ;GACjB,KAAK;IACH,MAAM,OAAO;IACb,OAAO,QAAQ;GACjB,KAAK;IACH,MAAM,OAAO;IACb,OAAO,QAAQ;GACjB,KAAK;IACH,MAAM,aAAa,KAAK,IAAI,GAAG,MAAM,aAAa,CAAC;IACnD,OAAO,QAAQ;GACjB,KAAK;IACH,MAAM,aAAa,KAAK,IACtB,IAAI,SAAS,SAAS,GACtB,MAAM,aAAa,CACrB;IACA,OAAO,QAAQ;GACjB,KAAK,SACH,OAAO,cAAc,GAAG;GAC1B,KAAK,KACH,OAAO,QAAQ,GAAG;EACtB;EACA,IAAI,IAAI,aAAa,KAAK,OAAO,cAAc,GAAG;EAClD,IAAI,IAAI,aAAa,OAAO,IAAI,aAAa,KAAK;GAChD,MAAM,WAAW;GACjB,OAAO,QAAQ;EACjB;EACA;CACF;CAEA,QAAQ,IAAI,MAAZ;EACE,KAAK,KACH,OAAO,QAAQ;EACjB,KAAK;GACH,MAAM,OAAO;GACb,OAAO,QAAQ;EACjB,KAAK;GACH,MAAM,SAAS,QAAQ,OAAO,EAAE;GAChC,OAAO,QAAQ;EACjB,KAAK;GACH,MAAM,SAAS,QAAQ,OAAO,CAAC;GAC/B,OAAO,QAAQ;EACjB,KAAK;GACH,IAAI,MAAM,WAAW,GAAG;IAEtB,MAAM,OAAO;IACb,OAAO,QAAQ;GACjB;GACA,MAAM,SAAS,KAAK,IAAI,GAAG,MAAM,SAAS,CAAC;GAC3C,OAAO,QAAQ;EACjB,KAAK;GACH,MAAM,SAAS,KAAK,IAAI,IAAI,OAAO,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC;GACrE,OAAO,QAAQ;EACjB,KAAK;EACL,KAAK,UACH,OAAO,UAAU,GAAG;EACtB,KAAK,KACH,OAAO,SAAS,GAAG;EACrB,KAAK,KACH,OAAO,YAAY,GAAG;EACxB,KAAK,KACH,OAAO,aAAa,GAAG;EACzB,KAAK;GACH,MAAM,YAAY,CAAC,MAAM;GACzB,MAAM,UAAU,MAAM,YAClB,kDACA;GACJ,qBAAqB,GAAG;GACxB,OAAO,QAAQ;EACjB,KAAK,KAAK;GACR,IAAI,IAAI,OAAO;IAGb,IAAI,MAAM,UAAU,SAAS,GAAG;KAC9B,MAAM,UAAU;KAChB,OAAO,QAAQ;IACjB;IACA,MAAM,QAAQ,MAAM,UAAU;IAC9B,MAAM,UAAU,MAAM;IACtB,MAAM,UAAU,YAAY,MAAM;IAClC,qBAAqB,GAAG;IACxB,OAAO,QAAQ;GACjB;GAIA,MAAM,OAAO,MAAM,aAAa,MAAM;GACtC,IAAI,CAAC,MAAM;GACX,MAAM,aACJ,KAAK,SAAS,YACV,KAAK,MACJ,IAAI,UAAU,KAAK,GAAG,KAAA;GAC7B,MAAM,QACJ,eAAA,cAAsC,YAAY;GACpD,IAAI,MAAM,UAAU,IAAI,UAAU,GAAG;IACnC,MAAM,UAAU,OAAO,UAAU;IACjC,MAAM,UAAU,aAAa,MAAM;GACrC,OAAO;IACL,MAAM,UAAU,IAAI,UAAU;IAC9B,MAAM,UAAU,cAAc,MAAM;GACtC;GACA,qBAAqB,GAAG;GACxB,OAAO,QAAQ;EACjB;EACA,KAAK;GAGH,MAAM,WAAW,MAAM,aAAa,WAAW,WAAW;GAC1D,qBAAqB,GAAG;GACxB,MAAM,UACJ,MAAM,aAAa,WACf,8BACA;GACN,OAAO,QAAQ;CAEnB;CAEA,IAAI,IAAI,aAAa,OAAO,IAAI,SAAS,SAAS;EAChD,MAAM,OAAO;EACb,MAAM,UAAU;EAChB,QAAQ;EACR;CACF;CAIA,IAAI,IAAI,aAAa,KAAK,OAAO,UAAU,GAAG;CAE9C,IAAI,IAAI,aAAa,OAAO,IAAI,aAAa,KAAK;EAChD,MAAM,WAAW;EACjB,QAAQ;CACV;AACF;;;ACvLA,SAAgB,gBAAgB,KAAiB,KAAqB;CACpE,MAAM,EAAE,UAAU;CAClB,IAAI,IAAI,SAAS,UAAU;EACzB,MAAM,SAAS;EACf,MAAM,OAAO;EACb,qBAAqB,GAAG;EACxB,IAAI,QAAQ;EACZ;CACF;CACA,IAAI,IAAI,SAAS,UAAU;EACzB,MAAM,OAAO;EACb,IAAI,QAAQ;EACZ;CACF;CACA,IAAI,IAAI,SAAS,aAAa;EAC5B,IAAI,MAAM,OAAO,SAAS,GAAG;GAC3B,MAAM,SAAS,MAAM,OAAO,MAAM,GAAG,EAAE;GACvC,qBAAqB,GAAG;GACxB,IAAI,QAAQ;EACd;EACA;CACF;CAGA,MAAM,MAAM,IAAI,YAAY;CAC5B,IAAI,IAAI,WAAW,KAAK,OAAO,OAAO,QAAQ,KAAQ;EACpD,MAAM,UAAU;EAChB,qBAAqB,GAAG;EACxB,IAAI,QAAQ;CACd;AACF;;;AC/BA,SAAgB,cAAc,KAAiB,KAAqB;CAClE,IACE,IAAI,SAAS,YACb,IAAI,aAAa,OACjB,IAAI,aAAa,OACjB,IAAI,SAAS,KACb;EACA,IAAI,MAAM,WAAW;EACrB,IAAI,QAAQ;CACd;AACF;;;ACHA,SAAgB,gBAAgB,KAAiB,KAAqB;CACpE,MAAM,EAAE,UAAU;CAClB,IAAI,IAAI,SAAS,UAAU;EACzB,aAAa,GAAG;EAChB;CACF;CACA,IAAI,IAAI,SAAS,UAAU;EACzB,aAAa,GAAG;EAChB;CACF;CACA,IAAI,IAAI,SAAS,aAAa;EAC5B,IAAI,MAAM,YAAY,SAAS,GAAG;GAChC,MAAM,cAAc,MAAM,YAAY,MAAM,GAAG,EAAE;GACjD,IAAI,QAAQ;EACd;EACA;CACF;CACA,IAAI,IAAI,QAAQ,IAAI,SAAS,KAAK;EAChC,MAAM,cAAc,CAAC,MAAM;EAC3B,IAAI,QAAQ;EACZ;CACF;CACA,IAAI,IAAI,QAAQ,IAAI,SAAS,OAAO,MAAM,QAAQ;EAChD,MAAM,IAAI,MAAM;EAChB,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,aAAa;GAC/C,MAAM,UAAU,gBAAgB,KAAK,EAAE,KAAK,MAAM,WAAW;GAC7D,cAAc,GAAG;GACjB,YACE,KACA,UAAU,IACN,OAAO,EAAE,IAAI,MAAM,QAAQ,6BAC3B,GAAG,EAAE,IAAI,oCACf;EACF;EACA;CACF;CACA,MAAM,MAAM,IAAI,YAAY;CAC5B,IAAI,CAAC,IAAI,QAAQ,IAAI,WAAW,KAAK,OAAO,OAAO,QAAQ,KAAQ;EACjE,MAAM,eAAe;EACrB,IAAI,QAAQ;CACd;AACF;;;;;;;;ACvCA,SAAgB,YACd,KACA,SACyB;CACzB,QAAQ,QAAkB;EACxB,IAAI,IAAI,MAAM,UAAU,OAAO,cAAc,KAAK,GAAG;EACrD,IAAI,IAAI,MAAM,SAAS,UAAU,OAAO,gBAAgB,KAAK,GAAG;EAChE,IAAI,IAAI,MAAM,SAAS,UAAU,OAAO,gBAAgB,KAAK,GAAG;EAChE,gBAAgB,KAAK,KAAK,OAAO;CACnC;AACF;;;;;;;;ACPA,SAAgB,YACd,UACA,OACA,QACa;CACb,MAAM,OAAO,IAAI,cAAc,UAAU;EACvC,IAAI;EACJ,eAAe;EACf,OAAO;EACP,QAAQ;CACV,CAAC;CACD,SAAS,KAAK,IAAI,IAAI;CAEtB,MAAM,OAAO,IAAI,cAAc,UAAU;EACvC,IAAI;EACJ,eAAe;EACf,UAAU;CACZ,CAAC;CACD,KAAK,IAAI,IAAI;CAEb,MAAM,UAAU,IAAI,cAAc,UAAU;EAC1C,IAAI;EACJ,QAAQ;EACR,aAAa;EACb,OAAO;EACP,eAAe;EACf,OAAO,OAAO;EACd,YAAY;EACZ,UAAU;CACZ,CAAC;CACD,KAAK,IAAI,OAAO;CAEhB,MAAM,YAAY,IAAI,cAAc,UAAU;EAC5C,IAAI;EACJ,QAAQ;EACR,aAAa;EACb,OAAO;EACP,eAAe;EACf,UAAU;EACV,UAAU;EAGV,eAAe;CACjB,CAAC;CACD,KAAK,IAAI,SAAS;CAGlB,MAAM,aAAa,IAAI,cAAc,UAAU;EAC7C,IAAI;EACJ,eAAe;EACf,YAAY;EAGZ,cAAc;CAChB,CAAC;CACD,UAAU,IAAI,UAAU;CAExB,MAAM,YAAY,IAAI,oBAAoB,UAAU;EAClD,IAAI;EACJ,UAAU;EACV,SAAS;EACT,SAAS;EAGT,iBAAiB;GAAE,cAAc;GAAG,eAAe;EAAE;EACrD,gBAAgB;GAAE,eAAe;GAAU,QAAQ,OAAO;EAAQ;CACpE,CAAC;CACD,UAAU,IAAI,SAAS;CAEvB,MAAM,SAAS,IAAI,cAAc,UAAU;EACzC,IAAI;EACJ,eAAe;EACf,YAAY;EACZ,UAAU;CACZ,CAAC;CACD,KAAK,IAAI,MAAM;CAEf,MAAM,QAAQ,IAAI,cAAc,UAAU;EACxC,IAAI;EACJ,eAAe;EACf,QAAQ;EACR,YAAY;CACd,CAAC;CACD,OAAO,IAAI,KAAK;CAEhB,MAAM,QAAQ,IAAI,cAAc,UAAU;EACxC,IAAI;EACJ,eAAe;EACf,QAAQ;EACR,YAAY;CACd,CAAC;CACD,OAAO,IAAI,KAAK;CAEhB,MAAM,SAAS,IAAI,eAAe,UAAU;EAC1C,IAAI;EACJ,SAAS;EACT,IAAI,MAAM;EACV,UAAU;EACV,QAAQ;CACV,CAAC;CACD,OAAO,IAAI,MAAM;CAKjB,MAAM,YAAY,IAAI,cAAc,UAAU;EAC5C,IAAI;EACJ,UAAU;EACV,KAAK;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,OAAO;EACP,UAAU;EACV,UAAU;EACV,SAAS;EACT,iBAAiB,KAAK,QAAQ,SAAS;EACvC,eAAe;CACjB,CAAC;CACD,MAAM,cAAc,IAAI,eAAe,UAAU;EAC/C,IAAI;EACJ,SAAS;EACT,IAAI,MAAM;EACV,QAAQ;EACR,UAAU;CACZ,CAAC;CACD,MAAM,eAAe,IAAI,eAAe,UAAU;EAChD,IAAI;EACJ,SAAS;EACT,IAAI,MAAM;EACV,QAAQ;EACR,WAAW;EACX,UAAU;CACZ,CAAC;CACD,MAAM,aAAa,IAAI,eAAe,UAAU;EAC9C,IAAI;EACJ,SAAS;EACT,IAAI,MAAM;EACV,QAAQ;EACR,WAAW;EACX,UAAU;CACZ,CAAC;CACD,UAAU,IAAI,WAAW;CACzB,UAAU,IAAI,YAAY;CAC1B,UAAU,IAAI,UAAU;CACxB,SAAS,KAAK,IAAI,SAAS;CAG3B,MAAM,YAAY,IAAI,cAAc,UAAU;EAC5C,IAAI;EACJ,UAAU;EACV,KAAK;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,OAAO;EACP,UAAU;EACV,UAAU;EACV,SAAS;EACT,iBAAiB,KAAK,QAAQ,SAAS;EACvC,eAAe;CACjB,CAAC;CAGD,MAAM,aAAa,IAAI,cAAc,UAAU;EAC7C,IAAI;EACJ,eAAe;EACf,UAAU;CACZ,CAAC;CACD,MAAM,aAAa,IAAI,eAAe,UAAU;EAC9C,IAAI;EACJ,SAAS;EACT,IAAI,MAAM;EACV,QAAQ;EACR,WAAW;EACX,UAAU;CACZ,CAAC;CACD,UAAU,IAAI,UAAU;CACxB,UAAU,IAAI,UAAU;CACxB,SAAS,KAAK,IAAI,SAAS;CAK3B,MAAM,aAAa,IAAI,cAAc,UAAU;EAC7C,IAAI;EACJ,UAAU;EACV,KAAK;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,iBAAiB,KAAK,QAAQ,SAAS;EACvC,SAAS;EACT,SAAS;CACX,CAAC;CACD,SAAS,KAAK,IAAI,UAAU;CAK5B,MAAM,UAAU,IAAI,cAAc,UAAU;EAC1C,IAAI;EACJ,UAAU;EACV,KAAK;EACL,QAAQ;EACR,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,aAAa;EACb,OAAO;EACP,UAAU;EACV,UAAU;EACV,SAAS;EACT,iBAAiB,KAAK,QAAQ,SAAS;EACvC,eAAe;CACjB,CAAC;CACD,SAAS,KAAK,IAAI,OAAO;CAEzB,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;ACnQA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EACJ,IAAI,EAAE,WAAW,aAAa,gBAC9B,QACA,UACE;CACJ,MAAM,OAAO,MAAM,SAAS;CAC5B,UAAU,UAAU;CACpB,IAAI,CAAC,MAAM;CAGX,YAAY,UAAU,KAAK,MAAM,OAAO;CACxC,MAAM,UAAU,MAAM,YAAY;CAClC,MAAM,QAAQ,OAAO,KAAK;CAC1B,aAAa,UACX,MAAM,OAAO,WAAW,IACpB,kCACA,YAAY,QAAQ,MAAM,MAAM;AACxC;;;AClBA,SAAgB,kBAAkB,MAA2B;CAC3D,MAAM,WAAW,CAAC,GAAG,KAAK,YAAY,CAAC;CACvC,KAAK,MAAM,SAAS,UAAU,KAAK,OAAO,KAAK;AACjD;;;ACUA,SAAS,SACP,OACA,OACa;CAGb,MAAM,MAAmB,CAAC;CAC1B,MAAM,SAAS,MAAM,MAAM;EACzB,IAAI,IAAI,GAAG,IAAI,KAAK;GAAE,MAAM;GAAO,IAAI,MAAM;EAAM,CAAC;EACpD,IAAI,KAAK;GAAE,MAAM;GAAK,IAAI,MAAM;EAAM,CAAC;EACvC,IAAI,KAAK;GAAE,MAAM,KAAK;GAAK,IAAI,MAAM;EAAG,CAAC;EACzC,IAAI,KAAK;GAAE,MAAM;GAAM,IAAI,MAAM;EAAM,CAAC;EACxC,IAAI,KAAK;GAAE,MAAM,KAAK;GAAO,IAAI,MAAM;EAAG,CAAC;CAC7C,CAAC;CACD,OAAO;AACT;AAEA,SAAgB,cACd,KACA,UACA,MACM;CACN,kBAAkB,GAAG;CACrB,KAAK,SAAS,KAAK,MAAM;EACvB,IAAI,IACF,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,IAAI,GAAG,OAAO;GACrB,SAAS,IAAI;GACb,IAAI,IAAI;GACR,QAAQ;GACR,UAAU;EACZ,CAAC,CACH;CACF,CAAC;AACH;AAEA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EACJ,IAAI,EAAE,OAAO,OAAO,UACpB,UACA,OACA,UACE;CACJ,MAAM,QAAQ,MAAM,MAAM;CAC1B,MAAM,YACJ,QAAQ,IACJ;EACE;GAAE,MAAM;GAAO,IAAI,MAAM;EAAM;EAC/B;GAAE,MAAM;GAAK,IAAI,MAAM;EAAS;EAChC;GAAE,MAAM,IAAI,MAAM;GAAW,IAAI,MAAM;EAAG;CAC5C,IACA,CAAC;CAEP,IAAI,MAAM,SAAS,UAAU;EAC3B,cAAc,OAAO,UAAU,CAC7B,GAAG,SACD,CACE;GAAE,KAAK;GAAS,OAAO;EAAc,GACrC;GAAE,KAAK;GAAO,OAAO;EAAQ,CAC/B,GACA,KACF,GACA,GAAG,SACL,CAAC;EACD,cAAc,OAAO,UAAU,CAAC;GAAE,MAAM;GAAY,IAAI,MAAM;EAAM,CAAC,CAAC;CACxE,OAAO,IAAI,MAAM,SAAS,UAAU;EAClC,cAAc,OAAO,UAAU,CAAC,CAAC;EACjC,cAAc,OAAO,UAAU,CAAC,CAAC;CACnC,OAAO,IAAI,MAAM,SAAS,WAAW;EACnC,cAAc,OAAO,UAAU,CAC7B,GAAG,SACD;GACE;IAAE,KAAK;IAAM,OAAO;GAAO;GAC3B;IAAE,KAAK;IAAS,OAAO;GAAS;GAChC;IAAE,KAAK;IAAK,OAAO;GAAW;GAC9B;IAAE,KAAK;IAAS,OAAO;GAAS;GAChC;IAAE,KAAK;IAAM,OAAO;GAAO;GAC3B;IAAE,KAAK;IAAK,OAAO;GAAO;GAC1B;IAAE,KAAK;IAAK,OAAO;GAAO;EAC5B,GACA,KACF,GACA,GAAG,SACL,CAAC;EACD,cAAc,OAAO,UAAU,CAAC;GAAE,MAAM;GAAc,IAAI,MAAM;EAAM,CAAC,CAAC;CAC1E,OAAO;EACL,cAAc,OAAO,UAAU,CAC7B,GAAG,SACD;GACE;IAAE,KAAK;IAAQ,OAAO;GAAO;GAC7B;IAAE,KAAK;IAAO,OAAO;GAAQ;GAC7B;IAAE,KAAK;IAAK,OAAO;GAAO;GAC1B;IAAE,KAAK;IAAK,OAAO;GAAU;GAC7B;IAAE,KAAK;IAAK,OAAO;GAAU;GAC7B;IAAE,KAAK;IAAK,OAAO;GAAW;GAC9B;IAAE,KAAK;IAAK,OAAO;GAAc;GACjC;IAAE,KAAK;IAAK,OAAO;GAAW;GAC9B;IAAE,KAAK;IAAM,OAAO;GAAU;GAC9B;IAAE,KAAK;IAAM,OAAO;GAAO;GAC3B;IAAE,KAAK;IAAM,OAAO;GAAO;GAC3B;IAAE,KAAK;IAAK,OAAO;GAAS;GAC5B;IAAE,KAAK;IAAO,OAAO;GAAO;GAC5B;IAAE,KAAK;IAAK,OAAO;GAAO;EAC5B,GACA,KACF,GACA,GAAG,SACL,CAAC;EACD,cAAc,OAAO,UAAU;GAC7B;IAAE,MAAM;IAAU,IAAI,MAAM;GAAM;GAClC;IAAE,MAAM,MAAM,YAAY,UAAU;IAAO,IAAI,MAAM;GAAG;GACxD;IAAE,MAAM;IAAgB,IAAI,MAAM;GAAM;GACxC;IAAE,MAAM,MAAM;IAAU,IAAI,MAAM;GAAG;GACrC;IAAE,MAAM;IAAkB,IAAI,MAAM;GAAM;GAC1C;IAAE,MAAM,MAAM,cAAc,UAAU;IAAU,IAAI,MAAM;GAAG;EAC/D,CAAC;CACH;CACA,OAAO,UAAU,MAAM,WAAW;AACpC;;;AClIA,SAAgB,iBAA6B;CAC3C,OAAO;EACL;GAAE,MAAM;GAAU,MAAM;EAAQ;EAChC;GACE,MAAM;GACN,MAAM;EACR;EACA;GACE,MAAM;GACN,MAAM;EACR;EACA,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAoB;EAC5C;GAAE,MAAM;GAAS,MAAM;EAAwC;EAC/D;GAAE,MAAM;GAAS,MAAM;EAAyC;EAChE,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAgB;EACxC;GAAE,MAAM;GAAS,MAAM;EAAqC;EAC5D;GAAE,MAAM;GAAS,MAAM;EAA4C;EACnE;GAAE,MAAM;GAAS,MAAM;EAAkD;EACzE;GAAE,MAAM;GAAS,MAAM;EAAqC;EAC5D,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAU;EAClC;GAAE,MAAM;GAAS,MAAM;EAA8C;EACrE;GAAE,MAAM;GAAS,MAAM;EAA8C;EACrE;GACE,MAAM;GACN,MAAM;EACR;EACA;GAAE,MAAM;GAAS,MAAM;EAA8C;EACrE;GACE,MAAM;GACN,MAAM;EACR;EACA;GACE,MAAM;GACN,MAAM;EACR;EACA;GAAE,MAAM;GAAS,MAAM;EAAgD;EACvE;GAAE,MAAM;GAAS,MAAM;EAA4C;EACnE;GACE,MAAM;GACN,MAAM;EACR;EACA;GACE,MAAM;GACN,MAAM;EACR;EACA,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAO;EAC/B;GAAE,MAAM;GAAS,MAAM;EAAkC;EACzD;GAAE,MAAM;GAAS,MAAM;EAA4C;EACnE;GAAE,MAAM;GAAS,MAAM;EAA+C;EACtE;GAAE,MAAM;GAAS,MAAM;EAAgD;EACvE,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAc;EACtC;GAAE,MAAM;GAAS,MAAM;EAA0C;EACjE;GAAE,MAAM;GAAS,MAAM;EAA4C;EACnE;GAAE,MAAM;GAAS,MAAM;EAAiC;EACxD,EAAE,MAAM,QAAQ;EAChB;GAAE,MAAM;GAAU,MAAM;EAAa;EACrC;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;EACA;GACE,MAAM;GACN,QAAQ;GACR,OAAO,KAAK,QAAQ,SAAS;GAC7B,aAAa;EACf;CACF;AACF;;;AC5EA,SAAgB,eACd,MACA,QACA,OACA,SACA,UACA,OACA,eACU;CACV,MAAM,KAAK,UAAU,MAAM,UAAU,KAAA;CACrC,MAAM,WAAW,WAAW;EAAE,MAAM;EAAK,IAAI,MAAM;CAAS,IAAI,KAAA;CAChE,IAAI,KAAK,UAAU,WACjB,OAAO;EACL,MAAM;EACN,IAAI,MAAM;EACV;EACA;EACA,MAAM;GAAE,MAAM;GAAK,IAAI,MAAM;EAAQ;EACrC;CACF;CAEF,MAAM,QAAQ,KAAK,SAAS;CAC5B,IAAI,UAAU,MAAM,cAAc,KAAK,GACrC,OAAO;EACL,MAAM;EACN,IAAI,MAAM;EACV;EACA;EACA,MAAM;GAAE,MAAM;GAAK,IAAI,MAAM;EAAY;EACzC;CACF;CAEF,MAAM,UAAU,UAAU,MAAM,CAAC;CACjC,MAAM,cAAc,UAAU,YAAY,YAAY,OAAO,MAAM;CACnE,MAAM,YAAY,UAAU,MAAM,QAAQ,MAAM;CAChD,IAAI,KAAK,UAAU,WACjB,OAAO;EACL,MAAM;EACN,IAAI;EACJ;EACA;EACA,MAAM;GAAE,MAAM;GAAK,IAAI,MAAM;EAAQ;EACrC;CACF;CAEF,IAAI,KAAK,UAAU,SACjB,OAAO;EACL,MAAM;EACN,IAAI;EACJ;EACA;EACA,MAAM;GAAE,MAAM;GAAK,IAAI,MAAM;EAAM;EACnC;CACF;CAEF,OAAO;EAAE,MAAM;EAAa,IAAI;EAAW;EAAO;EAAI;CAAS;AACjE;AAEA,SAAgB,aACd,UACA,IACA,MACA,OACe;CACf,MAAM,MAAM,IAAI,cAAc,UAAU;EACtC;EACA,eAAe;EACf,QAAQ;EACR,YAAY;CACd,CAAC;CACD,IAAI,KAAK,SAAS,UAChB,IAAI,IACF,IAAI,eAAe,UAAU;EAC3B,IAAI,GAAG,GAAG;EACV,SAAS,KAAK;EACd,IAAI,MAAM;EACV,UAAU;EACV,QAAQ;CACV,CAAC,CACH;MACK,IAAI,KAAK,SAAS,SACvB,IAAI,IACF,IAAI,eAAe,UAAU;EAC3B,IAAI,GAAG,GAAG;EACV,SAAS,KAAK;EACd,IAAI,MAAM;EACV,UAAU;EACV,QAAQ;CACV,CAAC,CACH;MACK,IAAI,KAAK,SAAS,UAAU;EACjC,IAAI,IACF,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,GAAG;GACV,SAAS,KAAK,KAAK,OAAO,OAAO,EAAE;GACnC,IAAI,KAAK;GACT,UAAU;GACV,QAAQ;EACV,CAAC,CACH;EACA,IAAI,IACF,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,GAAG;GACV,SAAS,KAAK;GACd,IAAI,MAAM;GACV,UAAU;GACV,QAAQ;EACV,CAAC,CACH;CACF;CACA,OAAO;AACT;AAEA,SAAgB,oBACd,UACA,IACA,MACA,OACA,MACA,OACe;CAMf,MAAM,WAAW,QAAQ;CAMzB,MAAM,OAAc;EAClB;GAAE,MAAM,IANQ,KAAK,YAAY,MAAM,IAMjB;GAAI,IAAI,MAAM;EAAM;EAC1C;GAAE,MAAM;GAAU,IAAI,MAAM;EAAG;EAC/B;GAAE,MAAM;GAAM,IAAI,MAAM;EAAM;CAChC;CACA,IAAI,KAAK,UAAU,GAAG;EACpB,KAAK,KAAK;GAAE,MAAM;GAAM,IAAI,MAAM;EAAQ,CAAC;EAC3C,KAAK,KAAK;GAAE,MAAM,GAAG,KAAK;GAAW,IAAI,MAAM;EAAQ,CAAC;EACxD,KAAK,KAAK;GAAE,MAAM;GAAc,IAAI,MAAM;EAAG,CAAC;CAChD;CACA,IAAI,KAAK,QAAQ,GAAG;EAClB,KAAK,KAAK;GAAE,MAAM;GAAM,IAAI,MAAM;EAAQ,CAAC;EAC3C,KAAK,KAAK;GAAE,MAAM,GAAG,KAAK;GAAS,IAAI,MAAM;EAAQ,CAAC;EACtD,KAAK,KAAK;GAAE,MAAM;GAAK,IAAI,MAAM;EAAM,CAAC;EACxC,KAAK,KAAK;GAAE,MAAM,GAAG,KAAK;GAAS,IAAI,MAAM;EAAQ,CAAC;EACtD,KAAK,KAAK;GAAE,MAAM;GAAY,IAAI,MAAM;EAAG,CAAC;CAC9C;CACA,IAAI,KAAK,YAAY,KAAK,KAAK,UAAU,GAAG;EAC1C,KAAK,KAAK;GAAE,MAAM,GAAG,KAAK;GAAS,IAAI,MAAM;EAAM,CAAC;EACpD,KAAK,KAAK;GAAE,MAAM;GAAW,IAAI,MAAM;EAAG,CAAC;CAC7C;CACA,KAAK,KAAK;EAAE,MAAM;EAAK,IAAI,MAAM;CAAM,CAAC;CAExC,MAAM,cAAc,KAAK,QAAQ,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;CAClE,MAAM,OAAO;CACb,MAAM,UAAU,KAAK,IAAI,GAAG,QAAQ,CAAC;CACrC,MAAM,YAAY,KAAK,IAAI,GAAG,KAAK,OAAO,UAAU,eAAe,CAAC,CAAC;CACrE,MAAM,WAAW,KAAK,IAAI,GAAG,UAAU,YAAY,WAAW;CAE9D,MAAM,MAAM,IAAI,cAAc,UAAU;EACtC;EACA,eAAe;EACf,YAAY;EACZ,QAAQ;EACR,UAAU;EACV,GAAI,KAAK,UAAU,EAAE,iBAAiB,MAAM,QAAQ,IAAI,CAAC;CAC3D,CAAC;CACD,IAAI,IACF,IAAI,eAAe,UAAU;EAC3B,IAAI,GAAG,GAAG;EACV,SAAS,KAAK,OAAO,SAAS;EAC9B,IAAI,MAAM;EACV,QAAQ;EACR,UAAU;CACZ,CAAC,CACH;CACA,KAAK,SAAS,KAAK,MAAM;EACvB,IAAI,IACF,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,GAAG,OAAO;GACjB,SAAS,IAAI;GACb,IAAI,IAAI;GACR,QAAQ;GACR,UAAU;EACZ,CAAC,CACH;CACF,CAAC;CACD,IAAI,IACF,IAAI,eAAe,UAAU;EAC3B,IAAI,GAAG,GAAG;EACV,SAAS,KAAK,OAAO,QAAQ;EAC7B,IAAI,MAAM;EACV,QAAQ;EACR,UAAU;CACZ,CAAC,CACH;CACA,OAAO;AACT;AAEA,SAAgB,SACd,UACA,UACA,OACA,MACe;CACf,MAAM,MAAM,IAAI,cAAc,UAAU;EACtC,IAAI;EACJ,eAAe;EACf,YAAY;EACZ,QAAQ;CACV,CAAC;CACD,MAAM,SAAS,MAAM,MAAM;EACzB,MAAM,WAA2D;GAC/D,IAAI,GAAG,SAAS,IAAI;GACpB,OAAO,KAAK;GACZ,QAAQ;GACR,eAAe;GACf,YAAY;GACZ,UAAU;EACZ;EACA,IAAI,KAAK,IAAI,SAAS,kBAAkB,KAAK;EAC7C,MAAM,UAAU,IAAI,cAAc,UAAU,QAAQ;EACpD,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,QAAQ,OAAO,CAAC;EACpD,MAAM,UAAU,KAAK,OAAO,KAAK,KAAK,KAAK,SAAS,IAAI;EACxD,MAAM,cAAc,KAAK,WAAW,KAAK,SAAS,KAAK,SAAS,IAAI;EACpE,MAAM,YAAY,KAAK,IAAI,GAAG,aAAa,UAAU,WAAW;EAChE,IAAI,KAAK,MACP,QAAQ,IACN,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,SAAS,IAAI,EAAE;GACtB,SAAS,GAAG,KAAK,KAAK,KAAK;GAC3B,IAAI,KAAK,KAAK;GACd,QAAQ;GACR,UAAU;EACZ,CAAC,CACH;EAEF,QAAQ,IACN,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,SAAS,IAAI,EAAE;GACtB,SAAS,SAAS,KAAK,MAAM,SAAS;GACtC,IAAI,KAAK;GACT,QAAQ;GACR,UAAU;GACV,UAAU;EACZ,CAAC,CACH;EACA,IAAI,KAAK,UACP,QAAQ,IACN,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,SAAS,IAAI,EAAE;GACtB,SAAS,IAAI,KAAK,SAAS;GAC3B,IAAI,KAAK,SAAS;GAClB,QAAQ;GACR,UAAU;EACZ,CAAC,CACH;EAEF,IAAI,IAAI,OAAO;CACjB,CAAC;CACD,OAAO;AACT;;;AC1RA,SAAgB,YAAY,KAAuB;CACjD,MAAM,EACJ,IAAI,EAAE,WACN,UACA,OACA,UACE;CACJ,QAAQ,UAAU,MAAM;CACxB,IAAI,CAAC,MAAM,UAAU;CACrB,kBAAkB,OAAO;CACzB,MAAM,QAAQ,eAAe;CAE7B,MAAM,SAAS,SAAS,gBAAgB;CACxC,MAAM,QAAQ,SAAS,iBAAiB;CAExC,IADkB,UAAU,OACb;EACb,MAAM,SAAS,IAAI,oBAAoB,UAAU;GAC/C,IAAI;GACJ,UAAU;GACV,SAAS;GACT,SAAS;GACT,iBAAiB,EAAE,cAAc,EAAE;GACnC,gBAAgB,EAAE,eAAe,SAAS;EAC5C,CAAC;EACD,QAAQ,IAAI,MAAM;EAClB,MAAM,SAAS,MAAM,MAAM;GACzB,OAAO,QAAQ,IAAI,aAAa,UAAU,QAAQ,KAAK,MAAM,KAAK,CAAC;EACrE,CAAC;EACD;CACF;CAEA,MAAM,OAAO,IAAI,cAAc,UAAU;EACvC,IAAI;EACJ,eAAe;EACf,UAAU;EACV,WAAW;CACb,CAAC;CACD,MAAM,OAAO,IAAI,cAAc,UAAU;EACvC,IAAI;EACJ,eAAe;EACf,UAAU;EACV,WAAW;CACb,CAAC;CACD,MAAM,QAAQ,IAAI,cAAc,UAAU;EACxC,IAAI;EACJ,eAAe;EACf,UAAU;EACV,WAAW;CACb,CAAC;CACD,MAAM,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC;CACxC,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,MAAM,IAAI,MAAM,QAAQ,KACnC,IAAI,MAAM,EAAE,EAAE,SAAS,SAAS;EAC9B,WAAW,IAAI;EACf;CACF;CAEF,MACG,MAAM,GAAG,QAAQ,CAAC,CAClB,SAAS,MAAM,MACd,KAAK,IAAI,aAAa,UAAU,UAAU,KAAK,MAAM,KAAK,CAAC,CAC7D;CACF,MACG,MAAM,QAAQ,CAAC,CACf,SAAS,MAAM,MACd,MAAM,IAAI,aAAa,UAAU,UAAU,KAAK,MAAM,KAAK,CAAC,CAC9D;CACF,KAAK,IAAI,IAAI;CACb,KAAK,IAAI,KAAK;CACd,QAAQ,IAAI,IAAI;AAClB;;;AC/DA,SAAgB,YAAY,QAAgB,OAAsB;CAChE,MAAM,UAAU,MAAM,YAAY;CAClC,MAAM,QAAQ,OAAO,KAAK;CAC1B,MAAM,QAAkB,CAAC,GAAG,MAAM,MAAM;CACxC,IAAI,MAAM,WAAW,MAAM,KAAK,SAAS,QAAQ,GAAG,OAAO;MACtD,IAAI,MAAM,UAAU,YAAY,OACnC,MAAM,KAAK,IAAI,MAAM,OAAO,IAAI,QAAQ,GAAG,OAAO;CAEpD,OAAO,aAAa,MAAM,KAAK,KAAK,EAAE;AACxC;;;;;;AAOA,SAAgB,qBAAqB,KAAyB;CAC5D,MAAM,EAAE,UAAU,QAAQ,WAAW;CACrC,MAAM,YAAY,KAAK,IACrB,GACA,SAAS,gBAAgB,OAAO,gBAAgB,IAAI,OAAO,aAC7D;CACA,MAAM,OAAO,OAAO,MAAM,SACtB,KAAK,MAAM,YAAY,OAAO,MAAM,MAAM,IAC1C,OAAO;CACX,OAAO,KAAK,IAAI,OAAO,eAAe,IAAI;AAC5C;AAEA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EACJ,IAAI,EAAE,WAAW,YAAY,aAC7B,UACA,QACA,OACA,OACA,QACA,eACE;CACJ,MAAM,YAAY,IAAI;CACtB,MAAM,gBAAgB,qBAAqB,GAAG;CAC9C,UAAU,QAAQ,YAAY,QAAQ,KAAK;CAC3C,kBAAkB,UAAU;CAC5B,kBAAkB,UAAU,OAAO;CAEnC,WAAW,IACT,SACE,UACA,UACA,CACE;EAAE,MAAM;EAAO,IAAI,MAAM;EAAU,OAAO,OAAO;CAAc,GAC/D,GAAG,OAAO,MAAM,KAAK,OAAO;EAC1B,MAAM,SAAS,EAAE,IAAI;EACrB,IAAI,MAAM;EACV,OAAO;CACT,EAAE,CACJ,GACA,OAAO,UACT,CACF;CAMA,MAAM,aAAa,OAAO,gBAAgB,gBAAgB,OAAO,MAAM;CACvE,MAAM,eAAe,gBAAgB,QAAQ,WAAW,KAAK;CAE7D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,aAAa,QAAQ,KAAK;EAClD,MAAM,OAAO,MAAM,aAAa;EAChC,IAAI,KAAK,SAAS,WAAW;GAC3B,MAAM,aAAa,KAAK;GACxB,MAAM,cAAc,eAAe,cAAc,KAAA,IAAY;GAC7D,MAAM,OAAO,aAAa,IAAI,UAAU,KAAK;IAC3C,OAAO;IACP,SAAS;IACT,OAAO;GACT;GACA,MAAM,UAAU,MAAM,SAAS,YAAY,MAAM,MAAM;GACvD,UAAU,QAAQ,IAChB,oBACE,UACA,OAAO,KACP,aACA,YACA;IACE,GAAG;IACH,WAAW,MAAM,UAAU,IAAI,UAAU;IACzC;GACF,GACA,KACF,CACF;GACA;EACF;EACA,MAAM,MAAM,KAAK;EACjB,MAAM,SAAS,WAAW,YAAY,GAAG,KAAK,CAAC,MAAM;EACrD,MAAM,QAAoB,CACxB;GAAE,MAAM;GAAK,IAAI,MAAM;GAAI,OAAO,OAAO;EAAc,CACzD;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,MAAM,QAAQ,KAAK;GAC5C,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,KAAK,KAAK,IAAI;GAClC,MAAM,UACJ,MAAM,SAAS,YAAY,MAAM,MAAM,UAAU,MAAM,MAAM;GAC/D,MAAM,aAAa,MAAM,SAAS,IAAI,GAAG,IAAI,GAAG,KAAK,MAAM;GAC3D,MAAM,KACJ,eACE,MACA,QACA,eACA,SACA,YACA,OACA,WAAW,kBACb,CACF;EACF;EACA,UAAU,QAAQ,IAChB,SAAS,UAAU,OAAO,KAAK,OAAO,OAAO,UAAU,CACzD;CACF;CAMA,IAAI,MAAM,SAAS,YAAY,MAAM,aAAa,SAAS,GAAG;EAC5D,MAAM,SAAS,OAAO,MAAM;EAC5B,mBAAmB;GACjB,IAAI;IACF,UAAU,oBAAoB,MAAM;GACtC,QAAQ,CAER;EACF,CAAC;CACH;AACF;;;AC9IA,SAAgB,gBAAgB,GAAmB;CACjD,QAAQ,EAAE,MAAV;EACE,KAAK,QACH,OAAO,SAAS,EAAE,IAAI,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE;EACpD,KAAK,WACH,OAAO,mBAAmB,SAAS,EAAE,KAAK,IAAI,EAAE;EAClD,KAAK,aACH,OAAO,cAAc,EAAE,IAAI,MAAM,SAAS,EAAE,KAAK,IAAI,EAAE;EACzD,KAAK,YACH,OAAO;CACX;AACF;AAEA,SAAgB,cAAc,KAAuB;CACnD,MAAM,EACJ,IAAI,EAAE,WAAW,YAAY,cAC7B,UACA,QACA,OACA,OACA,eACE;CACJ,MAAM,OAAO,MAAM,SAAS,YAAY,MAAM,WAAW;CACzD,UAAU,UAAU;CACpB,IAAI,CAAC,QAAQ,CAAC,MAAM,QAAQ;CAE5B,UAAU,QAAQ,gBAAgB,MAAM,MAAM;CAG9C,MAAM,IAAI,MAAM;CAChB,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,aAClC,WAAW,UACT;MAGF,WAAW,UAAU;CAMvB,kBAAkB,UAAU;CAG5B,WAAW,IACT,IAAI,eAAe,UAAU;EAC3B,IAAI;EACJ,SAAS,KAAK,MAAM,YAAY;EAChC,IAAI,MAAM;EACV,QAAQ;EACR,UAAU;CACZ,CAAC,CACH;CAIA,IAAI,MAAM,SACR,WAAW,IACT,IAAI,eAAe,UAAU;EAC3B,IAAI;EACJ,SAAS,KAAK,MAAM;EACpB,IAAI,MAAM;EACV,QAAQ;EACR,WAAW;EACX,UAAU;CACZ,CAAC,CACH;CAGF,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,aAAa;EAC/C,MAAM,SAAS,WAAW,YAAY,EAAE,GAAG,KAAK,CAAC,MAAM;EACvD,MAAM,YAAY,KAAK,IACrB,IACA,KAAK,IAAI,GAAG,OAAO,MAAM,KAAK,MAAM,SAAS,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAClE;EAEA,WAAW,IACT,IAAI,eAAe,UAAU;GAC3B,IAAI;GACJ,SAAS;GACT,IAAI,MAAM;GACV,UAAU;GACV,QAAQ;GACR,WAAW;EACb,CAAC,CACH;EAEA,KAAK,MAAM,QAAQ,OAAO,OAAO;GAC/B,MAAM,WAAW,SAAS,EAAE;GAC5B,MAAM,MAAM,IAAI,cAAc,UAAU;IACtC,IAAI,cAAc,KAAK;IACvB,eAAe;IACf,QAAQ;IACR,YAAY;GACd,CAAC;GACD,IAAI,IACF,IAAI,eAAe,UAAU;IAC3B,IAAI,cAAc,KAAK,KAAK;IAC5B,SAAS,GAAG,WAAW,MAAM,IAAI,GAAG,SAAS,KAAK,IAAI,IAAI,OACxD,SACF;IACA,IAAI,WAAW,MAAM,SAAS,MAAM;IACpC,QAAQ;IACR,UAAU;GACZ,CAAC,CACH;GACA,MAAM,QAAQ,YAAY,MAAM,EAAE,GAAG;GACrC,MAAM,UAAU,QAAQ,YAAY,MAAM,OAAO,MAAM,IAAI;GAC3D,IAAI,IACF,IAAI,eAAe,UAAU;IAC3B,IAAI,cAAc,KAAK,KAAK;IAC5B,SAAS;IACT,IAAI,CAAC,QAAQ,MAAM,UAAU,WAAW,MAAM,KAAK,MAAM;IACzD,QAAQ;IACR,UAAU;GACZ,CAAC,CACH;GACA,WAAW,IAAI,GAAG;EACpB;CACF;AACF;;;AC1HA,SAAgB,eAAe,KAAuB;CACpD,MAAM,EACJ,IAAI,EAAE,WACN,UACA,QACA,UACA,OACA,UACE;CACJ,MAAM,QAAQ,SAAS;CACvB,MAAM,UAAU,MAAM,QAAQ;CAC9B,QAAQ,QACN,MAAM,SAAS,YACX,UAAU,QAAQ,GAAG,MAAM,eAC3B,UAAU,QAAQ,GAAG,MAAM;CACjC,kBAAkB,OAAO;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,OAAO,SAAS;EACtB,MAAM,SAAS,SAAS,OAAO;EAC/B,MAAM,UAAU,MAAM,MAAM,IAAI,IAAI;EACpC,MAAM,YAAY,MAAM,QAAQ,IAAI,IAAI;EACxC,MAAM,YAAY,OAAO,MAAM,QAAQ,IAAI;EAC3C,MAAM,aAAa,aAAa,cAAc,MAAM;EACpD,MAAM,cAAc,MAAM,SAAS,aAAa,MAAM,MAAM;EAC5D,MAAM,SAAS,CAAC,YAAY,MAAM,QAAQ,SAAS,MAAM,SAAS,MAAM;EAExE,MAAM,MAAM,IAAI,cAAc,UAAU;GACtC,IAAI,QAAQ,KAAK;GACjB,eAAe;GACf,QAAQ;GACR,YAAY;GACZ,GAAI,cAAc,EAAE,iBAAiB,MAAM,QAAQ,IAAI,CAAC;EAC1D,CAAC;EACD,MAAM,QAAQ,IAAY,MAAc,OACtC,IAAI,eAAe,UAAU;GAC3B,IAAI,GAAG,IAAI,GAAG,GAAG;GACjB,SAAS;GACT;GACA,QAAQ;GACR,UAAU;EACZ,CAAC;EACH,IAAI,IAAI,KAAK,SAAS,GAAG,cAAc,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;EAC9D,IAAI,IACF,KACE,SACA,GAAG,UAAU,MAAM,IAAI,IACvB,UAAU,MAAM,UAAU,MAAM,KAClC,CACF;EACA,IAAI,IACF,KACE,QACA,GAAG,SAAS,MAAM,IAAI,IACtB,SAAS,MAAM,SAAS,MAAM,KAChC,CACF;EACA,IAAI,IAAI,KAAK,OAAO,GAAG,aAAa,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;EAC9D,IAAI,IAAI,KAAK,WAAW,GAAG,YAAY,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;EACjE,IAAI,IAAI,KAAK,QAAQ,SAAS,KAAK,IAAI,GAAG,MAAM,CAAC;EACjD,QAAQ,IAAI,GAAG;CACjB;AACF;;;;;;;ACtDA,SAAgB,WAAW,KAAuB;CAChD,MAAM,EAAE,UAAU;CAClB,eAAe,GAAG;CAClB,cAAc,GAAG;CACjB,cAAc,GAAG;CACjB,cAAc,GAAG;CACjB,YAAY,GAAG;CACf,cAAc,GAAG;CACjB,IAAI,GAAG,WAAW,UAChB,MAAM,YAAY,MAAM,SAAS,YAAY,MAAM,SAAS;AAChE;;;;ACXA,SAAgB,aACd,QAAqB,CAAC,GACtB,MACe;CACf,MAAM,MAAM,gBAAgB,OAAO,IAAI;CACvC,MAAM,MAAM,CAAC;CACb,KAAK,MAAM,OAAO,OAAO,KAAK,iBAAiB,GAC7C,IAAI,OAAO,KAAK,QAAQ,IAAI,IAAI;CAElC,OAAO;AACT;AAG4C,aAAa;AAUzD,SAAgB,cAAc,QAAsC;CAClE,OAAO;EACL,eAAe,OAAO;EACtB,eAAe,OAAO;EACtB,eAAe,OAAO;EACtB,SAAS,OAAO;EAChB,YAAY,OAAO;CACrB;AACF;;;AC7BA,eAAsB,aACpB,eACA,SAAyB,gBACV;CACf,MAAM,WAAW,MAAM,kBAAkB,EAAE,UAAU,KAAK,CAAC;CAC3D,MAAM,QAAQ,aAAa,OAAO,IAAI,KAAK;CAC3C,MAAM,SAAS,cAAc,OAAO,IAAI,MAAM;CAC9C,MAAM,aAAa,kBAAkB,MAAM;CAG3C,MAAM,WAAW,cAAc,MAAM,MAAM;CAK3C,MAAM,aAAa,cAAc,KAAK,MACnC,MAAM,cAAc,UAAU,CAAC,MAAM,KAAA,CACxC;CACA,MAAM,WACJ,WAAW,aAAa,SACpB,aACE,WACA,WACF,WAAW;CAEjB,MAAM,QAAe;EACnB,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,uBAAO,IAAI,IAAI;EACf,aAAa,cAAc,KAAK,MAAM;EACtC,cAAc,CAAC;EACf,SAAS;EACT,WAAW;EACX,aAAa;EACb;EACA,UAAU;EACV,MAAM,CAAC;EACP,MAAM;EACN,YAAY;EACZ,SAAS,IAAI,IAAI,QAAQ;EACzB,aAAa,CAAC,OAAO,IAAI;EACzB,2BAAW,IAAI,IAAI;EACnB,0BAAU,IAAI,IAAI;EAClB,aAAa;CACf;CAEA,MAAM,KAAK,YAAY,UAAU,OAAO,MAAM;CAM9C,IAAI,mBAAmB;CACvB,MAAM,MAAkB;EACtB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR,aAAa,cAAc;EAC3B,eAAe;GACb,IAAI,kBAAkB;GACtB,mBAAmB;GACnB,qBAAqB;IACnB,mBAAmB;IACnB,WAAW,GAAG;GAChB,CAAC;EACH;EACA,kBAAkB,WAAW,GAAG;EAChC,YAAY,QACV,MAAM,aAAa,WACf,IAAI,OAAO,UAAU,GAAG,IACxB,cAAc,GAAG;CACzB;CAEA,qBAAqB,GAAG;CACxB,IAAI,WAAW;CAGf,OAAO,IAAI,SAAe,YAAY;EACpC,MAAM,gBAAgB;GACpB,SAAS,kBAAkB,YAAY,YAAY,KAAK;GACxD,SAAS,UAAU;GACnB,QAAQ;EACV;EAEA,MAAM,QAAQ,YAAY,KAAK,OAAO;EAMtC,SAAS,kBAAkB,WAAW,YAAY,KAAK;EACvD,SAAS,GAAG,UAAU,IAAI,OAAO;CACnC,CAAC;AACH"}
|