@validation-os/dashboard 0.3.0 → 0.5.0

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/labels.ts","../src/register-counts.tsx","../src/columns.ts","../src/register-table.tsx","../src/record-drawer.tsx","../src/register-browser.tsx","../src/use-records.ts","../src/use-counts.ts"],"sourcesContent":["import type { Collection } from \"@validation-os/core\";\n\n/** Plain-language labels — the register is a surface a non-technical\n * teammate meets, so no jargon and no code-y plurals. */\nexport const REGISTER_LABEL: Record<Collection, string> = {\n assumptions: \"Assumptions\",\n experiments: \"Experiments\",\n readings: \"Readings\",\n goals: \"Goals\",\n decisions: \"Decisions\",\n glossary: \"Glossary\",\n people: \"People\",\n};\n\n/** The order tiles read left-to-right, top-to-bottom. */\nexport const REGISTER_ORDER: Collection[] = [\n \"assumptions\",\n \"experiments\",\n \"readings\",\n \"goals\",\n \"decisions\",\n \"glossary\",\n \"people\",\n];\n","import type { Collection } from \"@validation-os/core\";\nimport { REGISTER_LABEL, REGISTER_ORDER } from \"./labels.js\";\nimport type { Counts } from \"./use-counts.js\";\n\nexport interface RegisterCountsProps {\n counts: Counts;\n /** Optional caption under the tiles (e.g. the backend the numbers came from). */\n caption?: string;\n /**\n * Optional link target per register. When supplied, each tile becomes a link\n * (a plain anchor — works with any router), so counts double as navigation\n * into the browse tables.\n */\n hrefFor?: (register: Collection) => string;\n}\n\n/**\n * A glanceable grid of stat tiles — one per register, the register's row count\n * as the hero number. Presentational: the caller reads the counts (server-side,\n * through the adapter) and hands them in. Styled with Tailwind utility classes;\n * the host app provides Tailwind.\n */\nexport function RegisterCounts({ counts, caption, hrefFor }: RegisterCountsProps) {\n const registers = REGISTER_ORDER.filter(\n (r): r is Collection => counts[r] !== undefined,\n );\n return (\n <section aria-label=\"Register counts\">\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {registers.map((register) => (\n <StatTile\n key={register}\n label={REGISTER_LABEL[register]}\n value={counts[register] ?? 0}\n href={hrefFor?.(register)}\n />\n ))}\n </div>\n {caption ? (\n <p className=\"mt-4 text-sm text-neutral-500 dark:text-neutral-400\">\n {caption}\n </p>\n ) : null}\n </section>\n );\n}\n\nfunction StatTile({\n label,\n value,\n href,\n}: {\n label: string;\n value: number;\n href?: string;\n}) {\n const body = (\n <>\n <div className=\"text-sm font-medium text-neutral-500 dark:text-neutral-400\">\n {label}\n </div>\n <div className=\"mt-1 text-3xl font-semibold tabular-nums text-neutral-900 dark:text-neutral-50\">\n {value.toLocaleString()}\n </div>\n </>\n );\n const className =\n \"block rounded-xl border border-neutral-200 bg-white p-5 dark:border-neutral-800 dark:bg-neutral-900\";\n return href ? (\n <a\n href={href}\n className={`${className} transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:hover:border-neutral-700 dark:hover:bg-neutral-800`}\n >\n {body}\n </a>\n ) : (\n <div className={className}>{body}</div>\n );\n}\n","/**\n * Per-register table columns and value formatting — the presentational shape\n * of the browse tables, kept as pure data/functions so it is unit-testable\n * without a DOM. The register is a surface a non-technical teammate meets, so\n * headers are plain language and derived numbers are shown, never hidden.\n */\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\n\nexport interface ColumnDef {\n /** Stable key; also the default field read from the record. */\n key: string;\n /** Plain-language column header. */\n header: string;\n /** Pull the display value from a record (defaults to `record[key]`). */\n accessor?: (record: AnyRecord) => unknown;\n /** Numeric columns right-align for a clean column of figures. */\n align?: \"left\" | \"right\";\n /** Marks a column whose value is computed, never hand-typed (spec story 4). */\n derived?: boolean;\n}\n\n/** Read a nested `derived` number off a record, tolerating a missing tuple. */\nfunction derivedField(field: string): (r: AnyRecord) => unknown {\n return (r) => (r.derived as Record<string, unknown> | undefined)?.[field];\n}\n\n/**\n * The columns each register shows, left-to-right. The first column is always\n * the record's headline (Title, or Name for people); assumptions additionally\n * surface Impact, Confidence and Risk at a glance (spec user story 2).\n */\nconst COLUMNS: Record<Collection, ColumnDef[]> = {\n assumptions: [\n { key: \"Title\", header: \"Assumption\" },\n { key: \"Impact\", header: \"Impact\", align: \"right\" },\n {\n key: \"confidence\",\n header: \"Confidence\",\n align: \"right\",\n derived: true,\n accessor: derivedField(\"confidence\"),\n },\n {\n key: \"risk\",\n header: \"Risk\",\n align: \"right\",\n derived: true,\n accessor: derivedField(\"risk\"),\n },\n { key: \"Status\", header: \"Status\" },\n ],\n experiments: [\n { key: \"Title\", header: \"Experiment\" },\n { key: \"Status\", header: \"Status\" },\n { key: \"Feasibility\", header: \"Feasibility\" },\n ],\n readings: [\n { key: \"Title\", header: \"Reading\" },\n { key: \"Result\", header: \"Result\" },\n { key: \"Rung\", header: \"Rung\" },\n {\n key: \"strength\",\n header: \"Strength\",\n align: \"right\",\n derived: true,\n accessor: derivedField(\"strength\"),\n },\n ],\n goals: [\n { key: \"Title\", header: \"Goal\" },\n { key: \"Status\", header: \"Status\" },\n { key: \"Outcome\", header: \"Outcome\" },\n ],\n decisions: [\n { key: \"Title\", header: \"Decision\" },\n { key: \"Status\", header: \"Status\" },\n ],\n glossary: [\n { key: \"Title\", header: \"Term\" },\n { key: \"Status\", header: \"Status\" },\n ],\n people: [\n { key: \"Name\", header: \"Name\" },\n { key: \"Role\", header: \"Role\" },\n { key: \"Segment\", header: \"Segment\" },\n ],\n};\n\n/** The columns to render for a register. */\nexport function columnsFor(register: Collection): ColumnDef[] {\n return COLUMNS[register];\n}\n\n/** Read a column's raw value from a record (accessor, else `record[key]`). */\nexport function cellValue(column: ColumnDef, record: AnyRecord): unknown {\n return column.accessor ? column.accessor(record) : record[column.key];\n}\n\n/** Format any stored value for display; empty/missing reads as an em dash. */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"—\";\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n if (Array.isArray(value)) {\n return value.length ? value.map(formatScalar).join(\", \") : \"—\";\n }\n return formatScalar(value);\n}\n\nfunction formatScalar(value: unknown): string {\n if (value === null || value === undefined) return \"—\";\n if (typeof value === \"number\") return String(value);\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/** The record's headline for a row/drawer: Title, else Name, else its id. */\nexport function primaryLabel(record: AnyRecord): string {\n const title = record.Title ?? record.Name;\n return typeof title === \"string\" && title.trim() ? title : record.id;\n}\n\n// ── Field labels ────────────────────────────────────────────────────────────\n// The register is a surface a non-technical teammate meets, so field names are\n// shown in plain language, never as raw camelCase keys. This is the single\n// source for both the drawer's field list and its computed-numbers block.\n\n/** Labels for the computed `derived` tuple. Both `derivedImpact` (the\n * derivation module's name) and `impact` (the migrated data's name, pending the\n * OPS-1273 schema ripple) map to one label so the drawer reads cleanly either\n * way. */\nconst DERIVED_LABEL: Record<string, string> = {\n confidence: \"Confidence\",\n risk: \"Risk\",\n derivedImpact: \"Derived Impact\",\n impact: \"Derived Impact\",\n sourceQuality: \"Source quality\",\n strength: \"Strength\",\n};\n\n/** Plain-language names for the camelCase id/relation fields; Title-cased\n * fields (Title, Status, Impact, Owner…) already read cleanly and pass through. */\nconst FIELD_LABEL: Record<string, string> = {\n dependsOnIds: \"Depends on\",\n enablesIds: \"Enables\",\n contradictsIds: \"Contradicts\",\n readingIds: \"Readings\",\n assumptionId: \"Assumption\",\n experimentId: \"Experiment\",\n goalId: \"Goal\",\n basedOnIds: \"Based on\",\n resolvesIds: \"Resolves\",\n barLineAssumptionIds: \"Assumptions tested\",\n closureReason: \"Closure reason\",\n magnitudeBand: \"Magnitude band\",\n moot: \"Moot\",\n};\n\n/** A record field's display label — an override, else a humanised key. */\nexport function fieldLabel(key: string): string {\n const override = FIELD_LABEL[key];\n if (override) return override;\n if (/^[A-Z]/.test(key)) return key; // already Title-cased, reads fine\n const spaced = key.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\n/** A computed (`derived`) field's display label. */\nexport function derivedLabel(key: string): string {\n return DERIVED_LABEL[key] ?? fieldLabel(key);\n}\n","import type { AnyRecord, Collection } from \"@validation-os/core\";\nimport { cellValue, columnsFor, formatValue, primaryLabel } from \"./columns.js\";\n\nexport interface RegisterTableProps {\n register: Collection;\n records: AnyRecord[];\n /** Called with the clicked record's id — opens the read-only drawer. */\n onRowClick?: (id: string) => void;\n /** The id of the currently-open record, highlighted in the list. */\n selectedId?: string | null;\n}\n\n/**\n * A list table for one register — a row per record, the register's key fields\n * as columns (assumptions show Impact, Confidence and Risk). Presentational:\n * the caller supplies the rows. Clicking a row opens the read-only drawer.\n * Styled with Tailwind utilities the host app provides.\n */\nexport function RegisterTable({\n register,\n records,\n onRowClick,\n selectedId,\n}: RegisterTableProps) {\n const columns = columnsFor(register);\n\n if (records.length === 0) {\n return (\n <p className=\"rounded-xl border border-dashed border-neutral-300 p-8 text-center text-sm text-neutral-500 dark:border-neutral-700 dark:text-neutral-400\">\n No records yet.\n </p>\n );\n }\n\n return (\n <div className=\"overflow-x-auto rounded-xl border border-neutral-200 dark:border-neutral-800\">\n <table className=\"w-full border-collapse text-left text-sm\">\n <thead>\n <tr className=\"border-b border-neutral-200 bg-neutral-50 dark:border-neutral-800 dark:bg-neutral-900\">\n {columns.map((c) => (\n <th\n key={c.key}\n scope=\"col\"\n className={`px-4 py-2.5 font-medium text-neutral-500 dark:text-neutral-400 ${\n c.align === \"right\" ? \"text-right tabular-nums\" : \"text-left\"\n }`}\n >\n {c.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {records.map((record) => {\n const isSelected = record.id === selectedId;\n return (\n <tr\n key={record.id}\n onClick={() => onRowClick?.(record.id)}\n onKeyDown={\n onRowClick\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRowClick(record.id);\n }\n }\n : undefined\n }\n tabIndex={onRowClick ? 0 : undefined}\n aria-selected={isSelected}\n className={`border-b border-neutral-100 last:border-0 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500 dark:border-neutral-900 ${\n onRowClick ? \"cursor-pointer\" : \"\"\n } ${\n isSelected\n ? \"bg-blue-50 dark:bg-blue-950/40\"\n : \"hover:bg-neutral-50 dark:hover:bg-neutral-900/60\"\n }`}\n >\n {columns.map((c, i) => {\n const raw = cellValue(c, record);\n // The headline cell falls back to the record's id so a row is\n // never blank; other cells show an em dash when empty.\n const text =\n i === 0 && (raw === null || raw === undefined || raw === \"\")\n ? primaryLabel(record)\n : formatValue(raw);\n return (\n <td\n key={c.key}\n className={`px-4 py-2.5 ${\n c.align === \"right\"\n ? \"text-right tabular-nums text-neutral-700 dark:text-neutral-300\"\n : \"text-left\"\n } ${\n i === 0\n ? \"font-medium text-neutral-900 dark:text-neutral-100\"\n : \"text-neutral-600 dark:text-neutral-400\"\n }`}\n >\n {text}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\nimport { REGISTER_LABEL } from \"./labels.js\";\nimport { derivedLabel, fieldLabel, formatValue, primaryLabel } from \"./columns.js\";\n\nexport interface RecordDrawerProps {\n register: Collection;\n /** The open record, or null while loading / when nothing is selected. */\n record: AnyRecord | null;\n /** True while the record is being fetched. */\n loading?: boolean;\n error?: string | null;\n /** Whether the drawer is open (a row is selected). */\n open: boolean;\n onClose: () => void;\n}\n\n/** Provider-owned/meta fields are shown in the footer, not as content rows. */\nconst META_FIELDS = new Set([\"id\", \"version\", \"createdAt\", \"updatedAt\", \"derived\"]);\n\n/**\n * A read-only drawer for one record. Any derived numbers lead as the hero,\n * explicitly marked computed — not editable (spec user story 4), so a reader\n * trusts they follow the formulas; the record's own fields follow. This slice\n * is read-only; editing lands in a later slice.\n */\nexport function RecordDrawer({\n register,\n record,\n loading,\n error,\n open,\n onClose,\n}: RecordDrawerProps) {\n const closeButtonRef = useRef<HTMLButtonElement>(null);\n\n // Escape closes the drawer; focus lands inside it when it opens so keyboard\n // users aren't left behind an aria-modal dialog.\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", onKey);\n closeButtonRef.current?.focus();\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n if (!open) return null;\n\n const derived =\n record && record.derived && typeof record.derived === \"object\"\n ? (record.derived as Record<string, unknown>)\n : null;\n\n const fields = record\n ? Object.keys(record).filter((k) => !META_FIELDS.has(k))\n : [];\n\n return (\n <div className=\"fixed inset-0 z-50 flex justify-end\">\n {/* Overlay — click to dismiss. */}\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className=\"absolute inset-0 bg-neutral-950/30 backdrop-blur-sm\"\n />\n <aside\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`${REGISTER_LABEL[register]} record`}\n className=\"relative flex h-full w-full max-w-md flex-col overflow-y-auto border-l border-neutral-200 bg-white shadow-xl dark:border-neutral-800 dark:bg-neutral-950\"\n >\n <header className=\"flex items-start justify-between gap-4 border-b border-neutral-200 p-5 dark:border-neutral-800\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-neutral-400\">\n {REGISTER_LABEL[register]}\n </p>\n <h2 className=\"mt-1 text-lg font-semibold text-neutral-900 dark:text-neutral-50\">\n {record ? primaryLabel(record) : loading ? \"Loading…\" : \"—\"}\n </h2>\n </div>\n <button\n ref={closeButtonRef}\n type=\"button\"\n onClick={onClose}\n className=\"rounded-md px-2 py-1 text-sm text-neutral-500 hover:bg-neutral-100 dark:hover:bg-neutral-900\"\n >\n Close\n </button>\n </header>\n\n <div className=\"flex-1 p-5\">\n {loading ? (\n <p className=\"text-sm text-neutral-500\">Loading record…</p>\n ) : error ? (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n ) : !record ? (\n <p className=\"text-sm text-neutral-500\">No record.</p>\n ) : (\n <>\n {derived ? (\n <section className=\"mb-6\">\n <h3 className=\"mb-2 text-xs font-medium uppercase tracking-wide text-neutral-400\">\n Computed · not editable\n </h3>\n <dl className=\"grid grid-cols-3 gap-3\">\n {Object.entries(derived).map(([key, value]) => (\n <div\n key={key}\n className=\"rounded-lg border border-neutral-200 bg-neutral-50 p-3 dark:border-neutral-800 dark:bg-neutral-900\"\n >\n <dt className=\"text-xs text-neutral-500 dark:text-neutral-400\">\n {derivedLabel(key)}\n </dt>\n <dd className=\"mt-1 text-xl font-semibold tabular-nums text-neutral-900 dark:text-neutral-50\">\n {formatValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ) : null}\n\n <dl className=\"divide-y divide-neutral-100 dark:divide-neutral-900\">\n {fields.map((key) => (\n <div key={key} className=\"grid grid-cols-3 gap-3 py-2.5\">\n <dt className=\"text-sm text-neutral-500 dark:text-neutral-400\">\n {fieldLabel(key)}\n </dt>\n <dd className=\"col-span-2 text-sm text-neutral-800 dark:text-neutral-200\">\n {formatValue(record[key])}\n </dd>\n </div>\n ))}\n </dl>\n </>\n )}\n </div>\n\n {record ? (\n <footer className=\"border-t border-neutral-200 p-5 text-xs text-neutral-400 dark:border-neutral-800\">\n {record.id} · version {String(record.version)} · updated{\" \"}\n {formatValue(record.updatedAt)}\n </footer>\n ) : null}\n </aside>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\nimport { REGISTER_LABEL } from \"./labels.js\";\nimport { RegisterTable } from \"./register-table.js\";\nimport { RecordDrawer } from \"./record-drawer.js\";\nimport { useList, useRecord } from \"./use-records.js\";\n\nexport interface RegisterBrowserProps {\n register: Collection;\n /** API base path (default `/api`). */\n basePath?: string;\n}\n\n/**\n * The browse-and-open surface for one register: a list table that opens a\n * read-only drawer on row click. Reads over HTTP through the Clerk-gated API\n * read routes (list + get), so the browser never touches Firestore directly.\n * The thin host app renders this with a `register` — that's the whole page.\n */\nexport function RegisterBrowser({ register, basePath }: RegisterBrowserProps) {\n const { records, loading, error } = useList(register, basePath);\n const [openId, setOpenId] = useState<string | null>(null);\n const {\n record,\n loading: recordLoading,\n error: recordError,\n } = useRecord(register, openId, basePath);\n\n return (\n <div>\n {loading && !records ? (\n <p className=\"text-sm text-neutral-500\">\n Loading {REGISTER_LABEL[register].toLowerCase()}…\n </p>\n ) : error ? (\n <p className=\"text-sm text-red-600 dark:text-red-400\">{error}</p>\n ) : (\n <RegisterTable\n register={register}\n records={records ?? []}\n onRowClick={setOpenId}\n selectedId={openId}\n />\n )}\n\n <RecordDrawer\n register={register}\n record={record}\n loading={recordLoading}\n error={recordError}\n open={openId !== null}\n onClose={() => setOpenId(null)}\n />\n </div>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\n\n/**\n * Client hooks that read the register over HTTP through the API read routes\n * (`GET {basePath}/{register}` and `GET {basePath}/{register}/{id}`). The API\n * reaches Firestore server-side through the adapter, so no backend credentials\n * ever reach the browser — the browser only ever speaks to the Clerk-gated API.\n */\n\ninterface AsyncState<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n}\n\n/** Both read routes wrap their payload in a `{ data }` envelope. */\nfunction pickData<T>(body: unknown): T {\n return (body as { data: T }).data;\n}\n\n/**\n * Fetch one JSON resource, tracking loading/error. A null `url` means \"idle\"\n * (nothing to load yet) — the drawer's get hook uses this until a row is\n * clicked. Returns a `refresh` that re-runs the fetch. This is the shared\n * engine behind both `useList` and `useRecord`.\n */\nfunction useJsonResource<T>(url: string | null): AsyncState<T> & {\n refresh: () => void;\n} {\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n loading: url !== null,\n error: null,\n });\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (url === null) {\n setState({ data: null, loading: false, error: null });\n return;\n }\n let live = true;\n setState((s) => ({ ...s, loading: true }));\n fetch(url)\n .then(async (res) => {\n if (!res.ok) throw new Error(`Request to ${url} failed (${res.status})`);\n return pickData<T>(await res.json());\n })\n .then((data) => live && setState({ data, loading: false, error: null }))\n .catch(\n (e: unknown) =>\n live &&\n setState({\n data: null,\n loading: false,\n error: e instanceof Error ? e.message : \"Failed to load\",\n }),\n );\n return () => {\n live = false;\n };\n }, [url, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n return { ...state, refresh };\n}\n\nexport interface UseListResult {\n records: AnyRecord[] | null;\n loading: boolean;\n error: string | null;\n refresh: () => void;\n}\n\n/** Fetch every row of a register. */\nexport function useList(register: Collection, basePath = \"/api\"): UseListResult {\n const { data, loading, error, refresh } = useJsonResource<AnyRecord[]>(\n `${basePath}/${register}`,\n );\n return { records: data, loading, error, refresh };\n}\n\nexport interface UseRecordResult {\n record: AnyRecord | null;\n loading: boolean;\n error: string | null;\n}\n\n/**\n * Fetch one record by id. `id` may be null (nothing open) — the hook stays\n * idle until an id is supplied, so it drives a drawer that opens on row click.\n */\nexport function useRecord(\n register: Collection,\n id: string | null,\n basePath = \"/api\",\n): UseRecordResult {\n const url = id\n ? `${basePath}/${register}/${encodeURIComponent(id)}`\n : null;\n const { data, loading, error } = useJsonResource<AnyRecord>(url);\n return { record: data, loading, error };\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\n\nexport type Counts = Partial<Record<Collection, number>>;\n\nexport interface UseCountsResult {\n counts: Counts | null;\n loading: boolean;\n error: string | null;\n refresh: () => void;\n}\n\n/**\n * Client hook: fetch per-register counts from the API (`GET {basePath}/counts`).\n * The API reads Firestore server-side through the adapter; this only speaks\n * HTTP, so no backend credentials ever reach the browser.\n */\nexport function useCounts(basePath = \"/api\"): UseCountsResult {\n const [counts, setCounts] = useState<Counts | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n let live = true;\n setLoading(true);\n fetch(`${basePath}/counts`)\n .then(async (res) => {\n if (!res.ok) throw new Error(`Counts request failed (${res.status})`);\n return (await res.json()) as { counts: Counts };\n })\n .then((body) => {\n if (!live) return;\n setCounts(body.counts);\n setError(null);\n })\n .catch((e: unknown) => {\n if (!live) return;\n setError(e instanceof Error ? e.message : \"Failed to load counts\");\n })\n .finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [basePath, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n return { counts, loading, error, refresh };\n}\n"],"mappings":"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","names":["jsx","jsxs","Fragment","jsx","jsxs","useState","useEffect","jsx","jsxs","useState","useCallback","useEffect","useState"]}
1
+ {"version":3,"sources":["../src/dashboard-app.tsx","../src/labels.ts","../src/register-browser.tsx","../src/drawer-shell.tsx","../src/columns.ts","../src/primitives.ts","../src/primitives-view.tsx","../src/register-table.tsx","../src/record-drawer.tsx","../src/edit.ts","../src/use-records.ts","../src/understanding.ts","../src/understanding-panel.tsx","../src/record-form.tsx","../src/form-fields.ts","../src/field-styles.ts","../src/use-mutations.ts","../src/relation-editor.tsx","../src/link-choices.ts","../src/register-nav.tsx","../src/use-counts.ts","../src/register-counts.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\nimport { REGISTER_ORDER, REGISTER_SUBTITLE } from \"./labels.js\";\nimport { RegisterBrowser } from \"./register-browser.js\";\nimport { RegisterNav } from \"./register-nav.js\";\nimport { useCounts } from \"./use-counts.js\";\n\n/**\n * Everything the instance passes — config only, never secrets. The API base\n * path points at where the Clerk-gated `@validation-os/api` routes are mounted;\n * the backend label (from the connector config) shows in the topbar; branding\n * and the signed-in user are optional cosmetics. Auth is the instance's Clerk\n * provider that this renders within — no credential reaches the package.\n */\nexport interface DashboardConfig {\n /** Where the API is mounted (default `/api`). */\n basePath?: string;\n /** Topbar backend indicator, e.g. \"Firestore · doshi-crm\". */\n backendLabel?: string;\n /** Optional product branding for the sidebar. */\n branding?: {\n /** Product name shown next to the mark (default \"Validation-OS\"). */\n name?: string;\n /** One or two letters for the square mark (default \"V\"). */\n initials?: string;\n /** A logo image for the square mark; overrides `initials` when set. */\n logoUrl?: string;\n };\n /** Optional agent label shown in the topbar, e.g. \"Claude Code\". */\n agentLabel?: string;\n /** The signed-in user, for the topbar avatar + name. */\n user?: { name?: string; caption?: string };\n /** Restrict/reorder the registers shown; defaults to all, in order. */\n registers?: Collection[];\n}\n\nexport interface ValidationOSDashboardProps {\n config?: DashboardConfig;\n}\n\n/** Two letters from a name for the avatar, e.g. \"Benji Fisher\" → \"BF\". */\nfunction initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/);\n const first = parts[0]?.[0] ?? \"\";\n const last = parts.length > 1 ? (parts[parts.length - 1]?.[0] ?? \"\") : \"\";\n return (first + last).toUpperCase() || \"?\";\n}\n\n/** Read the active register from the URL hash, if it names one. */\nfunction registerFromHash(available: Collection[]): Collection | null {\n if (typeof window === \"undefined\") return null;\n const hash = window.location.hash.replace(/^#\\/?/, \"\");\n return (available as string[]).includes(hash) ? (hash as Collection) : null;\n}\n\n/**\n * The entire styled dashboard as one mountable app (spec OPS-1280): the frame —\n * sidebar composing register nav + live counts, topbar with the backend\n * indicator and user — and the register views (browse → drawer → understanding)\n * it composes from the package's own bricks. Navigation is owned here, not the\n * host router: the active register lives in client state (synced to the URL\n * hash), so the instance mounts this at one route and wires no routing. Styled\n * by the package's own token sheet — the instance imports `styles.css` once and\n * builds no UI.\n */\nexport function ValidationOSDashboard({ config = {} }: ValidationOSDashboardProps) {\n const {\n basePath = \"/api\",\n backendLabel,\n branding,\n agentLabel,\n user,\n registers = REGISTER_ORDER,\n } = config;\n\n const [active, setActive] = useState<Collection>(\n () => registerFromHash(registers) ?? registers[0] ?? \"assumptions\",\n );\n const { counts } = useCounts(basePath);\n\n // Keep the active register and the URL hash in step, so a deep link opens the\n // right register and the browser back button moves between them.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const onHash = () => {\n const next = registerFromHash(registers);\n if (next) setActive(next);\n };\n window.addEventListener(\"hashchange\", onHash);\n return () => window.removeEventListener(\"hashchange\", onHash);\n }, [registers]);\n\n const select = useCallback((register: Collection) => {\n setActive(register);\n if (typeof window !== \"undefined\") {\n window.location.hash = register;\n }\n }, []);\n\n const toggleTheme = useCallback(() => {\n const root = document.documentElement;\n const current =\n root.getAttribute(\"data-theme\") ??\n (window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\");\n root.setAttribute(\"data-theme\", current === \"dark\" ? \"light\" : \"dark\");\n }, []);\n\n const brandName = branding?.name ?? \"Validation-OS\";\n const brandMark = branding?.initials ?? \"V\";\n\n return (\n <div className=\"vos-app\">\n <div className=\"vos-brand\">\n <span className=\"vos-brand-dot\">\n {branding?.logoUrl ? (\n <img src={branding.logoUrl} alt=\"\" />\n ) : (\n brandMark\n )}\n </span>{\" \"}\n {brandName}\n </div>\n\n <div className=\"vos-topbar\">\n {backendLabel ? (\n <div className=\"vos-backend\">\n <span className=\"vos-live-dot\" /> Backend: <b>{backendLabel}</b>\n </div>\n ) : null}\n {agentLabel ? (\n <span className=\"vos-hint\">\n Agent: <b style={{ color: \"var(--vos-text)\" }}>{agentLabel}</b>\n </span>\n ) : null}\n <div className=\"vos-spacer\" />\n <button type=\"button\" className=\"vos-iconbtn\" onClick={toggleTheme}>\n ◐ Theme\n </button>\n {user?.name ? (\n <div className=\"vos-user\">\n <span className=\"vos-avatar\">{initialsOf(user.name)}</span>\n <div>\n <span className=\"vos-user-name\">{user.name}</span>\n {user.caption ? <small>{user.caption}</small> : null}\n </div>\n </div>\n ) : null}\n </div>\n\n <RegisterNav\n active={active}\n onSelect={select}\n counts={counts}\n registers={registers}\n />\n\n <main className=\"vos-main\">\n <RegisterBrowser\n key={active}\n register={active}\n basePath={basePath}\n subtitle={REGISTER_SUBTITLE[active]}\n />\n </main>\n </div>\n );\n}\n","import type { Collection } from \"@validation-os/core\";\n\n/** Plain-language labels — the register is a surface a non-technical\n * teammate meets, so no jargon and no code-y plurals. */\nexport const REGISTER_LABEL: Record<Collection, string> = {\n assumptions: \"Assumptions\",\n experiments: \"Experiments\",\n readings: \"Readings\",\n goals: \"Goals\",\n decisions: \"Decisions\",\n glossary: \"Glossary\",\n people: \"People\",\n};\n\n/** Singular labels — for \"New {thing}\" affordances (never a naive de-pluralise\n * that would read \"New Peopl\" / \"New Glossary\"). */\nexport const REGISTER_SINGULAR: Record<Collection, string> = {\n assumptions: \"Assumption\",\n experiments: \"Experiment\",\n readings: \"Reading\",\n goals: \"Goal\",\n decisions: \"Decision\",\n glossary: \"Glossary term\",\n people: \"Person\",\n};\n\n/** The order tiles read left-to-right, top-to-bottom. */\nexport const REGISTER_ORDER: Collection[] = [\n \"assumptions\",\n \"experiments\",\n \"readings\",\n \"goals\",\n \"decisions\",\n \"glossary\",\n \"people\",\n];\n\n/** A one-line description shown under each register's title (spec story 9). */\nexport const REGISTER_SUBTITLE: Record<Collection, string> = {\n assumptions:\n \"Falsifiable beliefs the plan rests on. Risk = Impact × (1 − max(0, Confidence)/100).\",\n experiments: \"The tests that move Confidence in the beliefs.\",\n readings: \"The evidence logged against experiments and beliefs.\",\n goals: \"The outcomes the plan is steering toward.\",\n decisions: \"The choices made, and what they rest on.\",\n glossary: \"The shared vocabulary for this venture.\",\n people: \"The people the plan touches.\",\n};\n\n/** A single-glyph icon per register for the sidebar nav (matches the prototype\n * feel; a glyph, not an icon font, so nothing external is pulled in). */\nexport const REGISTER_ICON: Record<Collection, string> = {\n assumptions: \"◎\",\n experiments: \"⚗\",\n readings: \"▤\",\n goals: \"◇\",\n decisions: \"§\",\n glossary: \"A\",\n people: \"☺\",\n};\n\n/** The sidebar groups the registers into the register set and reference data. */\nexport const REGISTER_GROUPS: { label: string; registers: Collection[] }[] = [\n {\n label: \"Registers\",\n registers: [\"assumptions\", \"experiments\", \"readings\", \"goals\", \"decisions\", \"glossary\"],\n },\n { label: \"Reference\", registers: [\"people\"] },\n];\n","import { useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\nimport { DrawerShell } from \"./drawer-shell.js\";\nimport { REGISTER_LABEL, REGISTER_SINGULAR } from \"./labels.js\";\nimport { RegisterTable } from \"./register-table.js\";\nimport { RecordDrawer } from \"./record-drawer.js\";\nimport { RecordForm } from \"./record-form.js\";\nimport { RelationEditor } from \"./relation-editor.js\";\nimport { useList, useRecord } from \"./use-records.js\";\n\nexport interface RegisterBrowserProps {\n register: Collection;\n /** API base path (default `/api`). */\n basePath?: string;\n /** A one-line description under the register title (spec story 7/9). */\n subtitle?: string;\n}\n\n/**\n * The browse-create-edit surface for one register: a list table that opens a\n * record drawer on row click, a \"New\" button that opens the create form, and a\n * relation editor in the drawer for wiring links. All reads and writes go over\n * HTTP through the Clerk-gated API (which recomputes derived fields on write),\n * so the browser never touches Firestore directly. After an edit saves, both\n * the drawer's record and the list re-fetch so recomputed derived numbers show\n * everywhere. The thin host app renders this with a `register` — that's the\n * whole page.\n */\nexport function RegisterBrowser({\n register,\n basePath,\n subtitle,\n}: RegisterBrowserProps) {\n const { records, loading, error, refresh: refreshList } = useList(\n register,\n basePath,\n );\n const [openId, setOpenId] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const {\n record,\n loading: recordLoading,\n error: recordError,\n refresh: refreshRecord,\n } = useRecord(register, openId, basePath);\n\n return (\n <div>\n <div className=\"vos-head\">\n <div>\n <h1>{REGISTER_LABEL[register]}</h1>\n {subtitle ? <p>{subtitle}</p> : null}\n </div>\n <div className=\"vos-spacer\" />\n <button\n type=\"button\"\n onClick={() => refreshList()}\n className=\"vos-btn vos-btn-ghost\"\n >\n ↻ Refresh\n </button>\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\n className=\"vos-btn\"\n >\n + New {REGISTER_SINGULAR[register]}\n </button>\n </div>\n\n {loading && !records ? (\n <p className=\"vos-muted\">\n Loading {REGISTER_LABEL[register].toLowerCase()}…\n </p>\n ) : error ? (\n <p className=\"vos-error\">{error}</p>\n ) : (\n <RegisterTable\n register={register}\n records={records ?? []}\n onRowClick={setOpenId}\n selectedId={openId}\n />\n )}\n\n <RecordDrawer\n register={register}\n record={record}\n loading={recordLoading}\n error={recordError}\n open={openId !== null}\n onClose={() => setOpenId(null)}\n basePath={basePath}\n onChanged={() => {\n refreshRecord();\n refreshList();\n }}\n >\n {openId ? (\n <RelationEditor\n register={register}\n recordId={openId}\n basePath={basePath}\n onLinked={() => {\n refreshRecord();\n refreshList();\n }}\n />\n ) : null}\n </RecordDrawer>\n\n <DrawerShell\n open={creating}\n onClose={() => setCreating(false)}\n ariaLabel={`New ${REGISTER_SINGULAR[register]} record`}\n >\n <header className=\"vos-drawer-header\">\n <div>\n <p className=\"vos-drawer-eyebrow\">New</p>\n <h2 className=\"vos-drawer-title\">{REGISTER_SINGULAR[register]}</h2>\n </div>\n </header>\n <RecordForm\n register={register}\n basePath={basePath}\n onCreated={(id) => {\n setCreating(false);\n refreshList();\n setOpenId(id);\n }}\n onCancel={() => setCreating(false)}\n />\n </DrawerShell>\n </div>\n );\n}\n","import { useEffect, useRef, type ReactNode } from \"react\";\n\nexport interface DrawerShellProps {\n /** Whether the drawer is mounted/visible. */\n open: boolean;\n onClose: () => void;\n /** Accessible name for the dialog. */\n ariaLabel: string;\n children: ReactNode;\n}\n\n/**\n * The right-hand slide-over chrome shared by the record drawer and the create\n * drawer: a click-to-dismiss scrim, an `aria-modal` panel, Escape-to-close, and\n * focus moved into the panel on open so keyboard users aren't stranded behind\n * the modal. Everything inside is the caller's content. Styled with the\n * package's own token sheet — no host Tailwind.\n */\nexport function DrawerShell({\n open,\n onClose,\n ariaLabel,\n children,\n}: DrawerShellProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", onKey);\n panelRef.current?.focus();\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n if (!open) return null;\n\n return (\n <>\n {/* Scrim — click to dismiss. */}\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className=\"vos-scrim\"\n />\n <aside\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n tabIndex={-1}\n className=\"vos-drawer\"\n >\n {children}\n </aside>\n </>\n );\n}\n","/**\n * Per-register table columns and value formatting — the presentational shape\n * of the browse tables, kept as pure data/functions so it is unit-testable\n * without a DOM. The register is a surface a non-technical teammate meets, so\n * headers are plain language and derived numbers are shown, never hidden.\n */\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\n\n/**\n * How a cell renders. `text` is plain formatted text; `status` is a colored\n * pill; `risk` is a threshold-toned bar + number; `confidence` is a signed\n * number (with a sparkline when a trajectory is available). Keeping this on the\n * column — not branching by key in the table — is what makes the visual\n * treatment declarative and testable at this seam (spec story 13).\n */\nexport type CellKind = \"text\" | \"status\" | \"risk\" | \"confidence\";\n\nexport interface ColumnDef {\n /** Stable key; also the default field read from the record. */\n key: string;\n /** Plain-language column header. */\n header: string;\n /** Pull the display value from a record (defaults to `record[key]`). */\n accessor?: (record: AnyRecord) => unknown;\n /** Numeric columns right-align for a clean column of figures. */\n align?: \"left\" | \"right\";\n /** Marks a column whose value is computed, never hand-typed (spec story 4). */\n derived?: boolean;\n /** How the cell renders; defaults to `text`. */\n kind?: CellKind;\n}\n\n/** Read a nested `derived` number off a record, tolerating a missing tuple. */\nfunction derivedField(field: string): (r: AnyRecord) => unknown {\n return (r) => (r.derived as Record<string, unknown> | undefined)?.[field];\n}\n\n/**\n * The columns each register shows, left-to-right. The first column is always\n * the record's headline (Title, or Name for people); assumptions additionally\n * surface Impact, Confidence and Risk at a glance (spec user story 2).\n */\nconst COLUMNS: Record<Collection, ColumnDef[]> = {\n assumptions: [\n { key: \"Title\", header: \"Belief\" },\n {\n key: \"Status\",\n header: \"Status\",\n kind: \"status\",\n },\n { key: \"Impact\", header: \"Impact\", align: \"right\" },\n {\n key: \"confidence\",\n header: \"Confidence\",\n align: \"right\",\n derived: true,\n kind: \"confidence\",\n accessor: derivedField(\"confidence\"),\n },\n {\n key: \"risk\",\n header: \"Risk\",\n align: \"right\",\n derived: true,\n kind: \"risk\",\n accessor: derivedField(\"risk\"),\n },\n ],\n experiments: [\n { key: \"Title\", header: \"Experiment\" },\n { key: \"Status\", header: \"Status\", kind: \"status\" },\n { key: \"Feasibility\", header: \"Feasibility\" },\n ],\n readings: [\n { key: \"Title\", header: \"Reading\" },\n { key: \"Result\", header: \"Result\" },\n { key: \"Rung\", header: \"Rung\" },\n {\n key: \"strength\",\n header: \"Strength\",\n align: \"right\",\n derived: true,\n accessor: derivedField(\"strength\"),\n },\n ],\n goals: [\n { key: \"Title\", header: \"Goal\" },\n { key: \"Status\", header: \"Status\", kind: \"status\" },\n { key: \"Outcome\", header: \"Outcome\" },\n ],\n decisions: [\n { key: \"Title\", header: \"Decision\" },\n { key: \"Status\", header: \"Status\", kind: \"status\" },\n ],\n glossary: [\n { key: \"Title\", header: \"Term\" },\n { key: \"Status\", header: \"Status\", kind: \"status\" },\n ],\n people: [\n { key: \"Name\", header: \"Name\" },\n { key: \"Role\", header: \"Role\" },\n { key: \"Segment\", header: \"Segment\" },\n ],\n};\n\n/** The columns to render for a register. */\nexport function columnsFor(register: Collection): ColumnDef[] {\n return COLUMNS[register];\n}\n\n/** Read a column's raw value from a record (accessor, else `record[key]`). */\nexport function cellValue(column: ColumnDef, record: AnyRecord): unknown {\n return column.accessor ? column.accessor(record) : record[column.key];\n}\n\n/** Format any stored value for display; empty/missing reads as an em dash. */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined || value === \"\") return \"—\";\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n if (Array.isArray(value)) {\n return value.length ? value.map(formatScalar).join(\", \") : \"—\";\n }\n return formatScalar(value);\n}\n\nfunction formatScalar(value: unknown): string {\n if (value === null || value === undefined) return \"—\";\n if (typeof value === \"number\") return String(value);\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n}\n\n/** The record's headline for a row/drawer: Title, else Name, else its id. */\nexport function primaryLabel(record: AnyRecord): string {\n const title = record.Title ?? record.Name;\n return typeof title === \"string\" && title.trim() ? title : record.id;\n}\n\n// ── Field labels ────────────────────────────────────────────────────────────\n// The register is a surface a non-technical teammate meets, so field names are\n// shown in plain language, never as raw camelCase keys. This is the single\n// source for both the drawer's field list and its computed-numbers block.\n\n/** Labels for the computed `derived` tuple. Both `derivedImpact` (the\n * derivation module's name) and `impact` (the migrated data's name, pending the\n * OPS-1273 schema ripple) map to one label so the drawer reads cleanly either\n * way. */\nconst DERIVED_LABEL: Record<string, string> = {\n confidence: \"Confidence\",\n risk: \"Risk\",\n derivedImpact: \"Derived Impact\",\n impact: \"Derived Impact\",\n sourceQuality: \"Source quality\",\n strength: \"Strength\",\n};\n\n/** Plain-language names for the camelCase id/relation fields; Title-cased\n * fields (Title, Status, Impact, Owner…) already read cleanly and pass through. */\nconst FIELD_LABEL: Record<string, string> = {\n dependsOnIds: \"Depends on\",\n enablesIds: \"Enables\",\n contradictsIds: \"Contradicts\",\n readingIds: \"Readings\",\n assumptionId: \"Assumption\",\n experimentId: \"Experiment\",\n goalId: \"Goal\",\n basedOnIds: \"Based on\",\n resolvesIds: \"Resolves\",\n barLineAssumptionIds: \"Assumptions tested\",\n closureReason: \"Closure reason\",\n magnitudeBand: \"Magnitude band\",\n moot: \"Moot\",\n};\n\n/** A record field's display label — an override, else a humanised key. */\nexport function fieldLabel(key: string): string {\n const override = FIELD_LABEL[key];\n if (override) return override;\n if (/^[A-Z]/.test(key)) return key; // already Title-cased, reads fine\n const spaced = key.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\n/** A computed (`derived`) field's display label. */\nexport function derivedLabel(key: string): string {\n return DERIVED_LABEL[key] ?? fieldLabel(key);\n}\n","/**\n * Pure presentation logic for the dashboard's visual primitives — status→tone,\n * risk→fraction/level, the sparkline path, and count/number formatting. Kept\n * free of React and the DOM so the mapping that drives every pill, bar and\n * sparkline is unit-tested at this seam (spec story 13), and the components stay\n * thin wrappers over it.\n */\n\n/** A pill/fill tone — maps onto the `--vos-good/warn/crit/accent` tokens. */\nexport type Tone = \"good\" | \"warn\" | \"crit\" | \"accent\" | \"neutral\";\n\n/** Statuses that read as settled/positive, whatever the register. */\nconst GOOD_STATUS = new Set([\n \"live\",\n \"concluded\",\n \"closed\",\n \"done\",\n \"resolved\",\n \"accepted\",\n \"adopted\",\n \"shipped\",\n]);\n/** Statuses that read as in-flight / not yet settled. */\nconst WARN_STATUS = new Set([\n \"testing\",\n \"running\",\n \"in progress\",\n \"in-progress\",\n \"draft\",\n]);\n/** Statuses that read as a problem. */\nconst CRIT_STATUS = new Set([\n \"invalidated\",\n \"rejected\",\n \"blocked\",\n \"failed\",\n \"at risk\",\n]);\n\n/**\n * A record's Status → a pill tone. Live/concluded read good, testing/running\n * read warn, invalidated/rejected read crit; everything else (Proposed, and any\n * status we don't recognise) stays neutral rather than guessing a colour. Case-\n * and whitespace-insensitive.\n */\nexport function statusTone(status: string | null | undefined): Tone {\n if (!status) return \"neutral\";\n const s = status.trim().toLowerCase();\n if (GOOD_STATUS.has(s)) return \"good\";\n if (WARN_STATUS.has(s)) return \"warn\";\n if (CRIT_STATUS.has(s)) return \"crit\";\n return \"neutral\";\n}\n\n/** Risk thresholds — a belief is critical at ≥60, watch at ≥30 (prototype). */\nexport const RISK_CRIT = 60;\nexport const RISK_WARN = 30;\n\n/** Risk (0–100) → a tone for the bar fill and the number. */\nexport function riskLevel(risk: number): Tone {\n if (risk >= RISK_CRIT) return \"crit\";\n if (risk >= RISK_WARN) return \"warn\";\n return \"good\";\n}\n\n/** Risk (0–100) → the bar's fill fraction (0–1), clamped. */\nexport function riskFraction(risk: number): number {\n if (!Number.isFinite(risk)) return 0;\n return Math.max(0, Math.min(100, risk)) / 100;\n}\n\n/** Confidence (signed) → the tone for its number: negative reads crit. */\nexport function confidenceTone(confidence: number): Tone {\n return confidence < 0 ? \"crit\" : \"good\";\n}\n\n/**\n * The tone for a derived-hero number. Confidence reads crit when negative; Risk\n * reads by threshold; Derived Impact, Strength and anything else read neutral.\n * Pure, so the drawer's hero doesn't hand-roll this branching.\n */\nexport function derivedTone(field: string, value: number): Tone {\n if (field === \"confidence\") return confidenceTone(value);\n if (field === \"risk\") return riskLevel(value);\n return \"neutral\";\n}\n\n/**\n * Tone → the text-colour class for a derived-hero number. Only warn/crit are\n * tinted; a good or neutral number stays the default text colour (the hero\n * doesn't paint every number green the way the in-row cells do).\n */\nexport function heroToneClass(tone: Tone): string {\n if (tone === \"crit\") return \"vos-text-crit\";\n if (tone === \"warn\") return \"vos-text-warn\";\n return \"\";\n}\n\n/** A signed number rendered with an explicit sign: `+6`, `-3`, `0`. */\nexport function formatSigned(n: number): string {\n const r = Math.round(n);\n return r > 0 ? `+${r}` : String(r);\n}\n\n/** A count for the nav/tiles, thousands-separated. */\nexport function formatCount(n: number): string {\n return n.toLocaleString();\n}\n\n/**\n * An SVG polyline `d` for a sparkline over `values`, fit to a `width`×`height`\n * box with a 2px inset. The vertical domain defaults to the data's own range\n * (with 0 always included, so a signed series keeps its baseline meaningful);\n * pass `min`/`max` to pin it — e.g. −100…100 for Confidence. Returns \"\" for\n * fewer than two points (nothing to draw).\n */\nexport function sparklinePath(\n values: number[],\n width: number,\n height: number,\n min?: number,\n max?: number,\n): string {\n if (values.length < 2) return \"\";\n const lo = min ?? Math.min(...values, 0);\n const hi = max ?? Math.max(...values, 0);\n const span = hi - lo || 1;\n const inset = 2;\n return values\n .map((v, i) => {\n const x = (i / (values.length - 1)) * (width - inset * 2) + inset;\n const y = height - inset - ((v - lo) / span) * (height - inset * 2);\n return `${i ? \"L\" : \"M\"}${x.toFixed(1)} ${y.toFixed(1)}`;\n })\n .join(\" \");\n}\n\n/** The y for a value in the same box `sparklinePath` uses — for endpoint dots\n * and the zero baseline. */\nexport function sparklineY(\n value: number,\n height: number,\n lo: number,\n hi: number,\n): number {\n const span = hi - lo || 1;\n const inset = 2;\n return height - inset - ((value - lo) / span) * (height - inset * 2);\n}\n","/**\n * The dashboard's visual primitives, rendered in the package's own semantic\n * classes (backed by the `styles.css` token sheet) — never host Tailwind. Each\n * is a thin wrapper over the pure logic in `primitives.ts`, so the mapping is\n * tested there and the markup stays trivial. These are the bricks the register\n * views and the assembled app compose.\n */\nimport type { ReactNode } from \"react\";\nimport {\n confidenceTone,\n formatCount,\n formatSigned,\n riskFraction,\n riskLevel,\n sparklinePath,\n sparklineY,\n statusTone,\n type Tone,\n} from \"./primitives.js\";\n\nconst PILL_CLASS: Record<Tone, string> = {\n good: \"vos-pill vos-pill-good\",\n warn: \"vos-pill vos-pill-warn\",\n crit: \"vos-pill vos-pill-crit\",\n accent: \"vos-pill vos-pill-accent\",\n neutral: \"vos-pill vos-pill-neutral\",\n};\n\n/** A colored status pill — tone from the status, the label shown verbatim. */\nexport function StatusPill({ status }: { status: string | null | undefined }) {\n if (!status) return <span className=\"vos-muted\">—</span>;\n return <span className={PILL_CLASS[statusTone(status)]}>{status}</span>;\n}\n\nconst FILL_CLASS: Record<Tone, string> = {\n good: \"vos-fill-good\",\n warn: \"vos-fill-warn\",\n crit: \"vos-fill-crit\",\n accent: \"vos-fill-good\",\n neutral: \"vos-fill-good\",\n};\nconst TEXT_CLASS: Record<Tone, string> = {\n good: \"vos-text-good\",\n warn: \"vos-text-warn\",\n crit: \"vos-text-crit\",\n accent: \"vos-text-good\",\n neutral: \"\",\n};\n\n/**\n * A risk bar (0–100) plus its number, both toned by threshold: a longer, redder\n * bar means a riskier belief the eye should land on first (spec story 5).\n */\nexport function RiskBar({ risk }: { risk: number }) {\n const level = riskLevel(risk);\n const pct = Math.round(riskFraction(risk) * 100);\n return (\n <span className=\"vos-metric-cell\">\n <span\n className=\"vos-risk-bar\"\n role=\"img\"\n aria-label={`Risk ${Math.round(risk)} of 100`}\n >\n <i className={FILL_CLASS[level]} style={{ width: `${pct}%` }} />\n </span>\n <b className={`vos-metric-num ${TEXT_CLASS[level]}`}>{Math.round(risk)}</b>\n </span>\n );\n}\n\n/**\n * A signed confidence reading: a tiny sparkline of its trajectory when a\n * history is available, always the +/- number (negative reads crit) — so a row\n * shows both where a belief stands and, when known, which way it is trending\n * (spec story 6). With no history the number stands alone; the list endpoint\n * carries no per-row series, so the in-row sparkline appears wherever a caller\n * does have one (e.g. the drawer trajectory uses `Sparkline` directly).\n */\nexport function ConfidenceCell({\n confidence,\n history,\n}: {\n confidence: number;\n history?: number[];\n}) {\n const tone = confidenceTone(confidence);\n return (\n <span className=\"vos-metric-cell\">\n {history && history.length >= 2 ? (\n <Sparkline\n values={history}\n width={46}\n height={16}\n min={-100}\n max={100}\n tone={tone}\n />\n ) : null}\n <b className={`vos-metric-num ${TEXT_CLASS[tone]}`}>\n {formatSigned(confidence)}\n </b>\n </span>\n );\n}\n\nconst STROKE_VAR: Record<Tone, string> = {\n good: \"var(--vos-good)\",\n warn: \"var(--vos-warn)\",\n crit: \"var(--vos-crit)\",\n accent: \"var(--vos-accent)\",\n neutral: \"var(--vos-muted)\",\n};\n\n/**\n * A signed sparkline over `values`. A zero baseline is drawn whenever the domain\n * spans it, so a line dipping below zero reads as a belief losing ground. The\n * last point gets a dot. `fill` shades the area under the line. Pure geometry\n * comes from `sparklinePath`/`sparklineY`.\n */\nexport function Sparkline({\n values,\n width = 240,\n height = 44,\n min,\n max,\n tone = \"good\",\n fill = false,\n ariaLabel,\n}: {\n values: number[];\n width?: number;\n height?: number;\n min?: number;\n max?: number;\n tone?: Tone;\n fill?: boolean;\n ariaLabel?: string;\n}) {\n const d = sparklinePath(values, width, height, min, max);\n if (!d) return null;\n const lo = min ?? Math.min(...values, 0);\n const hi = max ?? Math.max(...values, 0);\n const stroke = STROKE_VAR[tone];\n const last = values[values.length - 1]!;\n const lastX = width - 2;\n const lastY = sparklineY(last, height, lo, hi);\n const zeroY = sparklineY(0, height, lo, hi);\n const showBaseline = lo < 0 && hi > 0;\n return (\n <svg\n className=\"vos-spark\"\n width={width}\n height={height}\n viewBox={`0 0 ${width} ${height}`}\n preserveAspectRatio=\"none\"\n role=\"img\"\n aria-label={ariaLabel ?? `Trend, now ${formatSigned(last)}`}\n >\n {fill ? (\n <path\n d={`${d} L ${width - 2} ${height} L 2 ${height} Z`}\n fill={stroke}\n opacity=\"0.13\"\n />\n ) : null}\n {showBaseline ? (\n <line\n x1={2}\n x2={width - 2}\n y1={zeroY}\n y2={zeroY}\n stroke=\"var(--vos-border-strong)\"\n strokeWidth={1}\n strokeDasharray=\"3 3\"\n />\n ) : null}\n <path d={d} fill=\"none\" stroke={stroke} strokeWidth={2} />\n <circle cx={lastX} cy={lastY} r={3} fill={stroke} />\n </svg>\n );\n}\n\n/**\n * A glanceable stat tile — a label, a big number, and an optional sub-caption.\n * Becomes a button when `onClick` is given (counts that double as nav). Pure\n * presentation; the caller supplies the value.\n */\nexport function StatTile({\n label,\n value,\n sub,\n onClick,\n active,\n}: {\n label: string;\n value: number;\n sub?: ReactNode;\n onClick?: () => void;\n active?: boolean;\n}) {\n const body = (\n <>\n <div className=\"vos-tile-label\">{label}</div>\n <div className=\"vos-tile-value\">{formatCount(value)}</div>\n {sub ? <div className=\"vos-tile-sub\">{sub}</div> : null}\n </>\n );\n if (onClick) {\n return (\n <button\n type=\"button\"\n className=\"vos-tile\"\n onClick={onClick}\n aria-pressed={active}\n >\n {body}\n </button>\n );\n }\n return <div className=\"vos-tile\">{body}</div>;\n}\n","import type { AnyRecord, Collection } from \"@validation-os/core\";\nimport {\n cellValue,\n columnsFor,\n formatValue,\n primaryLabel,\n type ColumnDef,\n} from \"./columns.js\";\nimport { ConfidenceCell, RiskBar, StatusPill } from \"./primitives-view.js\";\n\nexport interface RegisterTableProps {\n register: Collection;\n records: AnyRecord[];\n /** Called with the clicked record's id — opens the read-only drawer. */\n onRowClick?: (id: string) => void;\n /** The id of the currently-open record, highlighted in the list. */\n selectedId?: string | null;\n}\n\n/**\n * A list table for one register — a row per record, the register's key fields\n * as columns. Assumptions read their state at a glance: a colored Status pill, a\n * signed Confidence, and a threshold-toned Risk bar (spec stories 4–6). Which\n * cells render as pills/bars/sparklines is declared on the column (`kind`), so\n * the treatment stays testable at the columns seam and this component stays a\n * dumb renderer. Presentational: the caller supplies the rows.\n */\nexport function RegisterTable({\n register,\n records,\n onRowClick,\n selectedId,\n}: RegisterTableProps) {\n const columns = columnsFor(register);\n\n if (records.length === 0) {\n return <p className=\"vos-empty\">No records yet.</p>;\n }\n\n return (\n <div className=\"vos-card vos-table-scroll\">\n <table className=\"vos-table\">\n <thead>\n <tr>\n {columns.map((c) => (\n <th\n key={c.key}\n scope=\"col\"\n className={c.align === \"right\" ? \"vos-r\" : undefined}\n >\n {c.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {records.map((record) => {\n const isSelected = record.id === selectedId;\n return (\n <tr\n key={record.id}\n onClick={() => onRowClick?.(record.id)}\n onKeyDown={\n onRowClick\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRowClick(record.id);\n }\n }\n : undefined\n }\n tabIndex={onRowClick ? 0 : undefined}\n aria-selected={isSelected}\n className={isSelected ? \"is-selected\" : undefined}\n >\n {columns.map((c, i) => (\n <td\n key={c.key}\n className={c.align === \"right\" ? \"vos-r\" : undefined}\n >\n <Cell column={c} record={record} headline={i === 0} />\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n/** One cell, rendered per its column's `kind`. The headline column falls back\n * to the record's id so a row is never blank. */\nfunction Cell({\n column,\n record,\n headline,\n}: {\n column: ColumnDef;\n record: AnyRecord;\n headline: boolean;\n}) {\n const raw = cellValue(column, record);\n\n if (column.kind === \"status\") {\n return <StatusPill status={raw == null ? null : String(raw)} />;\n }\n if (column.kind === \"risk\") {\n return typeof raw === \"number\" ? (\n <RiskBar risk={raw} />\n ) : (\n <span className=\"vos-muted\">—</span>\n );\n }\n if (column.kind === \"confidence\") {\n return typeof raw === \"number\" ? (\n <ConfidenceCell confidence={raw} />\n ) : (\n <span className=\"vos-muted\">—</span>\n );\n }\n\n const text =\n headline && (raw === null || raw === undefined || raw === \"\")\n ? primaryLabel(record)\n : formatValue(raw);\n return <span className={headline ? \"vos-ttl\" : undefined}>{text}</span>;\n}\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\nimport { DrawerShell } from \"./drawer-shell.js\";\nimport { REGISTER_LABEL } from \"./labels.js\";\nimport { derivedLabel, fieldLabel, formatValue, primaryLabel } from \"./columns.js\";\nimport { derivedTone, formatSigned, heroToneClass } from \"./primitives.js\";\nimport {\n buildPatch,\n draftFrom,\n editableFields,\n type Draft,\n type FieldEditor,\n} from \"./edit.js\";\nimport { useUpdate } from \"./use-records.js\";\nimport { UnderstandingPanel } from \"./understanding-panel.js\";\n\nexport interface RecordDrawerProps {\n register: Collection;\n /** The open record, or null while loading / when nothing is selected. */\n record: AnyRecord | null;\n /** True while the record is being fetched. */\n loading?: boolean;\n error?: string | null;\n /** Whether the drawer is open (a row is selected). */\n open: boolean;\n onClose: () => void;\n /** API base path (default `/api`). */\n basePath?: string;\n /** Re-fetch the record + its list — called after a save, and the re-fetch\n * path offered when a concurrent edit is detected. */\n onChanged?: () => void;\n /** Extra content below the fields in read mode — e.g. the relation editor. */\n children?: ReactNode;\n}\n\n/** Provider-owned/meta fields are shown in the footer, not as content rows. */\nconst META_FIELDS = new Set([\"id\", \"version\", \"createdAt\", \"updatedAt\", \"derived\"]);\n\n/** Sub-captions under the derived numbers — the formula, in plain language. */\nconst DERIVED_SUB: Record<string, string> = {\n confidence: \"Signed average of concluded readings\",\n risk: \"Impact × (1 − Confidence⁺/100)\",\n derivedImpact: \"Impact re-weighted by links\",\n impact: \"Impact re-weighted by links\",\n strength: \"of the evidence base\",\n sourceQuality: \"of the source\",\n};\n\n/**\n * A record drawer that reads and edits, and wires relations. The derived\n * numbers lead as a visually distinct \"computed — not editable\" hero (spec\n * stories 4/10): a bordered box, each number big and mono, Confidence toned by\n * sign and Risk by threshold, with a \"Why?\" reveal opening the understanding\n * layer in the same accent/pill language (story 11). Editing recomputes those\n * numbers server-side on save; a concurrent edit surfaces as a gentle, jargon-\n * free prompt with a re-fetch path (story 12). In read mode the drawer hosts\n * the relation editor (`children`). Chrome is shared via `DrawerShell`; styled\n * with the package's own token sheet, no host Tailwind.\n */\nexport function RecordDrawer({\n register,\n record,\n loading,\n error,\n open,\n onClose,\n basePath,\n onChanged,\n children,\n}: RecordDrawerProps) {\n const [editing, setEditing] = useState(false);\n const [draft, setDraft] = useState<Draft>({});\n // The record as it was when editing began. Diffing the draft against this\n // (not the live `record`) is what makes a conflict re-fetch safe: only the\n // fields the editor actually changed are written, on top of the latest\n // version — so a teammate's concurrent change to an untouched field survives.\n const [baseline, setBaseline] = useState<AnyRecord | null>(null);\n const [why, setWhy] = useState(false);\n const { save, saving, conflict, error: saveError, reset } = useUpdate(\n register,\n basePath,\n );\n\n // Opening a different record drops any in-progress edit and clears banners.\n const recordId = record?.id ?? null;\n useEffect(() => {\n setEditing(false);\n setBaseline(null);\n setWhy(false);\n reset();\n }, [recordId, reset]);\n\n const derived =\n record && record.derived && typeof record.derived === \"object\"\n ? (record.derived as Record<string, unknown>)\n : null;\n\n const fields = record\n ? Object.keys(record).filter((k) => !META_FIELDS.has(k))\n : [];\n\n function startEditing() {\n if (!record) return;\n setBaseline(record);\n setDraft(draftFrom(register, record));\n reset();\n setEditing(true);\n }\n\n function cancelEditing() {\n setEditing(false);\n reset();\n }\n\n async function onSave() {\n if (!record || !baseline) return;\n // Diff against the baseline (the fields the editor changed), but write\n // against the freshest known version so a reloaded record rebases cleanly.\n const patch = buildPatch(register, baseline, draft);\n patch.version = record.version;\n if (Object.keys(patch).length <= 1) {\n setEditing(false); // only `version` present — nothing actually changed\n return;\n }\n const result = await save(record.id, patch);\n if (result.ok) {\n setEditing(false);\n onChanged?.(); // pull the recomputed record + refreshed list back in\n }\n // On conflict/error the hook holds the message; we stay in edit mode with\n // the draft intact so nothing the editor typed is lost.\n }\n\n function reloadLatest() {\n reset();\n // Re-fetch the latest record; the baseline is kept, so the next save still\n // writes only the fields this editor changed — never the teammate's edits.\n onChanged?.();\n }\n\n const setField = (key: string, value: string) =>\n setDraft((d) => ({ ...d, [key]: value }));\n\n return (\n <DrawerShell\n open={open}\n onClose={onClose}\n ariaLabel={`${REGISTER_LABEL[register]} record`}\n >\n <header className=\"vos-drawer-header\">\n <div style={{ flex: 1, minWidth: 0 }}>\n <p className=\"vos-drawer-eyebrow\">{REGISTER_LABEL[register]}</p>\n <h2 className=\"vos-drawer-title\">\n {record ? primaryLabel(record) : loading ? \"Loading…\" : \"—\"}\n </h2>\n </div>\n {record ? (\n <span className=\"vos-verbadge\">v{formatValue(record.version)}</span>\n ) : null}\n {record && !editing ? (\n <button\n type=\"button\"\n onClick={startEditing}\n className=\"vos-btn vos-btn-ghost vos-btn-sm\"\n >\n Edit\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={onClose}\n className=\"vos-iconbtn\"\n aria-label=\"Close\"\n >\n ✕\n </button>\n </header>\n\n <div className=\"vos-drawer-body\">\n {loading ? (\n <p className=\"vos-muted\">Loading record…</p>\n ) : error ? (\n <p className=\"vos-error\">{error}</p>\n ) : !record ? (\n <p className=\"vos-muted\">No record.</p>\n ) : (\n <>\n {derived ? (\n <div>\n <div className=\"vos-derived\">\n <div className=\"vos-derived-head\">\n Derived\n <span className=\"vos-lock\">🔒 computed on write — not editable</span>\n </div>\n <div className=\"vos-dgrid\">\n {Object.entries(derived).map(([key, value]) => (\n <DerivedCell\n key={key}\n field={key}\n value={value}\n showWhy={key === \"confidence\"}\n whyOpen={why}\n onWhy={() => setWhy((w) => !w)}\n />\n ))}\n </div>\n </div>\n {\"confidence\" in derived && why ? (\n <div className=\"vos-why-panel\">\n <UnderstandingPanel assumption={record} basePath={basePath} />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {conflict ? (\n <ConflictBanner message={conflict} onReload={reloadLatest} />\n ) : null}\n {saveError ? (\n <p role=\"alert\" className=\"vos-banner vos-banner-crit\">\n {saveError}\n </p>\n ) : null}\n\n {editing ? (\n <EditFields\n register={register}\n draft={draft}\n onField={setField}\n />\n ) : (\n <div className=\"vos-detail-list\">\n {fields.map((key) => (\n <div key={key} className=\"vos-detail-row\">\n <span className=\"vos-detail-k\">{fieldLabel(key)}</span>\n <span className=\"vos-detail-v\">\n {formatValue(record[key])}\n </span>\n </div>\n ))}\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Relation editor (read mode only) — editing keeps the drawer focused. */}\n {record && !loading && !error && !editing ? children : null}\n\n {record && editing ? (\n <footer className=\"vos-drawer-footer\">\n <button\n type=\"button\"\n onClick={cancelEditing}\n disabled={saving}\n className=\"vos-btn vos-btn-ghost vos-btn-sm\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={onSave}\n disabled={saving}\n className=\"vos-btn vos-btn-sm\"\n >\n {saving ? \"Saving…\" : \"Save\"}\n </button>\n </footer>\n ) : record ? (\n <footer className=\"vos-drawer-footer\">\n {record.id} · updated {formatValue(record.updatedAt)}\n </footer>\n ) : null}\n </DrawerShell>\n );\n}\n\n/** One number in the derived hero: label (+ \"Why?\" on Confidence), the big\n * mono value toned by meaning, and the formula sub-caption. */\nfunction DerivedCell({\n field,\n value,\n showWhy,\n whyOpen,\n onWhy,\n}: {\n field: string;\n value: unknown;\n showWhy: boolean;\n whyOpen: boolean;\n onWhy: () => void;\n}) {\n const num = typeof value === \"number\" ? value : null;\n let toneClass = \"\";\n let display = formatValue(value);\n if (num !== null) {\n toneClass = heroToneClass(derivedTone(field, num));\n // Confidence is signed; the other numbers read as whole counts.\n display = field === \"confidence\" ? formatSigned(num) : String(Math.round(num));\n }\n return (\n <div className=\"vos-dcell\">\n <div className=\"vos-dcell-k\">\n {derivedLabel(field)}\n {showWhy ? (\n <button\n type=\"button\"\n className=\"vos-why\"\n onClick={onWhy}\n aria-expanded={whyOpen}\n >\n Why? {whyOpen ? \"▴\" : \"▾\"}\n </button>\n ) : null}\n </div>\n <div className={`vos-dcell-v ${toneClass}`}>{display}</div>\n {DERIVED_SUB[field] ? (\n <div className=\"vos-dcell-sub\">{DERIVED_SUB[field]}</div>\n ) : null}\n </div>\n );\n}\n\nfunction ConflictBanner({\n message,\n onReload,\n}: {\n message: string;\n onReload: () => void;\n}) {\n return (\n <div role=\"alert\" className=\"vos-banner vos-banner-warn\">\n <div className=\"vos-banner-body\">\n <span>{message}</span>\n </div>\n <button type=\"button\" onClick={onReload}>\n Review the latest\n </button>\n </div>\n );\n}\n\nfunction EditFields({\n register,\n draft,\n onField,\n}: {\n register: Collection;\n draft: Draft;\n onField: (key: string, value: string) => void;\n}) {\n return (\n <div className=\"vos-field-stack\">\n {editableFields(register).map((field) => (\n <FieldInput\n key={field.key}\n field={field}\n value={draft[field.key]}\n onChange={(v) => onField(field.key, v)}\n />\n ))}\n </div>\n );\n}\n\nfunction FieldInput({\n field,\n value,\n onChange,\n}: {\n field: FieldEditor;\n value: string | undefined;\n onChange: (value: string) => void;\n}) {\n // Field keys can contain spaces (\"5 Whys\"); slugify for a valid DOM id.\n const id = `field-${field.key.replace(/\\s+/g, \"-\")}`;\n return (\n <div className=\"vos-field\">\n <label htmlFor={id}>{field.label}</label>\n {field.kind === \"textarea\" ? (\n <textarea\n id={id}\n value={String(value ?? \"\")}\n onChange={(e) => onChange(e.target.value)}\n rows={3}\n className=\"vos-input\"\n />\n ) : field.kind === \"select\" ? (\n <select\n id={id}\n value={String(value ?? \"\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"vos-input\"\n >\n {field.nullable ? <option value=\"\">—</option> : null}\n {field.options?.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n ) : (\n <input\n id={id}\n type={field.kind === \"number\" ? \"number\" : \"text\"}\n value={String(value ?? \"\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"vos-input\"\n />\n )}\n </div>\n );\n}\n","/**\n * The pure edit-logic seam — which fields a register lets you edit, how a\n * form draft maps back to a version-guarded patch, and the plain-language\n * conflict copy. Kept as pure data/functions (no DOM) so the edit behaviour\n * is unit-testable exactly like `columns.ts`; the drawer component consumes it.\n *\n * Derived numbers (Confidence, Risk, Derived Impact, Strength) are never\n * editable — they are computed server-side on write (spec user story 4/11),\n * so they never appear here. Relation links are set through `link`, a separate\n * story, so relation-id fields aren't editable inputs either.\n */\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\n\n/** The plain-language conflict prompt — never version jargon (user story 12).\n * The API returns its own copy on a 409; this is the client-side fallback. */\nexport const CONFLICT_MESSAGE =\n \"Someone edited this while you had it open — your changes are safe, \" +\n \"take a look before saving again.\";\n\nexport type FieldKind = \"text\" | \"textarea\" | \"number\" | \"select\";\n\nexport interface FieldEditor {\n /** The record key this editor writes. */\n key: string;\n /** Plain-language label shown beside the input. */\n label: string;\n kind: FieldKind;\n /** For `select`: the allowed options (a leading blank = \"unset\"). */\n options?: readonly string[];\n /** An empty input clears the field to `null` rather than \"\". */\n nullable?: boolean;\n}\n\nconst t = (key: string, label: string): FieldEditor => ({ key, label, kind: \"text\" });\nconst area = (key: string, label: string): FieldEditor => ({\n key,\n label,\n kind: \"textarea\",\n});\nconst num = (key: string, label: string): FieldEditor => ({\n key,\n label,\n kind: \"number\",\n nullable: true,\n});\nconst sel = (\n key: string,\n label: string,\n options: readonly string[],\n nullable = false,\n): FieldEditor => ({ key, label, kind: \"select\", options, nullable });\n\nconst READING_RUNGS = [\n \"Opinion\",\n \"Pitch-deck reaction\",\n \"Anecdotal\",\n \"Desk research\",\n \"Survey at scale\",\n \"Prototype usage\",\n \"Signed intent\",\n \"Paying users\",\n] as const;\nconst SOURCE_QUALITY = [\"1\", \"0.7\", \"0.5\"] as const;\n\n/**\n * The editable fields per register, in the order they render. Hand-scored and\n * descriptive fields only — derived numbers, ids/timestamps, and relation\n * links are deliberately excluded.\n */\nconst EDITORS: Record<Collection, FieldEditor[]> = {\n assumptions: [\n t(\"Title\", \"Assumption\"),\n area(\"Description\", \"Description\"),\n num(\"Impact\", \"Impact\"),\n sel(\"Status\", \"Status\", [\"Draft\", \"Live\", \"Invalidated\"]),\n t(\"Lens\", \"Lens\"),\n area(\"5 Whys\", \"5 Whys\"),\n area(\"Metric for truth\", \"Metric for truth\"),\n area(\"Scoring justification\", \"Scoring justification\"),\n // `moot` is deliberately not editable here — mooting an assumption is a\n // gated business action (see core `relations.ts`), not a free-form toggle.\n ],\n experiments: [\n t(\"Title\", \"Experiment\"),\n t(\"Instrument\", \"Instrument\"),\n sel(\"Feasibility\", \"Feasibility\", [\"High\", \"Medium\", \"Low\"], true),\n sel(\"Status\", \"Status\", [\"Running\", \"Closed\"]),\n sel(\n \"closureReason\",\n \"Closure reason\",\n [\"Completed\", \"Early-stop\", \"Kill\"],\n true,\n ),\n t(\"Date\", \"Date\"),\n ],\n readings: [\n t(\"Title\", \"Reading\"),\n t(\"Source\", \"Source\"),\n sel(\"Rung\", \"Rung\", READING_RUNGS),\n sel(\"Result\", \"Result\", [\"Validated\", \"Invalidated\", \"Inconclusive\"]),\n sel(\"Representativeness\", \"Representativeness\", SOURCE_QUALITY),\n sel(\"Credibility\", \"Credibility\", SOURCE_QUALITY),\n sel(\"magnitudeBand\", \"Magnitude band\", [\"Low\", \"Typical\", \"High\"], true),\n t(\"Date\", \"Date\"),\n ],\n goals: [\n t(\"Title\", \"Goal\"),\n sel(\"Status\", \"Status\", [\"Draft\", \"Active\", \"Closed\"]),\n sel(\"Outcome\", \"Outcome\", [\"Achieved\", \"Missed\", \"Dropped\"], true),\n t(\"Date\", \"Date\"),\n ],\n decisions: [\n t(\"Title\", \"Decision\"),\n sel(\"Status\", \"Status\", [\"Active\", \"Provisional\", \"Superseded\", \"Reversed\"]),\n ],\n glossary: [\n t(\"Title\", \"Term\"),\n sel(\"Status\", \"Status\", [\"Active\", \"Provisional\", \"Superseded\"]),\n ],\n people: [t(\"Name\", \"Name\"), t(\"Role\", \"Role\"), t(\"Segment\", \"Segment\")],\n};\n\n/** The fields a register lets you edit, in render order. */\nexport function editableFields(register: Collection): FieldEditor[] {\n return EDITORS[register];\n}\n\n/** A form draft is a plain string map keyed by field — what the inputs hold. */\nexport type Draft = Record<string, string>;\n\n/** Build the initial form draft from a record: every editable field becomes a\n * string input value, and missing values become empty inputs. */\nexport function draftFrom(register: Collection, record: AnyRecord): Draft {\n const draft: Draft = {};\n for (const f of editableFields(register)) {\n const value = record[f.key];\n draft[f.key] = value === null || value === undefined ? \"\" : String(value);\n }\n return draft;\n}\n\n/** Coerce one draft value back to its stored shape, honouring kind/nullable. */\nfunction coerce(field: FieldEditor, raw: string): unknown {\n const str = String(raw);\n if (field.kind === \"number\") {\n if (str.trim() === \"\") return null;\n const n = Number(str);\n return Number.isNaN(n) ? null : n;\n }\n // An empty select is \"unset\" → null; an empty nullable text field clears too.\n if (str === \"\" && (field.kind === \"select\" || field.nullable)) return null;\n return str;\n}\n\n/** Absent and empty values compare equal, so an untouched field isn't a change. */\nfunction norm(value: unknown): unknown {\n return value === undefined || value === \"\" ? null : value;\n}\n\n/**\n * A version-guarded patch from a draft: the loaded `version` plus only the\n * fields whose value actually changed (so an untouched save doesn't churn\n * unrelated fields). The API rejects a stale version with a 409.\n */\nexport function buildPatch(\n register: Collection,\n original: AnyRecord,\n draft: Draft,\n): Record<string, unknown> {\n const patch: Record<string, unknown> = { version: original.version };\n for (const field of editableFields(register)) {\n const next = coerce(field, draft[field.key] ?? \"\");\n if (norm(next) !== norm(original[field.key])) patch[field.key] = next;\n }\n return patch;\n}\n\n/** Whether a draft differs from the record it was loaded from. */\nexport function hasEdits(\n register: Collection,\n original: AnyRecord,\n draft: Draft,\n): boolean {\n return Object.keys(buildPatch(register, original, draft)).length > 1;\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AnyRecord, Collection } from \"@validation-os/core\";\nimport { CONFLICT_MESSAGE } from \"./edit.js\";\n\n/**\n * Client hooks that read the register over HTTP through the API read routes\n * (`GET {basePath}/{register}` and `GET {basePath}/{register}/{id}`). The API\n * reaches Firestore server-side through the adapter, so no backend credentials\n * ever reach the browser — the browser only ever speaks to the Clerk-gated API.\n */\n\ninterface AsyncState<T> {\n data: T | null;\n loading: boolean;\n error: string | null;\n}\n\n/** Both read routes wrap their payload in a `{ data }` envelope. */\nfunction pickData<T>(body: unknown): T {\n return (body as { data: T }).data;\n}\n\n/**\n * Fetch one JSON resource, tracking loading/error. A null `url` means \"idle\"\n * (nothing to load yet) — the drawer's get hook uses this until a row is\n * clicked. Returns a `refresh` that re-runs the fetch. This is the shared\n * engine behind both `useList` and `useRecord`.\n */\nfunction useJsonResource<T>(url: string | null): AsyncState<T> & {\n refresh: () => void;\n} {\n const [state, setState] = useState<AsyncState<T>>({\n data: null,\n loading: url !== null,\n error: null,\n });\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (url === null) {\n setState({ data: null, loading: false, error: null });\n return;\n }\n let live = true;\n setState((s) => ({ ...s, loading: true }));\n fetch(url)\n .then(async (res) => {\n if (!res.ok) throw new Error(`Request to ${url} failed (${res.status})`);\n return pickData<T>(await res.json());\n })\n .then((data) => live && setState({ data, loading: false, error: null }))\n .catch(\n (e: unknown) =>\n live &&\n setState({\n data: null,\n loading: false,\n error: e instanceof Error ? e.message : \"Failed to load\",\n }),\n );\n return () => {\n live = false;\n };\n }, [url, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n return { ...state, refresh };\n}\n\nexport interface UseListResult {\n records: AnyRecord[] | null;\n loading: boolean;\n error: string | null;\n refresh: () => void;\n}\n\n/** Fetch every row of a register. */\nexport function useList(register: Collection, basePath = \"/api\"): UseListResult {\n const { data, loading, error, refresh } = useJsonResource<AnyRecord[]>(\n `${basePath}/${register}`,\n );\n return { records: data, loading, error, refresh };\n}\n\nexport interface UseRecordResult {\n record: AnyRecord | null;\n loading: boolean;\n error: string | null;\n /** Re-fetch the record — the re-fetch path after a save or edit conflict. */\n refresh: () => void;\n}\n\n/**\n * Fetch one record by id. `id` may be null (nothing open) — the hook stays\n * idle until an id is supplied, so it drives a drawer that opens on row click.\n * `refresh` re-fetches: the edit flow calls it after a save, and it's the\n * re-fetch path offered when a write hits a concurrent-edit conflict.\n */\nexport function useRecord(\n register: Collection,\n id: string | null,\n basePath = \"/api\",\n): UseRecordResult {\n const url = id\n ? `${basePath}/${register}/${encodeURIComponent(id)}`\n : null;\n const { data, loading, error, refresh } = useJsonResource<AnyRecord>(url);\n return { record: data, loading, error, refresh };\n}\n\n/** The outcome of a save: the recomputed record, or a rejection with a\n * plain-language message (a concurrent-edit conflict, or another failure). */\nexport type SaveResult =\n | { ok: true; record: AnyRecord }\n | { ok: false; conflict: boolean; message: string };\n\nconst SAVE_FAILED = \"Couldn't save your changes — please try again.\";\n\n/**\n * Map an update response (status + parsed body) to a `SaveResult`. Pure, so\n * the 409/error/ok branching is unit-testable without a DOM. A 409 is a\n * concurrent-edit conflict, surfaced in the API's plain-language copy (or the\n * `CONFLICT_MESSAGE` fallback) — never version jargon (spec user story 12).\n */\nexport function interpretSave(status: number, body: unknown): SaveResult {\n if (status >= 200 && status < 300) {\n return { ok: true, record: pickData<AnyRecord>(body) };\n }\n const message = (body as { message?: unknown } | null)?.message;\n const text = typeof message === \"string\" ? message : null;\n if (status === 409) {\n return { ok: false, conflict: true, message: text ?? CONFLICT_MESSAGE };\n }\n return { ok: false, conflict: false, message: text ?? SAVE_FAILED };\n}\n\nexport interface UseUpdateResult {\n /** PATCH `{ version, ...patch }`; resolves to the recomputed record or a\n * rejection. Never throws — callers branch on `result.ok`. */\n save: (id: string, patch: Record<string, unknown>) => Promise<SaveResult>;\n saving: boolean;\n /** Plain-language conflict prompt when a concurrent edit was detected. */\n conflict: string | null;\n /** Plain-language message for any other save failure. */\n error: string | null;\n /** Clear conflict/error state (e.g. when re-entering edit mode). */\n reset: () => void;\n}\n\n/**\n * Version-guarded update over the API write route. A stale version comes back\n * as a 409, which we surface as a gentle, jargon-free `conflict` message (spec\n * user story 12) — the API sends the copy, and `CONFLICT_MESSAGE` is the\n * fallback. Derived values are recomputed server-side, so the returned record\n * carries the authoritative numbers, never anything the client computed.\n */\nexport function useUpdate(\n register: Collection,\n basePath = \"/api\",\n): UseUpdateResult {\n const [saving, setSaving] = useState(false);\n const [conflict, setConflict] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const save = useCallback(\n async (id: string, patch: Record<string, unknown>): Promise<SaveResult> => {\n setSaving(true);\n setConflict(null);\n setError(null);\n try {\n const res = await fetch(\n `${basePath}/${register}/${encodeURIComponent(id)}`,\n {\n method: \"PATCH\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(patch),\n },\n );\n const body = await res.json().catch(() => null);\n const result = interpretSave(res.status, body);\n if (!result.ok && result.conflict) setConflict(result.message);\n else if (!result.ok) setError(result.message);\n return result;\n } catch (e) {\n const message =\n e instanceof Error ? e.message : \"Couldn't save your changes.\";\n setError(message);\n return { ok: false, conflict: false, message };\n } finally {\n setSaving(false);\n }\n },\n [register, basePath],\n );\n\n const reset = useCallback(() => {\n setConflict(null);\n setError(null);\n }, []);\n\n return { save, saving, conflict, error, reset };\n}\n","/**\n * The understanding layer's data join (OPS-1276). Pure: given an assumption\n * and the readings + experiments registers, it produces everything the Reveal\n * shows — the experiments testing the belief (each with how hard it moves\n * Confidence and how close it is to concluding), the goal/direct evidence that\n * also moves the number, and the Confidence-over-time trajectory.\n *\n * The record → derivation-input mapping is `@validation-os/core`'s shared\n * `toReadingInput`, so a reading is read here exactly as it is server-side.\n */\nimport {\n toReadingInput,\n type AnyRecord,\n type BarLine,\n} from \"@validation-os/core\";\nimport {\n confidenceAttribution,\n confidenceTrajectory,\n experimentProgress,\n isConcluded,\n type MoverKind,\n type Progress,\n type TrajectoryPoint,\n} from \"@validation-os/core/derivation\";\n\n/** An experiment testing this assumption: how hard it moves Confidence, and\n * how close it is to concluding. `contribution` is 0 for a running experiment\n * that has not produced a concluded reading yet — it still shows, so its\n * progress-to-conclusion is visible. */\nexport interface ExperimentView {\n experimentId: string;\n title: string | null;\n status: string | null;\n /** Signed push on Confidence; 0 until a concluded reading lands. */\n contribution: number;\n magnitude: number;\n /** Concluded readings this experiment has produced for the belief. */\n readingCount: number;\n progress: Progress | null;\n /** Concluded/closed — reads as done rather than in-flight. */\n done: boolean;\n}\n\n/** Goal-rung or direct evidence that moves Confidence but is not an experiment. */\nexport interface OtherMover {\n key: string;\n kind: Exclude<MoverKind, \"experiment\">;\n goalId: string | null;\n contribution: number;\n magnitude: number;\n readingCount: number;\n}\n\nexport interface Understanding {\n /** The same Confidence the derived box shows. */\n confidence: number;\n /** Experiments testing this belief, ranked by how hard they push. */\n experiments: ExperimentView[];\n /** Goal/direct evidence that also moves the number. */\n otherMovers: OtherMover[];\n /** Confidence over time; empty when no concluded reading is dated. */\n trajectory: TrajectoryPoint[];\n /** Concluded readings feeding the number, across all sources. */\n readingCount: number;\n}\n\nfunction str(v: unknown): string | null {\n return typeof v === \"string\" && v !== \"\" ? v : null;\n}\n\n/** Does this experiment pre-register a bar line against the given assumption? */\nfunction testsAssumption(exp: AnyRecord, assumptionId: string): boolean {\n const bars = exp.barLines as BarLine[] | undefined;\n if (bars?.some((b) => b.assumptionId === assumptionId)) return true;\n const ids = exp.barLineAssumptionIds as string[] | undefined;\n return ids?.includes(assumptionId) ?? false;\n}\n\nexport function buildUnderstanding(\n assumption: AnyRecord,\n readings: AnyRecord[],\n experiments: AnyRecord[],\n): Understanding {\n const mine = readings.filter((r) => r.assumptionId === assumption.id);\n const inputs = mine.map(toReadingInput);\n const { confidence, movers } = confidenceAttribution(inputs);\n\n const experimentsById = new Map(experiments.map((e) => [e.id, e]));\n const moverByExperiment = new Map(\n movers.filter((m) => m.kind === \"experiment\").map((m) => [m.experimentId!, m]),\n );\n\n // Every experiment testing this belief — whether or not it has moved the\n // number yet — plus any experiment a reading points at that isn't linked via\n // bar lines. So a freshly-started experiment with no readings still shows.\n const experimentIds = new Set<string>([\n ...experiments.filter((e) => testsAssumption(e, assumption.id)).map((e) => e.id),\n ...moverByExperiment.keys(),\n ]);\n\n const experimentViews: ExperimentView[] = [...experimentIds].map((id) => {\n const exp = experimentsById.get(id);\n const mover = moverByExperiment.get(id);\n const bars = (exp?.barLines as BarLine[] | undefined) ?? [];\n const progress = bars.length ? experimentProgress(bars) : null;\n const status = exp ? str(exp.Status) : null;\n return {\n experimentId: id,\n title: exp ? str(exp.Title) : null,\n status,\n contribution: mover?.contribution ?? 0,\n magnitude: mover?.magnitude ?? 0,\n readingCount: mover?.readingCount ?? 0,\n progress,\n done: status === \"Closed\" || progress?.concluded === true,\n };\n });\n // Strongest movers first; among non-movers, in-flight before done, then id.\n experimentViews.sort(\n (a, b) =>\n b.magnitude - a.magnitude ||\n Number(a.done) - Number(b.done) ||\n a.experimentId.localeCompare(b.experimentId),\n );\n\n const otherMovers: OtherMover[] = movers\n .filter((m) => m.kind !== \"experiment\")\n .map((m) => ({\n key: m.key,\n kind: m.kind as OtherMover[\"kind\"],\n goalId: m.goalId,\n contribution: m.contribution,\n magnitude: m.magnitude,\n readingCount: m.readingCount,\n }));\n\n return {\n confidence,\n experiments: experimentViews,\n otherMovers,\n trajectory: confidenceTrajectory(inputs),\n readingCount: inputs.filter((r) => isConcluded(r.result)).length,\n };\n}\n","import type { ReactNode } from \"react\";\nimport type { AnyRecord } from \"@validation-os/core\";\nimport type { TrajectoryPoint } from \"@validation-os/core/derivation\";\nimport { useList } from \"./use-records.js\";\nimport { Sparkline } from \"./primitives-view.js\";\nimport { confidenceTone, formatSigned } from \"./primitives.js\";\nimport {\n buildUnderstanding,\n type ExperimentView,\n type OtherMover,\n} from \"./understanding.js\";\n\n/**\n * The understanding layer behind the Confidence \"Why?\" (OPS-1276): which\n * experiments move the number (ranked by push) and how close each running\n * experiment is to concluding, the goal/direct evidence that also moves it, and\n * Confidence over time. It lazy-loads the readings + experiments registers (it\n * only mounts when the Reveal is open), then derives everything through the\n * shared derivation module. Restyled into the drawer's accent/pill language\n * (spec story 11): signed push tracks and a signed trajectory sparkline, in the\n * package's own token sheet — no host Tailwind.\n */\nexport function UnderstandingPanel({\n assumption,\n basePath,\n}: {\n assumption: AnyRecord;\n basePath?: string;\n}) {\n const readings = useList(\"readings\", basePath);\n const experiments = useList(\"experiments\", basePath);\n\n if (readings.loading || experiments.loading) {\n return <Muted>Working out what moved the number…</Muted>;\n }\n if (readings.error || experiments.error) {\n return <Muted>Couldn't load the evidence behind this number.</Muted>;\n }\n\n const u = buildUnderstanding(\n assumption,\n readings.records ?? [],\n experiments.records ?? [],\n );\n\n if (u.experiments.length === 0 && u.otherMovers.length === 0) {\n return (\n <Muted>\n No experiments or concluded readings yet — Confidence rests on the\n neutral prior alone.\n </Muted>\n );\n }\n\n // One scale for every push bar so experiments and other evidence compare.\n const maxMagnitude = Math.max(\n ...u.experiments.map((e) => e.magnitude),\n ...u.otherMovers.map((m) => m.magnitude),\n 0.01,\n );\n\n return (\n <>\n {u.experiments.length ? (\n <section>\n <div className=\"vos-why-section-title\">What's moving Confidence</div>\n {u.experiments.map((e) => (\n <PushRow\n key={e.experimentId}\n label={e.title ?? `Experiment ${e.experimentId}`}\n note={experimentDetail(e)}\n contribution={e.contribution}\n magnitude={e.magnitude}\n max={maxMagnitude}\n done={e.done}\n />\n ))}\n </section>\n ) : null}\n\n {u.otherMovers.length ? (\n <section>\n <div className=\"vos-why-section-title\">Other evidence</div>\n {u.otherMovers.map((m) => (\n <PushRow\n key={m.key}\n label={otherMoverLabel(m)}\n contribution={m.contribution}\n magnitude={m.magnitude}\n max={maxMagnitude}\n />\n ))}\n </section>\n ) : null}\n\n <Trajectory points={u.trajectory} />\n </>\n );\n}\n\n/** A labelled row with a signed contribution and a signed push bar (fill left\n * for negative, right for positive; width ∝ push). */\nfunction PushRow({\n label,\n note,\n contribution,\n magnitude,\n max,\n done,\n}: {\n label: string;\n note?: string;\n contribution: number;\n magnitude: number;\n max: number;\n done?: boolean;\n}) {\n const up = contribution >= 0;\n const moving = magnitude > 0;\n const width = Math.round((magnitude / max) * 50);\n const fill = up\n ? { left: \"50%\", width: `${width}%`, background: \"var(--vos-good)\" }\n : { right: \"50%\", width: `${width}%`, background: \"var(--vos-crit)\" };\n return (\n <div className=\"vos-mover\">\n <span className=\"vos-mover-name\">{label}</span>\n {note ? (\n <span className={`vos-mover-note ${done ? \"vos-text-good\" : \"vos-text-warn\"}`}>\n {note}\n </span>\n ) : null}\n <span className=\"vos-track vos-signed\">\n {moving ? <i style={fill} /> : null}\n </span>\n <span\n className=\"vos-mover-val\"\n style={{ color: up ? \"var(--vos-good)\" : \"var(--vos-crit)\" }}\n >\n {moving ? formatSigned(contribution) : \"—\"}\n </span>\n </div>\n );\n}\n\nfunction Trajectory({ points }: { points: TrajectoryPoint[] }) {\n if (points.length < 2) {\n return (\n <p className=\"vos-hint\">\n {points.length === 1\n ? `One dated reading so far — Confidence ${formatSigned(points[0]!.confidence)} on ${points[0]!.date}.`\n : \"No dated readings yet to chart a trajectory.\"}\n </p>\n );\n }\n const first = points[0]!;\n const last = points[points.length - 1]!;\n const values = points.map((p) => p.confidence);\n return (\n <div className=\"vos-traj\">\n <div className=\"vos-traj-head\">\n <span className=\"vos-lbl\">Confidence over time</span>\n </div>\n <Sparkline\n values={values}\n width={260}\n height={44}\n min={-100}\n max={100}\n tone={confidenceTone(last.confidence)}\n fill\n ariaLabel={`Confidence moved from ${formatSigned(first.confidence)} to ${formatSigned(last.confidence)}`}\n />\n <div className=\"vos-traj-foot\">\n <span>{first.date}</span>\n <span className=\"vos-num\">now {formatSigned(last.confidence)}</span>\n </div>\n </div>\n );\n}\n\nfunction experimentDetail(e: ExperimentView): string {\n const evidence =\n e.readingCount === 0\n ? \"No readings yet\"\n : `${e.readingCount} reading${e.readingCount === 1 ? \"\" : \"s\"}`;\n const p = e.progress;\n if (e.done) {\n return p\n ? `Concluded · ${p.total} of ${p.total} bars settled`\n : `Concluded · ${evidence}`;\n }\n if (!p || p.total === 0) return `${evidence} · no pre-registered bars`;\n return `${evidence} · ${p.settled} of ${p.total} bars settled · ${p.toGo} to go`;\n}\n\nfunction otherMoverLabel(m: OtherMover): string {\n if (m.kind === \"goal\") return `Goal ${m.goalId ?? \"\"}`.trim();\n return m.readingCount === 1 ? \"A direct reading\" : \"Direct readings\";\n}\n\nfunction Muted({ children }: { children: ReactNode }) {\n return <p className=\"vos-hint\">{children}</p>;\n}\n","import { useMemo, useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\nimport { REGISTER_LABEL } from \"./labels.js\";\nimport {\n emptyDraft,\n formFieldsFor,\n missingRequired,\n toCreatePayload,\n type FormField,\n} from \"./form-fields.js\";\nimport { FIELD_CONTROL_CLASS, FIELD_LABEL_CLASS } from \"./field-styles.js\";\nimport { useCreate } from \"./use-mutations.js\";\n\nexport interface RecordFormProps {\n register: Collection;\n basePath?: string;\n /** Called with the new record's id after a successful create. */\n onCreated: (id: string) => void;\n onCancel: () => void;\n}\n\n/**\n * The \"new record\" form for one register (spec user story 13). Editable own-\n * fields only — derived numbers are computed server-side and marked\n * computed-not-editable elsewhere; relations are wired by linking after the\n * record exists. Presence-gap fields (5 Whys, etc.) appear as first-class\n * textareas. On submit it POSTs through the API, which recomputes on write.\n */\nexport function RecordForm({\n register,\n basePath,\n onCreated,\n onCancel,\n}: RecordFormProps) {\n const fields = useMemo(() => formFieldsFor(register), [register]);\n const [draft, setDraft] = useState<Record<string, string>>(() =>\n emptyDraft(register),\n );\n const { create, saving, error } = useCreate(register, basePath);\n\n const missing = missingRequired(register, draft);\n const set = (key: string, value: string) =>\n setDraft((d) => ({ ...d, [key]: value }));\n\n const onSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (missing.length > 0 || saving) return;\n try {\n const created = await create(toCreatePayload(register, draft));\n onCreated(created.id);\n } catch {\n // The hook surfaces the message in `error`; keep the form open to retry.\n }\n };\n\n return (\n <form onSubmit={onSubmit} className=\"vos-form\">\n <div className=\"vos-form-body\">\n {fields.map((field) => (\n <Field\n key={field.key}\n field={field}\n value={draft[field.key] ?? \"\"}\n onChange={(v) => set(field.key, v)}\n />\n ))}\n {error ? <p className=\"vos-error\">{error}</p> : null}\n </div>\n\n <footer className=\"vos-drawer-footer\">\n <button type=\"button\" onClick={onCancel} className=\"vos-btn vos-btn-ghost vos-btn-sm\">\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={missing.length > 0 || saving}\n title={\n missing.length > 0 ? `Fill in: ${missing.join(\", \")}` : undefined\n }\n className=\"vos-btn vos-btn-sm\"\n >\n {saving ? \"Creating…\" : `Create ${REGISTER_LABEL[register]}`}\n </button>\n </footer>\n </form>\n );\n}\n\nfunction Field({\n field,\n value,\n onChange,\n}: {\n field: FormField;\n value: string;\n onChange: (value: string) => void;\n}) {\n const id = `field-${field.key}`;\n return (\n <div className=\"vos-field\">\n <label htmlFor={id} className={FIELD_LABEL_CLASS}>\n {field.label}\n {field.required ? <span className=\"vos-req\"> *</span> : null}\n </label>\n {field.kind === \"textarea\" ? (\n <textarea\n id={id}\n value={value}\n rows={3}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n className={FIELD_CONTROL_CLASS}\n />\n ) : field.kind === \"select\" ? (\n <select\n id={id}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className={FIELD_CONTROL_CLASS}\n >\n <option value=\"\">—</option>\n {field.options?.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n ) : (\n <input\n id={id}\n type={field.kind === \"number\" ? \"number\" : \"text\"}\n value={value}\n placeholder={field.placeholder}\n onChange={(e) => onChange(e.target.value)}\n className={FIELD_CONTROL_CLASS}\n />\n )}\n </div>\n );\n}\n","/**\n * The editable-field spec for the \"new record\" form, per register — kept as\n * pure data + functions (like `columns.ts`) so the create form is unit-testable\n * without a DOM. Only a record's own scalar fields appear here: derived numbers\n * are computed server-side (never typed), and relations are wired separately by\n * linking (see `relations.ts` / the relation editor), so id/relation fields are\n * deliberately absent. Vocabularies mirror `core`'s type unions.\n */\nimport {\n GOAL_RUNG_VALUES,\n TESTING_RUNGS,\n type Collection,\n} from \"@validation-os/core\";\nimport type { FieldKind } from \"./edit.js\";\n\n// The create form and the edit form speak the same field-kind vocabulary\n// (`FieldKind` lives in `edit.js`); the create-side spec adds `required` (a\n// blank blocks submit) and numeric `coerce` (a labelled numeric select → a\n// number), which the edit side doesn't need.\n\nexport interface FormField {\n /** Record field key (what the create payload uses). */\n key: string;\n /** Plain-language label a non-technical teammate reads. */\n label: string;\n kind: FieldKind;\n /** Options for a `select`. */\n options?: readonly string[];\n /** A `select`/`text` value that should be stored as a number. */\n coerce?: \"number\";\n required?: boolean;\n placeholder?: string;\n}\n\nconst ASSUMPTION_STATUS = [\"Draft\", \"Live\", \"Invalidated\"] as const;\nconst EXPERIMENT_STATUS = [\"Running\", \"Closed\"] as const;\nconst CLOSURE_REASON = [\"Completed\", \"Early-stop\", \"Kill\"] as const;\nconst GOAL_STATUS = [\"Draft\", \"Active\", \"Closed\"] as const;\nconst GOAL_OUTCOME = [\"Achieved\", \"Missed\", \"Dropped\"] as const;\nconst DECISION_STATUS = [\"Active\", \"Provisional\", \"Superseded\", \"Reversed\"] as const;\nconst GLOSSARY_STATUS = [\"Active\", \"Provisional\", \"Superseded\"] as const;\nconst RESULT = [\"Validated\", \"Invalidated\", \"Inconclusive\"] as const;\nconst MAGNITUDE = [\"Low\", \"Typical\", \"High\"] as const;\nconst FEASIBILITY = [\"High\", \"Medium\", \"Low\"] as const;\n/** The full evidence ladder, weakest first — the canonical runtime lists. */\nconst RUNGS = [...TESTING_RUNGS, ...GOAL_RUNG_VALUES] as const;\n/** Representativeness / Credibility picks, as labelled numeric options. */\nconst QUALITY = [\"1\", \"0.7\", \"0.5\"] as const;\n\nconst FIELDS: Record<Collection, FormField[]> = {\n assumptions: [\n { key: \"Title\", label: \"Assumption\", kind: \"text\", required: true },\n { key: \"Description\", label: \"Description\", kind: \"textarea\" },\n { key: \"Lens\", label: \"Lens\", kind: \"text\" },\n { key: \"Impact\", label: \"Impact (0–100)\", kind: \"number\" },\n { key: \"Status\", label: \"Status\", kind: \"select\", options: ASSUMPTION_STATUS },\n { key: \"5 Whys\", label: \"5 Whys\", kind: \"textarea\" },\n { key: \"Metric for truth\", label: \"Metric for truth\", kind: \"textarea\" },\n {\n key: \"Scoring justification\",\n label: \"Scoring justification\",\n kind: \"textarea\",\n },\n ],\n experiments: [\n { key: \"Title\", label: \"Experiment\", kind: \"text\", required: true },\n { key: \"Instrument\", label: \"Instrument\", kind: \"text\" },\n { key: \"Feasibility\", label: \"Feasibility\", kind: \"select\", options: FEASIBILITY },\n { key: \"Status\", label: \"Status\", kind: \"select\", options: EXPERIMENT_STATUS },\n {\n key: \"closureReason\",\n label: \"Closure reason\",\n kind: \"select\",\n options: CLOSURE_REASON,\n },\n { key: \"Date\", label: \"Date\", kind: \"text\", placeholder: \"YYYY-MM-DD\" },\n ],\n readings: [\n { key: \"Title\", label: \"Reading\", kind: \"text\", required: true },\n { key: \"Source\", label: \"Source\", kind: \"text\" },\n { key: \"Rung\", label: \"Rung\", kind: \"select\", options: RUNGS, required: true },\n { key: \"Result\", label: \"Result\", kind: \"select\", options: RESULT, required: true },\n {\n key: \"Representativeness\",\n label: \"Representativeness\",\n kind: \"select\",\n options: QUALITY,\n coerce: \"number\",\n },\n {\n key: \"Credibility\",\n label: \"Credibility\",\n kind: \"select\",\n options: QUALITY,\n coerce: \"number\",\n },\n {\n key: \"magnitudeBand\",\n label: \"Magnitude band\",\n kind: \"select\",\n options: MAGNITUDE,\n },\n { key: \"Date\", label: \"Date\", kind: \"text\", placeholder: \"YYYY-MM-DD\" },\n ],\n goals: [\n { key: \"Title\", label: \"Goal\", kind: \"text\", required: true },\n { key: \"Status\", label: \"Status\", kind: \"select\", options: GOAL_STATUS },\n { key: \"Outcome\", label: \"Outcome\", kind: \"select\", options: GOAL_OUTCOME },\n { key: \"Date\", label: \"Date\", kind: \"text\", placeholder: \"YYYY-MM-DD\" },\n ],\n decisions: [\n { key: \"Title\", label: \"Decision\", kind: \"text\", required: true },\n { key: \"Status\", label: \"Status\", kind: \"select\", options: DECISION_STATUS },\n ],\n glossary: [\n { key: \"Title\", label: \"Term\", kind: \"text\", required: true },\n { key: \"Status\", label: \"Status\", kind: \"select\", options: GLOSSARY_STATUS },\n ],\n people: [\n { key: \"Name\", label: \"Name\", kind: \"text\", required: true },\n { key: \"Role\", label: \"Role\", kind: \"text\" },\n { key: \"Segment\", label: \"Segment\", kind: \"text\" },\n ],\n};\n\n/** The editable fields for a register's create form, in display order. */\nexport function formFieldsFor(register: Collection): FormField[] {\n return FIELDS[register];\n}\n\n/** A blank draft: every field keyed to an empty string (form-friendly). */\nexport function emptyDraft(register: Collection): Record<string, string> {\n const draft: Record<string, string> = {};\n for (const f of formFieldsFor(register)) draft[f.key] = \"\";\n return draft;\n}\n\n/** Labels of required fields the draft has left blank (submit-gating). */\nexport function missingRequired(\n register: Collection,\n draft: Record<string, string>,\n): string[] {\n return formFieldsFor(register)\n .filter((f) => f.required && !String(draft[f.key] ?? \"\").trim())\n .map((f) => f.label);\n}\n\n/**\n * Turn a string-keyed form draft into a create payload: numbers coerced, blank\n * optional values dropped so the record stores only what was filled. Derived\n * and relation fields are never here — the server computes the former and\n * linking wires the latter.\n */\nexport function toCreatePayload(\n register: Collection,\n draft: Record<string, string>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const f of formFieldsFor(register)) {\n const raw = String(draft[f.key] ?? \"\").trim();\n if (raw === \"\") continue; // leave unfilled fields unset\n if (f.kind === \"number\" || f.coerce === \"number\") {\n const n = Number(raw);\n if (!Number.isNaN(n)) out[f.key] = n;\n } else {\n out[f.key] = raw;\n }\n }\n return out;\n}\n","/**\n * Shared class names for form controls, so the create form and the relation\n * editor render identical inputs (and any restyle happens in one place). These\n * are the package's own semantic classes, backed by the `styles.css` token\n * sheet — no host Tailwind.\n */\n\nexport const FIELD_LABEL_CLASS = \"vos-field-label\";\n\nexport const FIELD_CONTROL_CLASS = \"vos-input\";\n","import { useCallback, useState } from \"react\";\nimport type { AnyRecord, Collection, Relation } from \"@validation-os/core\";\n\n/**\n * Client write hooks — the create + link counterparts to `use-records`'\n * read hooks. Both POST through the Clerk-gated API (`POST {basePath}/{register}`\n * and `POST {basePath}/link`), so the browser never touches Firestore and the\n * server always recomputes derived fields. Each returns a `pending`/`error`\n * pair and an action that resolves to the result (or throws), so the caller can\n * refresh the list/record afterwards.\n */\n\n/** Pull the API's `{ data }` envelope, or throw its plain-language message. */\nasync function postJson<T>(url: string, body: unknown): Promise<T> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n const payload = (await res.json().catch(() => null)) as\n | { data?: T; message?: string; error?: string }\n | null;\n if (!res.ok) {\n const message =\n payload?.message ?? payload?.error ?? `Request failed (${res.status})`;\n throw new Error(message);\n }\n return (payload as { data: T }).data;\n}\n\nexport interface UseCreateResult {\n create: (data: Record<string, unknown>) => Promise<AnyRecord>;\n saving: boolean;\n error: string | null;\n}\n\n/** Create a record in `register`; the server stamps derived fields on write. */\nexport function useCreate(\n register: Collection,\n basePath = \"/api\",\n): UseCreateResult {\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const create = useCallback(\n async (data: Record<string, unknown>) => {\n setSaving(true);\n setError(null);\n try {\n return await postJson<AnyRecord>(`${basePath}/${register}`, data);\n } catch (e) {\n const message = e instanceof Error ? e.message : \"Failed to create\";\n setError(message);\n throw e;\n } finally {\n setSaving(false);\n }\n },\n [register, basePath],\n );\n\n return { create, saving, error };\n}\n\nexport interface LinkArgs {\n relation: Relation;\n from: { register: Collection; id: string };\n to: { register: Collection; id: string };\n}\n\nexport interface UseLinkResult {\n link: (args: LinkArgs) => Promise<void>;\n linking: boolean;\n error: string | null;\n}\n\n/** Wire a relation; the API sets both ends and recomputes derived fields. */\nexport function useLink(basePath = \"/api\"): UseLinkResult {\n const [linking, setLinking] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const link = useCallback(\n async (args: LinkArgs) => {\n setLinking(true);\n setError(null);\n try {\n await postJson<unknown>(`${basePath}/link`, args);\n } catch (e) {\n const message = e instanceof Error ? e.message : \"Failed to link\";\n setError(message);\n throw e;\n } finally {\n setLinking(false);\n }\n },\n [basePath],\n );\n\n return { link, linking, error };\n}\n","import { useMemo, useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\nimport { primaryLabel } from \"./columns.js\";\nimport { FIELD_CONTROL_CLASS } from \"./field-styles.js\";\nimport { linkChoicesFrom } from \"./link-choices.js\";\nimport { useList } from \"./use-records.js\";\nimport { useLink } from \"./use-mutations.js\";\n\nexport interface RelationEditorProps {\n /** The register of the open record initiating the link. */\n register: Collection;\n /** The open record's id (the `from` end). */\n recordId: string;\n basePath?: string;\n /** Called after a relation is wired, so the drawer can re-fetch. */\n onLinked: () => void;\n}\n\n/**\n * Wire a relation from the open record (spec user story 14). Pick an edge, then\n * a target record from the register that edge points at; linking sets both ends\n * server-side and recomputes derived fields. Registers with no outbound edges\n * (glossary, people) render nothing.\n */\nexport function RelationEditor({\n register,\n recordId,\n basePath,\n onLinked,\n}: RelationEditorProps) {\n const choices = useMemo(() => linkChoicesFrom(register), [register]);\n const [relation, setRelation] = useState(\"\");\n const [targetId, setTargetId] = useState(\"\");\n const { link, linking, error } = useLink(basePath);\n\n const active = choices.find((c) => c.relation === relation) ?? null;\n const { records } = useList(\n (active?.targetRegister ?? register) as Collection,\n basePath,\n );\n // Never offer to link a record to itself (self-referential registers).\n const targets = (records ?? []).filter(\n (r) => !(active?.targetRegister === register && r.id === recordId),\n );\n\n if (choices.length === 0) return null;\n\n const onLink = async () => {\n if (!active || !targetId || linking) return;\n try {\n await link({\n relation: active.relation,\n from: { register, id: recordId },\n to: { register: active.targetRegister, id: targetId },\n });\n setTargetId(\"\");\n setRelation(\"\");\n onLinked();\n } catch {\n // `error` carries the message; leave the picks in place to retry.\n }\n };\n\n return (\n <section className=\"vos-relation\">\n <h3 className=\"vos-sectitle\">Link a record</h3>\n <div className=\"vos-field-stack\">\n <select\n aria-label=\"Relation\"\n value={relation}\n onChange={(e) => {\n setRelation(e.target.value);\n setTargetId(\"\");\n }}\n className={FIELD_CONTROL_CLASS}\n >\n <option value=\"\">Choose a relation…</option>\n {choices.map((c) => (\n <option key={c.relation} value={c.relation}>\n {c.label}\n </option>\n ))}\n </select>\n\n {active ? (\n <select\n aria-label=\"Target record\"\n value={targetId}\n onChange={(e) => setTargetId(e.target.value)}\n className={FIELD_CONTROL_CLASS}\n >\n <option value=\"\">Choose a record…</option>\n {targets.map((r) => (\n <option key={r.id} value={r.id}>\n {primaryLabel(r)}\n </option>\n ))}\n </select>\n ) : null}\n\n {error ? <p className=\"vos-error\">{error}</p> : null}\n\n <button\n type=\"button\"\n onClick={onLink}\n disabled={!active || !targetId || linking}\n className=\"vos-btn vos-btn-sm\"\n style={{ alignSelf: \"flex-start\" }}\n >\n {linking ? \"Linking…\" : \"Link\"}\n </button>\n </div>\n </section>\n );\n}\n","/**\n * Which relations a record of a given register can initiate — the menu the\n * relation editor offers. Derived from `core`'s single `RELATIONS` table (so\n * the two never drift) and turned into plain-language choices, each naming the\n * register whose records are valid link targets.\n */\nimport { RELATIONS, type Collection, type Relation } from \"@validation-os/core\";\n\nexport interface LinkChoice {\n relation: Relation;\n /** Plain-language name of the edge, from the initiating record's side. */\n label: string;\n /** The register to pick a target record from. */\n targetRegister: Collection;\n}\n\n/** Plain-language label for each relation, read from the `from` side. */\nconst RELATION_LABEL: Record<Relation, string> = {\n \"assumption-reading\": \"Add reading\",\n \"assumption-depends-on\": \"Depends on\",\n \"assumption-contradicts\": \"Contradicts\",\n \"reading-experiment\": \"From experiment\",\n \"reading-goal\": \"From goal\",\n \"decision-based-on\": \"Based on assumption\",\n \"decision-resolves\": \"Resolves assumption\",\n \"goal-based-on\": \"Based on assumption\",\n};\n\n/** The relations a record of `register` can initiate, in table order. */\nexport function linkChoicesFrom(register: Collection): LinkChoice[] {\n return (Object.keys(RELATIONS) as Relation[])\n .filter((r) => RELATIONS[r].from.register === register)\n .map((relation) => ({\n relation,\n label: RELATION_LABEL[relation],\n targetRegister: RELATIONS[relation].targetRegister,\n }));\n}\n","import type { Collection } from \"@validation-os/core\";\nimport {\n REGISTER_GROUPS,\n REGISTER_ICON,\n REGISTER_LABEL,\n} from \"./labels.js\";\nimport { formatCount } from \"./primitives.js\";\nimport type { Counts } from \"./use-counts.js\";\n\nexport interface RegisterNavProps {\n /** The active register, highlighted with a clear active state (spec story 7). */\n active: Collection;\n /** Called when a register is chosen. */\n onSelect: (register: Collection) => void;\n /** Live per-register counts; a middle dot shows until they load. */\n counts?: Counts | null;\n /** Restrict/reorder the registers shown; defaults to all, grouped. */\n registers?: Collection[];\n}\n\n/**\n * The sidebar register nav — every register with its live count and an active\n * state, grouped into the register set and reference data (spec story 7). A\n * presentational brick: the caller owns which register is active and supplies\n * the counts. The assembled `<ValidationOSDashboard />` composes this; it's also\n * exported so anyone building their own surface can reuse it (the second level\n * of entry). Styled with the package's own token sheet — no host Tailwind.\n */\nexport function RegisterNav({\n active,\n onSelect,\n counts,\n registers,\n}: RegisterNavProps) {\n const groups = REGISTER_GROUPS.map((g) => ({\n ...g,\n registers: registers\n ? g.registers.filter((r) => registers.includes(r))\n : g.registers,\n })).filter((g) => g.registers.length > 0);\n\n return (\n <nav className=\"vos-nav\" aria-label=\"Registers\">\n {groups.map((group) => (\n <div key={group.label}>\n <div className=\"vos-nav-group\">{group.label}</div>\n {group.registers.map((register) => (\n <button\n key={register}\n type=\"button\"\n className={`vos-nav-item ${register === active ? \"is-active\" : \"\"}`}\n aria-current={register === active ? \"page\" : undefined}\n onClick={() => onSelect(register)}\n >\n <span className=\"vos-nav-ic\" aria-hidden=\"true\">\n {REGISTER_ICON[register]}\n </span>\n {REGISTER_LABEL[register]}\n <span className=\"vos-nav-count vos-num\">\n {counts?.[register] !== undefined\n ? formatCount(counts[register] ?? 0)\n : \"·\"}\n </span>\n </button>\n ))}\n </div>\n ))}\n </nav>\n );\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { Collection } from \"@validation-os/core\";\n\nexport type Counts = Partial<Record<Collection, number>>;\n\nexport interface UseCountsResult {\n counts: Counts | null;\n loading: boolean;\n error: string | null;\n refresh: () => void;\n}\n\n/**\n * Client hook: fetch per-register counts from the API (`GET {basePath}/counts`).\n * The API reads Firestore server-side through the adapter; this only speaks\n * HTTP, so no backend credentials ever reach the browser.\n */\nexport function useCounts(basePath = \"/api\"): UseCountsResult {\n const [counts, setCounts] = useState<Counts | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n let live = true;\n setLoading(true);\n fetch(`${basePath}/counts`)\n .then(async (res) => {\n if (!res.ok) throw new Error(`Counts request failed (${res.status})`);\n return (await res.json()) as { counts: Counts };\n })\n .then((body) => {\n if (!live) return;\n setCounts(body.counts);\n setError(null);\n })\n .catch((e: unknown) => {\n if (!live) return;\n setError(e instanceof Error ? e.message : \"Failed to load counts\");\n })\n .finally(() => {\n if (live) setLoading(false);\n });\n return () => {\n live = false;\n };\n }, [basePath, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n return { counts, loading, error, refresh };\n}\n","import type { Collection } from \"@validation-os/core\";\nimport { REGISTER_LABEL, REGISTER_ORDER } from \"./labels.js\";\nimport { StatTile } from \"./primitives-view.js\";\nimport type { Counts } from \"./use-counts.js\";\n\nexport interface RegisterCountsProps {\n counts: Counts;\n /** Optional caption under the tiles (e.g. the backend the numbers came from). */\n caption?: string;\n /** Optional click handler per register — makes each tile a nav button. */\n onSelect?: (register: Collection) => void;\n /** The active register, highlighted when tiles are nav. */\n active?: Collection | null;\n}\n\n/**\n * A glanceable grid of stat tiles — one per register, the register's row count\n * as the hero number. A brick kept for a counts landing; the assembled app\n * surfaces the same counts in the sidebar nav. Presentational: the caller reads\n * the counts (server-side, through the adapter) and hands them in. Rendered in\n * the package's own token sheet — no host Tailwind.\n */\nexport function RegisterCounts({\n counts,\n caption,\n onSelect,\n active,\n}: RegisterCountsProps) {\n const registers = REGISTER_ORDER.filter(\n (r): r is Collection => counts[r] !== undefined,\n );\n return (\n <section aria-label=\"Register counts\">\n <div className=\"vos-tile-grid\">\n {registers.map((register) => (\n <StatTile\n key={register}\n label={REGISTER_LABEL[register]}\n value={counts[register] ?? 0}\n onClick={onSelect ? () => onSelect(register) : undefined}\n active={active === register}\n />\n ))}\n </div>\n {caption ? <p className=\"vos-hint\" style={{ marginTop: 16 }}>{caption}</p> : null}\n </section>\n );\n}\n"],"mappings":";;;AAAA,SAAS,eAAAA,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;;;ACI1C,IAAM,iBAA6C;AAAA,EACxD,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AACV;AAIO,IAAM,oBAAgD;AAAA,EAC3D,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AACV;AAGO,IAAM,iBAA+B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,oBAAgD;AAAA,EAC3D,aACE;AAAA,EACF,aAAa;AAAA,EACb,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AACV;AAIO,IAAM,gBAA4C;AAAA,EACvD,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AACV;AAGO,IAAM,kBAAgE;AAAA,EAC3E;AAAA,IACE,OAAO;AAAA,IACP,WAAW,CAAC,eAAe,eAAe,YAAY,SAAS,aAAa,UAAU;AAAA,EACxF;AAAA,EACA,EAAE,OAAO,aAAa,WAAW,CAAC,QAAQ,EAAE;AAC9C;;;ACpEA,SAAS,YAAAC,iBAAgB;;;ACAzB,SAAS,WAAW,cAA8B;AAuC9C,mBAEE,KAFF;AArBG,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,WAAW,OAAuB,IAAI;AAE5C,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU,SAAQ;AAAA,IAClC;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,aAAS,SAAS,MAAM;AACxB,WAAO,MAAM,SAAS,oBAAoB,WAAW,KAAK;AAAA,EAC5D,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,MAAI,CAAC,KAAM,QAAO;AAElB,SACE,iCAEE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS;AAAA,QACT,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,cAAW;AAAA,QACX,cAAY;AAAA,QACZ,UAAU;AAAA,QACV,WAAU;AAAA,QAET;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;;;AC1BA,SAAS,aAAa,OAA0C;AAC9D,SAAO,CAAC,MAAO,EAAE,UAAkD,KAAK;AAC1E;AAOA,IAAM,UAA2C;AAAA,EAC/C,aAAa;AAAA,IACX,EAAE,KAAK,SAAS,QAAQ,SAAS;AAAA,IACjC;AAAA,MACE,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IACA,EAAE,KAAK,UAAU,QAAQ,UAAU,OAAO,QAAQ;AAAA,IAClD;AAAA,MACE,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU,aAAa,YAAY;AAAA,IACrC;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU,aAAa,MAAM;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,EAAE,KAAK,SAAS,QAAQ,aAAa;AAAA,IACrC,EAAE,KAAK,UAAU,QAAQ,UAAU,MAAM,SAAS;AAAA,IAClD,EAAE,KAAK,eAAe,QAAQ,cAAc;AAAA,EAC9C;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,SAAS,QAAQ,UAAU;AAAA,IAClC,EAAE,KAAK,UAAU,QAAQ,SAAS;AAAA,IAClC,EAAE,KAAK,QAAQ,QAAQ,OAAO;AAAA,IAC9B;AAAA,MACE,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,MACT,UAAU,aAAa,UAAU;AAAA,IACnC;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,EAAE,KAAK,SAAS,QAAQ,OAAO;AAAA,IAC/B,EAAE,KAAK,UAAU,QAAQ,UAAU,MAAM,SAAS;AAAA,IAClD,EAAE,KAAK,WAAW,QAAQ,UAAU;AAAA,EACtC;AAAA,EACA,WAAW;AAAA,IACT,EAAE,KAAK,SAAS,QAAQ,WAAW;AAAA,IACnC,EAAE,KAAK,UAAU,QAAQ,UAAU,MAAM,SAAS;AAAA,EACpD;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,SAAS,QAAQ,OAAO;AAAA,IAC/B,EAAE,KAAK,UAAU,QAAQ,UAAU,MAAM,SAAS;AAAA,EACpD;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,KAAK,QAAQ,QAAQ,OAAO;AAAA,IAC9B,EAAE,KAAK,QAAQ,QAAQ,OAAO;AAAA,IAC9B,EAAE,KAAK,WAAW,QAAQ,UAAU;AAAA,EACtC;AACF;AAGO,SAAS,WAAW,UAAmC;AAC5D,SAAO,QAAQ,QAAQ;AACzB;AAGO,SAAS,UAAU,QAAmB,QAA4B;AACvE,SAAO,OAAO,WAAW,OAAO,SAAS,MAAM,IAAI,OAAO,OAAO,GAAG;AACtE;AAGO,SAAS,YAAY,OAAwB;AAClD,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GAAI,QAAO;AAClE,MAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,QAAQ;AACvD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,SAAS,MAAM,IAAI,YAAY,EAAE,KAAK,IAAI,IAAI;AAAA,EAC7D;AACA,SAAO,aAAa,KAAK;AAC3B;AAEA,SAAS,aAAa,OAAwB;AAC5C,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC1D,SAAO,OAAO,KAAK;AACrB;AAGO,SAAS,aAAa,QAA2B;AACtD,QAAM,QAAQ,OAAO,SAAS,OAAO;AACrC,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,QAAQ,OAAO;AACpE;AAWA,IAAM,gBAAwC;AAAA,EAC5C,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,UAAU;AACZ;AAIA,IAAM,cAAsC;AAAA,EAC1C,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,MAAM;AACR;AAGO,SAAS,WAAW,KAAqB;AAC9C,QAAM,WAAW,YAAY,GAAG;AAChC,MAAI,SAAU,QAAO;AACrB,MAAI,SAAS,KAAK,GAAG,EAAG,QAAO;AAC/B,QAAM,SAAS,IAAI,QAAQ,sBAAsB,OAAO,EAAE,YAAY;AACtE,SAAO,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AACxD;AAGO,SAAS,aAAa,KAAqB;AAChD,SAAO,cAAc,GAAG,KAAK,WAAW,GAAG;AAC7C;;;AC9KA,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQM,SAAS,WAAW,QAAyC;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,IAAI,OAAO,KAAK,EAAE,YAAY;AACpC,MAAI,YAAY,IAAI,CAAC,EAAG,QAAO;AAC/B,MAAI,YAAY,IAAI,CAAC,EAAG,QAAO;AAC/B,MAAI,YAAY,IAAI,CAAC,EAAG,QAAO;AAC/B,SAAO;AACT;AAGO,IAAM,YAAY;AAClB,IAAM,YAAY;AAGlB,SAAS,UAAU,MAAoB;AAC5C,MAAI,QAAQ,UAAW,QAAO;AAC9B,MAAI,QAAQ,UAAW,QAAO;AAC9B,SAAO;AACT;AAGO,SAAS,aAAa,MAAsB;AACjD,MAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO;AACnC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AAC5C;AAGO,SAAS,eAAe,YAA0B;AACvD,SAAO,aAAa,IAAI,SAAS;AACnC;AAOO,SAAS,YAAY,OAAe,OAAqB;AAC9D,MAAI,UAAU,aAAc,QAAO,eAAe,KAAK;AACvD,MAAI,UAAU,OAAQ,QAAO,UAAU,KAAK;AAC5C,SAAO;AACT;AAOO,SAAS,cAAc,MAAoB;AAChD,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,OAAQ,QAAO;AAC5B,SAAO;AACT;AAGO,SAAS,aAAa,GAAmB;AAC9C,QAAM,IAAI,KAAK,MAAM,CAAC;AACtB,SAAO,IAAI,IAAI,IAAI,CAAC,KAAK,OAAO,CAAC;AACnC;AAGO,SAAS,YAAY,GAAmB;AAC7C,SAAO,EAAE,eAAe;AAC1B;AASO,SAAS,cACd,QACA,OACA,QACA,KACA,KACQ;AACR,MAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAM,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC;AACvC,QAAM,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC;AACvC,QAAM,OAAO,KAAK,MAAM;AACxB,QAAM,QAAQ;AACd,SAAO,OACJ,IAAI,CAAC,GAAG,MAAM;AACb,UAAM,IAAK,KAAK,OAAO,SAAS,MAAO,QAAQ,QAAQ,KAAK;AAC5D,UAAM,IAAI,SAAS,SAAU,IAAI,MAAM,QAAS,SAAS,QAAQ;AACjE,WAAO,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,EACxD,CAAC,EACA,KAAK,GAAG;AACb;AAIO,SAAS,WACd,OACA,QACA,IACA,IACQ;AACR,QAAM,OAAO,KAAK,MAAM;AACxB,QAAM,QAAQ;AACd,SAAO,SAAS,SAAU,QAAQ,MAAM,QAAS,SAAS,QAAQ;AACpE;;;ACtHsB,SA2KlB,YAAAC,WA3KkB,OAAAC,MA2BlB,QAAAC,aA3BkB;AAVtB,IAAM,aAAmC;AAAA,EACvC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AAGO,SAAS,WAAW,EAAE,OAAO,GAA0C;AAC5E,MAAI,CAAC,OAAQ,QAAO,gBAAAD,KAAC,UAAK,WAAU,aAAY,oBAAC;AACjD,SAAO,gBAAAA,KAAC,UAAK,WAAW,WAAW,WAAW,MAAM,CAAC,GAAI,kBAAO;AAClE;AAEA,IAAM,aAAmC;AAAA,EACvC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AACA,IAAM,aAAmC;AAAA,EACvC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AAMO,SAAS,QAAQ,EAAE,KAAK,GAAqB;AAClD,QAAM,QAAQ,UAAU,IAAI;AAC5B,QAAM,MAAM,KAAK,MAAM,aAAa,IAAI,IAAI,GAAG;AAC/C,SACE,gBAAAC,MAAC,UAAK,WAAU,mBACd;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAY,QAAQ,KAAK,MAAM,IAAI,CAAC;AAAA,QAEpC,0BAAAA,KAAC,OAAE,WAAW,WAAW,KAAK,GAAG,OAAO,EAAE,OAAO,GAAG,GAAG,IAAI,GAAG;AAAA;AAAA,IAChE;AAAA,IACA,gBAAAA,KAAC,OAAE,WAAW,kBAAkB,WAAW,KAAK,CAAC,IAAK,eAAK,MAAM,IAAI,GAAE;AAAA,KACzE;AAEJ;AAUO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAGG;AACD,QAAM,OAAO,eAAe,UAAU;AACtC,SACE,gBAAAC,MAAC,UAAK,WAAU,mBACb;AAAA,eAAW,QAAQ,UAAU,IAC5B,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA;AAAA,IACF,IACE;AAAA,IACJ,gBAAAA,KAAC,OAAE,WAAW,kBAAkB,WAAW,IAAI,CAAC,IAC7C,uBAAa,UAAU,GAC1B;AAAA,KACF;AAEJ;AAEA,IAAM,aAAmC;AAAA,EACvC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AAQO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,QAAQ;AAAA,EACR,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP;AACF,GASG;AACD,QAAM,IAAI,cAAc,QAAQ,OAAO,QAAQ,KAAK,GAAG;AACvD,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC;AACvC,QAAM,KAAK,OAAO,KAAK,IAAI,GAAG,QAAQ,CAAC;AACvC,QAAM,SAAS,WAAW,IAAI;AAC9B,QAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAQ,WAAW,MAAM,QAAQ,IAAI,EAAE;AAC7C,QAAM,QAAQ,WAAW,GAAG,QAAQ,IAAI,EAAE;AAC1C,QAAM,eAAe,KAAK,KAAK,KAAK;AACpC,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,SAAS,OAAO,KAAK,IAAI,MAAM;AAAA,MAC/B,qBAAoB;AAAA,MACpB,MAAK;AAAA,MACL,cAAY,aAAa,cAAc,aAAa,IAAI,CAAC;AAAA,MAExD;AAAA,eACC,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,MAAM,QAAQ,MAAM;AAAA,YAC9C,MAAM;AAAA,YACN,SAAQ;AAAA;AAAA,QACV,IACE;AAAA,QACH,eACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,IAAI;AAAA,YACJ,IAAI,QAAQ;AAAA,YACZ,IAAI;AAAA,YACJ,IAAI;AAAA,YACJ,QAAO;AAAA,YACP,aAAa;AAAA,YACb,iBAAgB;AAAA;AAAA,QAClB,IACE;AAAA,QACJ,gBAAAA,KAAC,UAAK,GAAM,MAAK,QAAO,QAAgB,aAAa,GAAG;AAAA,QACxD,gBAAAA,KAAC,YAAO,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG,MAAM,QAAQ;AAAA;AAAA;AAAA,EACpD;AAEJ;AAOO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,OACJ,gBAAAC,MAAAF,WAAA,EACE;AAAA,oBAAAC,KAAC,SAAI,WAAU,kBAAkB,iBAAM;AAAA,IACvC,gBAAAA,KAAC,SAAI,WAAU,kBAAkB,sBAAY,KAAK,GAAE;AAAA,IACnD,MAAM,gBAAAA,KAAC,SAAI,WAAU,gBAAgB,eAAI,IAAS;AAAA,KACrD;AAEF,MAAI,SAAS;AACX,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV;AAAA,QACA,gBAAc;AAAA,QAEb;AAAA;AAAA,IACH;AAAA,EAEJ;AACA,SAAO,gBAAAA,KAAC,SAAI,WAAU,YAAY,gBAAK;AACzC;;;ACxLW,gBAAAE,MAKL,QAAAC,aALK;AATJ,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,UAAU,WAAW,QAAQ;AAEnC,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,gBAAAD,KAAC,OAAE,WAAU,aAAY,6BAAe;AAAA,EACjD;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAU,6BACb,0BAAAC,MAAC,WAAM,WAAU,aACf;AAAA,oBAAAD,KAAC,WACC,0BAAAA,KAAC,QACE,kBAAQ,IAAI,CAAC,MACZ,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,OAAM;AAAA,QACN,WAAW,EAAE,UAAU,UAAU,UAAU;AAAA,QAE1C,YAAE;AAAA;AAAA,MAJE,EAAE;AAAA,IAKT,CACD,GACH,GACF;AAAA,IACA,gBAAAA,KAAC,WACE,kBAAQ,IAAI,CAAC,WAAW;AACvB,YAAM,aAAa,OAAO,OAAO;AACjC,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,SAAS,MAAM,aAAa,OAAO,EAAE;AAAA,UACrC,WACE,aACI,CAAC,MAAM;AACL,gBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,gBAAE,eAAe;AACjB,yBAAW,OAAO,EAAE;AAAA,YACtB;AAAA,UACF,IACA;AAAA,UAEN,UAAU,aAAa,IAAI;AAAA,UAC3B,iBAAe;AAAA,UACf,WAAW,aAAa,gBAAgB;AAAA,UAEvC,kBAAQ,IAAI,CAAC,GAAG,MACf,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW,EAAE,UAAU,UAAU,UAAU;AAAA,cAE3C,0BAAAA,KAAC,QAAK,QAAQ,GAAG,QAAgB,UAAU,MAAM,GAAG;AAAA;AAAA,YAH/C,EAAE;AAAA,UAIT,CACD;AAAA;AAAA,QAvBI,OAAO;AAAA,MAwBd;AAAA,IAEJ,CAAC,GACH;AAAA,KACF,GACF;AAEJ;AAIA,SAAS,KAAK;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,MAAM,UAAU,QAAQ,MAAM;AAEpC,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,gBAAAA,KAAC,cAAW,QAAQ,OAAO,OAAO,OAAO,OAAO,GAAG,GAAG;AAAA,EAC/D;AACA,MAAI,OAAO,SAAS,QAAQ;AAC1B,WAAO,OAAO,QAAQ,WACpB,gBAAAA,KAAC,WAAQ,MAAM,KAAK,IAEpB,gBAAAA,KAAC,UAAK,WAAU,aAAY,oBAAC;AAAA,EAEjC;AACA,MAAI,OAAO,SAAS,cAAc;AAChC,WAAO,OAAO,QAAQ,WACpB,gBAAAA,KAAC,kBAAe,YAAY,KAAK,IAEjC,gBAAAA,KAAC,UAAK,WAAU,aAAY,oBAAC;AAAA,EAEjC;AAEA,QAAM,OACJ,aAAa,QAAQ,QAAQ,QAAQ,UAAa,QAAQ,MACtD,aAAa,MAAM,IACnB,YAAY,GAAG;AACrB,SAAO,gBAAAA,KAAC,UAAK,WAAW,WAAW,YAAY,QAAY,gBAAK;AAClE;;;ACjIA,SAAS,aAAAE,YAAW,YAAAC,iBAAgC;;;ACe7C,IAAM,mBACX;AAiBF,IAAM,IAAI,CAAC,KAAa,WAAgC,EAAE,KAAK,OAAO,MAAM,OAAO;AACnF,IAAM,OAAO,CAAC,KAAa,WAAgC;AAAA,EACzD;AAAA,EACA;AAAA,EACA,MAAM;AACR;AACA,IAAM,MAAM,CAAC,KAAa,WAAgC;AAAA,EACxD;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,UAAU;AACZ;AACA,IAAM,MAAM,CACV,KACA,OACA,SACA,WAAW,WACM,EAAE,KAAK,OAAO,MAAM,UAAU,SAAS,SAAS;AAEnE,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,iBAAiB,CAAC,KAAK,OAAO,KAAK;AAOzC,IAAM,UAA6C;AAAA,EACjD,aAAa;AAAA,IACX,EAAE,SAAS,YAAY;AAAA,IACvB,KAAK,eAAe,aAAa;AAAA,IACjC,IAAI,UAAU,QAAQ;AAAA,IACtB,IAAI,UAAU,UAAU,CAAC,SAAS,QAAQ,aAAa,CAAC;AAAA,IACxD,EAAE,QAAQ,MAAM;AAAA,IAChB,KAAK,UAAU,QAAQ;AAAA,IACvB,KAAK,oBAAoB,kBAAkB;AAAA,IAC3C,KAAK,yBAAyB,uBAAuB;AAAA;AAAA;AAAA,EAGvD;AAAA,EACA,aAAa;AAAA,IACX,EAAE,SAAS,YAAY;AAAA,IACvB,EAAE,cAAc,YAAY;AAAA,IAC5B,IAAI,eAAe,eAAe,CAAC,QAAQ,UAAU,KAAK,GAAG,IAAI;AAAA,IACjE,IAAI,UAAU,UAAU,CAAC,WAAW,QAAQ,CAAC;AAAA,IAC7C;AAAA,MACE;AAAA,MACA;AAAA,MACA,CAAC,aAAa,cAAc,MAAM;AAAA,MAClC;AAAA,IACF;AAAA,IACA,EAAE,QAAQ,MAAM;AAAA,EAClB;AAAA,EACA,UAAU;AAAA,IACR,EAAE,SAAS,SAAS;AAAA,IACpB,EAAE,UAAU,QAAQ;AAAA,IACpB,IAAI,QAAQ,QAAQ,aAAa;AAAA,IACjC,IAAI,UAAU,UAAU,CAAC,aAAa,eAAe,cAAc,CAAC;AAAA,IACpE,IAAI,sBAAsB,sBAAsB,cAAc;AAAA,IAC9D,IAAI,eAAe,eAAe,cAAc;AAAA,IAChD,IAAI,iBAAiB,kBAAkB,CAAC,OAAO,WAAW,MAAM,GAAG,IAAI;AAAA,IACvE,EAAE,QAAQ,MAAM;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,EAAE,SAAS,MAAM;AAAA,IACjB,IAAI,UAAU,UAAU,CAAC,SAAS,UAAU,QAAQ,CAAC;AAAA,IACrD,IAAI,WAAW,WAAW,CAAC,YAAY,UAAU,SAAS,GAAG,IAAI;AAAA,IACjE,EAAE,QAAQ,MAAM;AAAA,EAClB;AAAA,EACA,WAAW;AAAA,IACT,EAAE,SAAS,UAAU;AAAA,IACrB,IAAI,UAAU,UAAU,CAAC,UAAU,eAAe,cAAc,UAAU,CAAC;AAAA,EAC7E;AAAA,EACA,UAAU;AAAA,IACR,EAAE,SAAS,MAAM;AAAA,IACjB,IAAI,UAAU,UAAU,CAAC,UAAU,eAAe,YAAY,CAAC;AAAA,EACjE;AAAA,EACA,QAAQ,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,EAAE,WAAW,SAAS,CAAC;AACxE;AAGO,SAAS,eAAe,UAAqC;AAClE,SAAO,QAAQ,QAAQ;AACzB;AAOO,SAAS,UAAU,UAAsB,QAA0B;AACxE,QAAM,QAAe,CAAC;AACtB,aAAW,KAAK,eAAe,QAAQ,GAAG;AACxC,UAAM,QAAQ,OAAO,EAAE,GAAG;AAC1B,UAAM,EAAE,GAAG,IAAI,UAAU,QAAQ,UAAU,SAAY,KAAK,OAAO,KAAK;AAAA,EAC1E;AACA,SAAO;AACT;AAGA,SAAS,OAAO,OAAoB,KAAsB;AACxD,QAAMC,OAAM,OAAO,GAAG;AACtB,MAAI,MAAM,SAAS,UAAU;AAC3B,QAAIA,KAAI,KAAK,MAAM,GAAI,QAAO;AAC9B,UAAM,IAAI,OAAOA,IAAG;AACpB,WAAO,OAAO,MAAM,CAAC,IAAI,OAAO;AAAA,EAClC;AAEA,MAAIA,SAAQ,OAAO,MAAM,SAAS,YAAY,MAAM,UAAW,QAAO;AACtE,SAAOA;AACT;AAGA,SAAS,KAAK,OAAyB;AACrC,SAAO,UAAU,UAAa,UAAU,KAAK,OAAO;AACtD;AAOO,SAAS,WACd,UACA,UACA,OACyB;AACzB,QAAM,QAAiC,EAAE,SAAS,SAAS,QAAQ;AACnE,aAAW,SAAS,eAAe,QAAQ,GAAG;AAC5C,UAAM,OAAO,OAAO,OAAO,MAAM,MAAM,GAAG,KAAK,EAAE;AACjD,QAAI,KAAK,IAAI,MAAM,KAAK,SAAS,MAAM,GAAG,CAAC,EAAG,OAAM,MAAM,GAAG,IAAI;AAAA,EACnE;AACA,SAAO;AACT;AAGO,SAAS,SACd,UACA,UACA,OACS;AACT,SAAO,OAAO,KAAK,WAAW,UAAU,UAAU,KAAK,CAAC,EAAE,SAAS;AACrE;;;ACxLA,SAAS,aAAa,aAAAC,YAAW,gBAAgB;AAkBjD,SAAS,SAAY,MAAkB;AACrC,SAAQ,KAAqB;AAC/B;AAQA,SAAS,gBAAmB,KAE1B;AACA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB;AAAA,IAChD,MAAM;AAAA,IACN,SAAS,QAAQ;AAAA,IACjB,OAAO;AAAA,EACT,CAAC;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,CAAC;AAElC,EAAAC,WAAU,MAAM;AACd,QAAI,QAAQ,MAAM;AAChB,eAAS,EAAE,MAAM,MAAM,SAAS,OAAO,OAAO,KAAK,CAAC;AACpD;AAAA,IACF;AACA,QAAI,OAAO;AACX,aAAS,CAAC,OAAO,EAAE,GAAG,GAAG,SAAS,KAAK,EAAE;AACzC,UAAM,GAAG,EACN,KAAK,OAAO,QAAQ;AACnB,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,cAAc,GAAG,YAAY,IAAI,MAAM,GAAG;AACvE,aAAO,SAAY,MAAM,IAAI,KAAK,CAAC;AAAA,IACrC,CAAC,EACA,KAAK,CAAC,SAAS,QAAQ,SAAS,EAAE,MAAM,SAAS,OAAO,OAAO,KAAK,CAAC,CAAC,EACtE;AAAA,MACC,CAAC,MACC,QACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,aAAa,QAAQ,EAAE,UAAU;AAAA,MAC1C,CAAC;AAAA,IACL;AACF,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,KAAK,IAAI,CAAC;AAEd,QAAM,UAAU,YAAY,MAAM,QAAQ,CAACC,OAAMA,KAAI,CAAC,GAAG,CAAC,CAAC;AAC3D,SAAO,EAAE,GAAG,OAAO,QAAQ;AAC7B;AAUO,SAAS,QAAQ,UAAsB,WAAW,QAAuB;AAC9E,QAAM,EAAE,MAAM,SAAS,OAAO,QAAQ,IAAI;AAAA,IACxC,GAAG,QAAQ,IAAI,QAAQ;AAAA,EACzB;AACA,SAAO,EAAE,SAAS,MAAM,SAAS,OAAO,QAAQ;AAClD;AAgBO,SAAS,UACd,UACA,IACA,WAAW,QACM;AACjB,QAAM,MAAM,KACR,GAAG,QAAQ,IAAI,QAAQ,IAAI,mBAAmB,EAAE,CAAC,KACjD;AACJ,QAAM,EAAE,MAAM,SAAS,OAAO,QAAQ,IAAI,gBAA2B,GAAG;AACxE,SAAO,EAAE,QAAQ,MAAM,SAAS,OAAO,QAAQ;AACjD;AAQA,IAAM,cAAc;AAQb,SAAS,cAAc,QAAgB,MAA2B;AACvE,MAAI,UAAU,OAAO,SAAS,KAAK;AACjC,WAAO,EAAE,IAAI,MAAM,QAAQ,SAAoB,IAAI,EAAE;AAAA,EACvD;AACA,QAAM,UAAW,MAAuC;AACxD,QAAM,OAAO,OAAO,YAAY,WAAW,UAAU;AACrD,MAAI,WAAW,KAAK;AAClB,WAAO,EAAE,IAAI,OAAO,UAAU,MAAM,SAAS,QAAQ,iBAAiB;AAAA,EACxE;AACA,SAAO,EAAE,IAAI,OAAO,UAAU,OAAO,SAAS,QAAQ,YAAY;AACpE;AAsBO,SAAS,UACd,UACA,WAAW,QACM;AACjB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAC5D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,OAAO;AAAA,IACX,OAAO,IAAY,UAAwD;AACzE,gBAAU,IAAI;AACd,kBAAY,IAAI;AAChB,eAAS,IAAI;AACb,UAAI;AACF,cAAM,MAAM,MAAM;AAAA,UAChB,GAAG,QAAQ,IAAI,QAAQ,IAAI,mBAAmB,EAAE,CAAC;AAAA,UACjD;AAAA,YACE,QAAQ;AAAA,YACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,YAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,UAC5B;AAAA,QACF;AACA,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9C,cAAM,SAAS,cAAc,IAAI,QAAQ,IAAI;AAC7C,YAAI,CAAC,OAAO,MAAM,OAAO,SAAU,aAAY,OAAO,OAAO;AAAA,iBACpD,CAAC,OAAO,GAAI,UAAS,OAAO,OAAO;AAC5C,eAAO;AAAA,MACT,SAAS,GAAG;AACV,cAAM,UACJ,aAAa,QAAQ,EAAE,UAAU;AACnC,iBAAS,OAAO;AAChB,eAAO,EAAE,IAAI,OAAO,UAAU,OAAO,QAAQ;AAAA,MAC/C,UAAE;AACA,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,IACA,CAAC,UAAU,QAAQ;AAAA,EACrB;AAEA,QAAM,QAAQ,YAAY,MAAM;AAC9B,gBAAY,IAAI;AAChB,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,MAAM,QAAQ,UAAU,OAAO,MAAM;AAChD;;;AC/LA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AA2CP,SAAS,IAAI,GAA2B;AACtC,SAAO,OAAO,MAAM,YAAY,MAAM,KAAK,IAAI;AACjD;AAGA,SAAS,gBAAgB,KAAgB,cAA+B;AACtE,QAAM,OAAO,IAAI;AACjB,MAAI,MAAM,KAAK,CAAC,MAAM,EAAE,iBAAiB,YAAY,EAAG,QAAO;AAC/D,QAAM,MAAM,IAAI;AAChB,SAAO,KAAK,SAAS,YAAY,KAAK;AACxC;AAEO,SAAS,mBACd,YACA,UACA,aACe;AACf,QAAM,OAAO,SAAS,OAAO,CAAC,MAAM,EAAE,iBAAiB,WAAW,EAAE;AACpE,QAAM,SAAS,KAAK,IAAI,cAAc;AACtC,QAAM,EAAE,YAAY,OAAO,IAAI,sBAAsB,MAAM;AAE3D,QAAM,kBAAkB,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACjE,QAAM,oBAAoB,IAAI;AAAA,IAC5B,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,cAAe,CAAC,CAAC;AAAA,EAC/E;AAKA,QAAM,gBAAgB,oBAAI,IAAY;AAAA,IACpC,GAAG,YAAY,OAAO,CAAC,MAAM,gBAAgB,GAAG,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,IAC/E,GAAG,kBAAkB,KAAK;AAAA,EAC5B,CAAC;AAED,QAAM,kBAAoC,CAAC,GAAG,aAAa,EAAE,IAAI,CAAC,OAAO;AACvE,UAAM,MAAM,gBAAgB,IAAI,EAAE;AAClC,UAAM,QAAQ,kBAAkB,IAAI,EAAE;AACtC,UAAM,OAAQ,KAAK,YAAsC,CAAC;AAC1D,UAAM,WAAW,KAAK,SAAS,mBAAmB,IAAI,IAAI;AAC1D,UAAM,SAAS,MAAM,IAAI,IAAI,MAAM,IAAI;AACvC,WAAO;AAAA,MACL,cAAc;AAAA,MACd,OAAO,MAAM,IAAI,IAAI,KAAK,IAAI;AAAA,MAC9B;AAAA,MACA,cAAc,OAAO,gBAAgB;AAAA,MACrC,WAAW,OAAO,aAAa;AAAA,MAC/B,cAAc,OAAO,gBAAgB;AAAA,MACrC;AAAA,MACA,MAAM,WAAW,YAAY,UAAU,cAAc;AAAA,IACvD;AAAA,EACF,CAAC;AAED,kBAAgB;AAAA,IACd,CAAC,GAAG,MACF,EAAE,YAAY,EAAE,aAChB,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,KAC9B,EAAE,aAAa,cAAc,EAAE,YAAY;AAAA,EAC/C;AAEA,QAAM,cAA4B,OAC/B,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,EACrC,IAAI,CAAC,OAAO;AAAA,IACX,KAAK,EAAE;AAAA,IACP,MAAM,EAAE;AAAA,IACR,QAAQ,EAAE;AAAA,IACV,cAAc,EAAE;AAAA,IAChB,WAAW,EAAE;AAAA,IACb,cAAc,EAAE;AAAA,EAClB,EAAE;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA,YAAY,qBAAqB,MAAM;AAAA,IACvC,cAAc,OAAO,OAAO,CAAC,MAAM,YAAY,EAAE,MAAM,CAAC,EAAE;AAAA,EAC5D;AACF;;;AC9GW,SA6BP,YAAAC,WA7BO,OAAAC,MA+BH,QAAAC,aA/BG;AAXJ,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGG;AACD,QAAM,WAAW,QAAQ,YAAY,QAAQ;AAC7C,QAAM,cAAc,QAAQ,eAAe,QAAQ;AAEnD,MAAI,SAAS,WAAW,YAAY,SAAS;AAC3C,WAAO,gBAAAD,KAAC,SAAM,qDAAkC;AAAA,EAClD;AACA,MAAI,SAAS,SAAS,YAAY,OAAO;AACvC,WAAO,gBAAAA,KAAC,SAAM,4DAA8C;AAAA,EAC9D;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,IACA,SAAS,WAAW,CAAC;AAAA,IACrB,YAAY,WAAW,CAAC;AAAA,EAC1B;AAEA,MAAI,EAAE,YAAY,WAAW,KAAK,EAAE,YAAY,WAAW,GAAG;AAC5D,WACE,gBAAAA,KAAC,SAAM,0GAGP;AAAA,EAEJ;AAGA,QAAM,eAAe,KAAK;AAAA,IACxB,GAAG,EAAE,YAAY,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,IACvC,GAAG,EAAE,YAAY,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,IACvC;AAAA,EACF;AAEA,SACE,gBAAAC,MAAAF,WAAA,EACG;AAAA,MAAE,YAAY,SACb,gBAAAE,MAAC,aACC;AAAA,sBAAAD,KAAC,SAAI,WAAU,yBAAwB,sCAAwB;AAAA,MAC9D,EAAE,YAAY,IAAI,CAAC,MAClB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,EAAE,SAAS,cAAc,EAAE,YAAY;AAAA,UAC9C,MAAM,iBAAiB,CAAC;AAAA,UACxB,cAAc,EAAE;AAAA,UAChB,WAAW,EAAE;AAAA,UACb,KAAK;AAAA,UACL,MAAM,EAAE;AAAA;AAAA,QANH,EAAE;AAAA,MAOT,CACD;AAAA,OACH,IACE;AAAA,IAEH,EAAE,YAAY,SACb,gBAAAC,MAAC,aACC;AAAA,sBAAAD,KAAC,SAAI,WAAU,yBAAwB,4BAAc;AAAA,MACpD,EAAE,YAAY,IAAI,CAAC,MAClB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,gBAAgB,CAAC;AAAA,UACxB,cAAc,EAAE;AAAA,UAChB,WAAW,EAAE;AAAA,UACb,KAAK;AAAA;AAAA,QAJA,EAAE;AAAA,MAKT,CACD;AAAA,OACH,IACE;AAAA,IAEJ,gBAAAA,KAAC,cAAW,QAAQ,EAAE,YAAY;AAAA,KACpC;AAEJ;AAIA,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,KAAK,gBAAgB;AAC3B,QAAM,SAAS,YAAY;AAC3B,QAAM,QAAQ,KAAK,MAAO,YAAY,MAAO,EAAE;AAC/C,QAAM,OAAO,KACT,EAAE,MAAM,OAAO,OAAO,GAAG,KAAK,KAAK,YAAY,kBAAkB,IACjE,EAAE,OAAO,OAAO,OAAO,GAAG,KAAK,KAAK,YAAY,kBAAkB;AACtE,SACE,gBAAAC,MAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,KAAC,UAAK,WAAU,kBAAkB,iBAAM;AAAA,IACvC,OACC,gBAAAA,KAAC,UAAK,WAAW,kBAAkB,OAAO,kBAAkB,eAAe,IACxE,gBACH,IACE;AAAA,IACJ,gBAAAA,KAAC,UAAK,WAAU,wBACb,mBAAS,gBAAAA,KAAC,OAAE,OAAO,MAAM,IAAK,MACjC;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,KAAK,oBAAoB,kBAAkB;AAAA,QAE1D,mBAAS,aAAa,YAAY,IAAI;AAAA;AAAA,IACzC;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW,EAAE,OAAO,GAAkC;AAC7D,MAAI,OAAO,SAAS,GAAG;AACrB,WACE,gBAAAA,KAAC,OAAE,WAAU,YACV,iBAAO,WAAW,IACf,8CAAyC,aAAa,OAAO,CAAC,EAAG,UAAU,CAAC,OAAO,OAAO,CAAC,EAAG,IAAI,MAClG,gDACN;AAAA,EAEJ;AACA,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAM,SAAS,OAAO,IAAI,CAAC,MAAM,EAAE,UAAU;AAC7C,SACE,gBAAAC,MAAC,SAAI,WAAU,YACb;AAAA,oBAAAD,KAAC,SAAI,WAAU,iBACb,0BAAAA,KAAC,UAAK,WAAU,WAAU,kCAAoB,GAChD;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM,eAAe,KAAK,UAAU;AAAA,QACpC,MAAI;AAAA,QACJ,WAAW,yBAAyB,aAAa,MAAM,UAAU,CAAC,OAAO,aAAa,KAAK,UAAU,CAAC;AAAA;AAAA,IACxG;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAU,iBACb;AAAA,sBAAAD,KAAC,UAAM,gBAAM,MAAK;AAAA,MAClB,gBAAAC,MAAC,UAAK,WAAU,WAAU;AAAA;AAAA,QAAK,aAAa,KAAK,UAAU;AAAA,SAAE;AAAA,OAC/D;AAAA,KACF;AAEJ;AAEA,SAAS,iBAAiB,GAA2B;AACnD,QAAM,WACJ,EAAE,iBAAiB,IACf,oBACA,GAAG,EAAE,YAAY,WAAW,EAAE,iBAAiB,IAAI,KAAK,GAAG;AACjE,QAAM,IAAI,EAAE;AACZ,MAAI,EAAE,MAAM;AACV,WAAO,IACH,kBAAe,EAAE,KAAK,OAAO,EAAE,KAAK,kBACpC,kBAAe,QAAQ;AAAA,EAC7B;AACA,MAAI,CAAC,KAAK,EAAE,UAAU,EAAG,QAAO,GAAG,QAAQ;AAC3C,SAAO,GAAG,QAAQ,SAAM,EAAE,OAAO,OAAO,EAAE,KAAK,sBAAmB,EAAE,IAAI;AAC1E;AAEA,SAAS,gBAAgB,GAAuB;AAC9C,MAAI,EAAE,SAAS,OAAQ,QAAO,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK;AAC5D,SAAO,EAAE,iBAAiB,IAAI,qBAAqB;AACrD;AAEA,SAAS,MAAM,EAAE,SAAS,GAA4B;AACpD,SAAO,gBAAAD,KAAC,OAAE,WAAU,YAAY,UAAS;AAC3C;;;AJpDQ,SAoCE,YAAAE,WAnCA,OAAAC,MADF,QAAAC,aAAA;AAlHR,IAAM,cAAc,oBAAI,IAAI,CAAC,MAAM,WAAW,aAAa,aAAa,SAAS,CAAC;AAGlF,IAAM,cAAsC;AAAA,EAC1C,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,eAAe;AACjB;AAaO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAgB,CAAC,CAAC;AAK5C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAA2B,IAAI;AAC/D,QAAM,CAAC,KAAK,MAAM,IAAIA,UAAS,KAAK;AACpC,QAAM,EAAE,MAAM,QAAQ,UAAU,OAAO,WAAW,MAAM,IAAI;AAAA,IAC1D;AAAA,IACA;AAAA,EACF;AAGA,QAAM,WAAW,QAAQ,MAAM;AAC/B,EAAAC,WAAU,MAAM;AACd,eAAW,KAAK;AAChB,gBAAY,IAAI;AAChB,WAAO,KAAK;AACZ,UAAM;AAAA,EACR,GAAG,CAAC,UAAU,KAAK,CAAC;AAEpB,QAAM,UACJ,UAAU,OAAO,WAAW,OAAO,OAAO,YAAY,WACjD,OAAO,UACR;AAEN,QAAM,SAAS,SACX,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,IACrD,CAAC;AAEL,WAAS,eAAe;AACtB,QAAI,CAAC,OAAQ;AACb,gBAAY,MAAM;AAClB,aAAS,UAAU,UAAU,MAAM,CAAC;AACpC,UAAM;AACN,eAAW,IAAI;AAAA,EACjB;AAEA,WAAS,gBAAgB;AACvB,eAAW,KAAK;AAChB,UAAM;AAAA,EACR;AAEA,iBAAe,SAAS;AACtB,QAAI,CAAC,UAAU,CAAC,SAAU;AAG1B,UAAM,QAAQ,WAAW,UAAU,UAAU,KAAK;AAClD,UAAM,UAAU,OAAO;AACvB,QAAI,OAAO,KAAK,KAAK,EAAE,UAAU,GAAG;AAClC,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,UAAM,SAAS,MAAM,KAAK,OAAO,IAAI,KAAK;AAC1C,QAAI,OAAO,IAAI;AACb,iBAAW,KAAK;AAChB,kBAAY;AAAA,IACd;AAAA,EAGF;AAEA,WAAS,eAAe;AACtB,UAAM;AAGN,gBAAY;AAAA,EACd;AAEA,QAAM,WAAW,CAAC,KAAa,UAC7B,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,EAAE;AAE1C,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,WAAW,GAAG,eAAe,QAAQ,CAAC;AAAA,MAEtC;AAAA,wBAAAA,MAAC,YAAO,WAAU,qBAChB;AAAA,0BAAAA,MAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,GACjC;AAAA,4BAAAD,KAAC,OAAE,WAAU,sBAAsB,yBAAe,QAAQ,GAAE;AAAA,YAC5D,gBAAAA,KAAC,QAAG,WAAU,oBACX,mBAAS,aAAa,MAAM,IAAI,UAAU,kBAAa,UAC1D;AAAA,aACF;AAAA,UACC,SACC,gBAAAC,MAAC,UAAK,WAAU,gBAAe;AAAA;AAAA,YAAE,YAAY,OAAO,OAAO;AAAA,aAAE,IAC3D;AAAA,UACH,UAAU,CAAC,UACV,gBAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cACX;AAAA;AAAA,UAED,IACE;AAAA,UACJ,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,WAAU;AAAA,cACV,cAAW;AAAA,cACZ;AAAA;AAAA,UAED;AAAA,WACF;AAAA,QAEA,gBAAAA,KAAC,SAAI,WAAU,mBACZ,oBACC,gBAAAA,KAAC,OAAE,WAAU,aAAY,kCAAe,IACtC,QACF,gBAAAA,KAAC,OAAE,WAAU,aAAa,iBAAM,IAC9B,CAAC,SACH,gBAAAA,KAAC,OAAE,WAAU,aAAY,wBAAU,IAEnC,gBAAAC,MAAAF,WAAA,EACG;AAAA,oBACC,gBAAAE,MAAC,SACC;AAAA,4BAAAA,MAAC,SAAI,WAAU,eACb;AAAA,8BAAAA,MAAC,SAAI,WAAU,oBAAmB;AAAA;AAAA,gBAEhC,gBAAAD,KAAC,UAAK,WAAU,YAAW,6DAAmC;AAAA,iBAChE;AAAA,cACA,gBAAAA,KAAC,SAAI,WAAU,aACZ,iBAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MACvC,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO;AAAA,kBACP;AAAA,kBACA,SAAS,QAAQ;AAAA,kBACjB,SAAS;AAAA,kBACT,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;AAAA;AAAA,gBALxB;AAAA,cAMP,CACD,GACH;AAAA,eACF;AAAA,YACC,gBAAgB,WAAW,MAC1B,gBAAAA,KAAC,SAAI,WAAU,iBACb,0BAAAA,KAAC,sBAAmB,YAAY,QAAQ,UAAoB,GAC9D,IACE;AAAA,aACN,IACE;AAAA,UAEH,WACC,gBAAAA,KAAC,kBAAe,SAAS,UAAU,UAAU,cAAc,IACzD;AAAA,UACH,YACC,gBAAAA,KAAC,OAAE,MAAK,SAAQ,WAAU,8BACvB,qBACH,IACE;AAAA,UAEH,UACC,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA,SAAS;AAAA;AAAA,UACX,IAEA,gBAAAA,KAAC,SAAI,WAAU,mBACZ,iBAAO,IAAI,CAAC,QACX,gBAAAC,MAAC,SAAc,WAAU,kBACvB;AAAA,4BAAAD,KAAC,UAAK,WAAU,gBAAgB,qBAAW,GAAG,GAAE;AAAA,YAChD,gBAAAA,KAAC,UAAK,WAAU,gBACb,sBAAY,OAAO,GAAG,CAAC,GAC1B;AAAA,eAJQ,GAKV,CACD,GACH;AAAA,WAEJ,GAEJ;AAAA,QAGC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,WAAW;AAAA,QAEtD,UAAU,UACT,gBAAAC,MAAC,YAAO,WAAU,qBAChB;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAU;AAAA,cAET,mBAAS,iBAAY;AAAA;AAAA,UACxB;AAAA,WACF,IACE,SACF,gBAAAC,MAAC,YAAO,WAAU,qBACf;AAAA,iBAAO;AAAA,UAAG;AAAA,UAAY,YAAY,OAAO,SAAS;AAAA,WACrD,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAMG,OAAM,OAAO,UAAU,WAAW,QAAQ;AAChD,MAAI,YAAY;AAChB,MAAI,UAAU,YAAY,KAAK;AAC/B,MAAIA,SAAQ,MAAM;AAChB,gBAAY,cAAc,YAAY,OAAOA,IAAG,CAAC;AAEjD,cAAU,UAAU,eAAe,aAAaA,IAAG,IAAI,OAAO,KAAK,MAAMA,IAAG,CAAC;AAAA,EAC/E;AACA,SACE,gBAAAH,MAAC,SAAI,WAAU,aACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,eACZ;AAAA,mBAAa,KAAK;AAAA,MAClB,UACC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,iBAAe;AAAA,UAChB;AAAA;AAAA,YACO,UAAU,WAAM;AAAA;AAAA;AAAA,MACxB,IACE;AAAA,OACN;AAAA,IACA,gBAAAD,KAAC,SAAI,WAAW,eAAe,SAAS,IAAK,mBAAQ;AAAA,IACpD,YAAY,KAAK,IAChB,gBAAAA,KAAC,SAAI,WAAU,iBAAiB,sBAAY,KAAK,GAAE,IACjD;AAAA,KACN;AAEJ;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAC,MAAC,SAAI,MAAK,SAAQ,WAAU,8BAC1B;AAAA,oBAAAD,KAAC,SAAI,WAAU,mBACb,0BAAAA,KAAC,UAAM,mBAAQ,GACjB;AAAA,IACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,SAAS,UAAU,+BAEzC;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA,KAAC,SAAI,WAAU,mBACZ,yBAAe,QAAQ,EAAE,IAAI,CAAC,UAC7B,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA,OAAO,MAAM,MAAM,GAAG;AAAA,MACtB,UAAU,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC;AAAA;AAAA,IAHhC,MAAM;AAAA,EAIb,CACD,GACH;AAEJ;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AAED,QAAM,KAAK,SAAS,MAAM,IAAI,QAAQ,QAAQ,GAAG,CAAC;AAClD,SACE,gBAAAC,MAAC,SAAI,WAAU,aACb;AAAA,oBAAAD,KAAC,WAAM,SAAS,IAAK,gBAAM,OAAM;AAAA,IAChC,MAAM,SAAS,aACd,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO,OAAO,SAAS,EAAE;AAAA,QACzB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,MAAM;AAAA,QACN,WAAU;AAAA;AAAA,IACZ,IACE,MAAM,SAAS,WACjB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAO,OAAO,SAAS,EAAE;AAAA,QACzB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAU;AAAA,QAET;AAAA,gBAAM,WAAW,gBAAAD,KAAC,YAAO,OAAM,IAAG,oBAAC,IAAY;AAAA,UAC/C,MAAM,SAAS,IAAI,CAAC,QACnB,gBAAAA,KAAC,YAAiB,OAAO,KACtB,iBADU,GAEb,CACD;AAAA;AAAA;AAAA,IACH,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,MAAM,SAAS,WAAW,WAAW;AAAA,QAC3C,OAAO,OAAO,SAAS,EAAE;AAAA,QACzB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAU;AAAA;AAAA,IACZ;AAAA,KAEJ;AAEJ;;;AK5ZA,SAAS,SAAS,YAAAK,iBAAgB;;;ACQlC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAsBP,IAAM,oBAAoB,CAAC,SAAS,QAAQ,aAAa;AACzD,IAAM,oBAAoB,CAAC,WAAW,QAAQ;AAC9C,IAAM,iBAAiB,CAAC,aAAa,cAAc,MAAM;AACzD,IAAM,cAAc,CAAC,SAAS,UAAU,QAAQ;AAChD,IAAM,eAAe,CAAC,YAAY,UAAU,SAAS;AACrD,IAAM,kBAAkB,CAAC,UAAU,eAAe,cAAc,UAAU;AAC1E,IAAM,kBAAkB,CAAC,UAAU,eAAe,YAAY;AAC9D,IAAM,SAAS,CAAC,aAAa,eAAe,cAAc;AAC1D,IAAM,YAAY,CAAC,OAAO,WAAW,MAAM;AAC3C,IAAM,cAAc,CAAC,QAAQ,UAAU,KAAK;AAE5C,IAAM,QAAQ,CAAC,GAAG,eAAe,GAAG,gBAAgB;AAEpD,IAAM,UAAU,CAAC,KAAK,OAAO,KAAK;AAElC,IAAM,SAA0C;AAAA,EAC9C,aAAa;AAAA,IACX,EAAE,KAAK,SAAS,OAAO,cAAc,MAAM,QAAQ,UAAU,KAAK;AAAA,IAClE,EAAE,KAAK,eAAe,OAAO,eAAe,MAAM,WAAW;AAAA,IAC7D,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,OAAO;AAAA,IAC3C,EAAE,KAAK,UAAU,OAAO,uBAAkB,MAAM,SAAS;AAAA,IACzD,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,kBAAkB;AAAA,IAC7E,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,WAAW;AAAA,IACnD,EAAE,KAAK,oBAAoB,OAAO,oBAAoB,MAAM,WAAW;AAAA,IACvE;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,EAAE,KAAK,SAAS,OAAO,cAAc,MAAM,QAAQ,UAAU,KAAK;AAAA,IAClE,EAAE,KAAK,cAAc,OAAO,cAAc,MAAM,OAAO;AAAA,IACvD,EAAE,KAAK,eAAe,OAAO,eAAe,MAAM,UAAU,SAAS,YAAY;AAAA,IACjF,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,kBAAkB;AAAA,IAC7E;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAQ,aAAa,aAAa;AAAA,EACxE;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,SAAS,OAAO,WAAW,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC/D,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,OAAO;AAAA,IAC/C,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,UAAU,SAAS,OAAO,UAAU,KAAK;AAAA,IAC7E,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,QAAQ,UAAU,KAAK;AAAA,IAClF;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,IACA,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAQ,aAAa,aAAa;AAAA,EACxE;AAAA,EACA,OAAO;AAAA,IACL,EAAE,KAAK,SAAS,OAAO,QAAQ,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC5D,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,YAAY;AAAA,IACvE,EAAE,KAAK,WAAW,OAAO,WAAW,MAAM,UAAU,SAAS,aAAa;AAAA,IAC1E,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAQ,aAAa,aAAa;AAAA,EACxE;AAAA,EACA,WAAW;AAAA,IACT,EAAE,KAAK,SAAS,OAAO,YAAY,MAAM,QAAQ,UAAU,KAAK;AAAA,IAChE,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,gBAAgB;AAAA,EAC7E;AAAA,EACA,UAAU;AAAA,IACR,EAAE,KAAK,SAAS,OAAO,QAAQ,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC5D,EAAE,KAAK,UAAU,OAAO,UAAU,MAAM,UAAU,SAAS,gBAAgB;AAAA,EAC7E;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC3D,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,OAAO;AAAA,IAC3C,EAAE,KAAK,WAAW,OAAO,WAAW,MAAM,OAAO;AAAA,EACnD;AACF;AAGO,SAAS,cAAc,UAAmC;AAC/D,SAAO,OAAO,QAAQ;AACxB;AAGO,SAAS,WAAW,UAA8C;AACvE,QAAM,QAAgC,CAAC;AACvC,aAAW,KAAK,cAAc,QAAQ,EAAG,OAAM,EAAE,GAAG,IAAI;AACxD,SAAO;AACT;AAGO,SAAS,gBACd,UACA,OACU;AACV,SAAO,cAAc,QAAQ,EAC1B,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,EAC9D,IAAI,CAAC,MAAM,EAAE,KAAK;AACvB;AAQO,SAAS,gBACd,UACA,OACyB;AACzB,QAAM,MAA+B,CAAC;AACtC,aAAW,KAAK,cAAc,QAAQ,GAAG;AACvC,UAAM,MAAM,OAAO,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK;AAC5C,QAAI,QAAQ,GAAI;AAChB,QAAI,EAAE,SAAS,YAAY,EAAE,WAAW,UAAU;AAChD,YAAM,IAAI,OAAO,GAAG;AACpB,UAAI,CAAC,OAAO,MAAM,CAAC,EAAG,KAAI,EAAE,GAAG,IAAI;AAAA,IACrC,OAAO;AACL,UAAI,EAAE,GAAG,IAAI;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;;;AClKO,IAAM,oBAAoB;AAE1B,IAAM,sBAAsB;;;ACTnC,SAAS,eAAAC,cAAa,YAAAC,iBAAgB;AAatC,eAAe,SAAY,KAAa,MAA2B;AACjE,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,QAAM,UAAW,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAGlD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,UACJ,SAAS,WAAW,SAAS,SAAS,mBAAmB,IAAI,MAAM;AACrE,UAAM,IAAI,MAAM,OAAO;AAAA,EACzB;AACA,SAAQ,QAAwB;AAClC;AASO,SAAS,UACd,UACA,WAAW,QACM;AACjB,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAS,KAAK;AAC1C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AAEtD,QAAM,SAASD;AAAA,IACb,OAAO,SAAkC;AACvC,gBAAU,IAAI;AACd,eAAS,IAAI;AACb,UAAI;AACF,eAAO,MAAM,SAAoB,GAAG,QAAQ,IAAI,QAAQ,IAAI,IAAI;AAAA,MAClE,SAAS,GAAG;AACV,cAAM,UAAU,aAAa,QAAQ,EAAE,UAAU;AACjD,iBAAS,OAAO;AAChB,cAAM;AAAA,MACR,UAAE;AACA,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AAAA,IACA,CAAC,UAAU,QAAQ;AAAA,EACrB;AAEA,SAAO,EAAE,QAAQ,QAAQ,MAAM;AACjC;AAeO,SAAS,QAAQ,WAAW,QAAuB;AACxD,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AAEtD,QAAM,OAAOD;AAAA,IACX,OAAO,SAAmB;AACxB,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,SAAkB,GAAG,QAAQ,SAAS,IAAI;AAAA,MAClD,SAAS,GAAG;AACV,cAAM,UAAU,aAAa,QAAQ,EAAE,UAAU;AACjD,iBAAS,OAAO;AAChB,cAAM;AAAA,MACR,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO,EAAE,MAAM,SAAS,MAAM;AAChC;;;AH1CM,SAEI,OAAAE,MAFJ,QAAAC,aAAA;AA7BC,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,SAAS,QAAQ,MAAM,cAAc,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAChE,QAAM,CAAC,OAAO,QAAQ,IAAIC;AAAA,IAAiC,MACzD,WAAW,QAAQ;AAAA,EACrB;AACA,QAAM,EAAE,QAAQ,QAAQ,MAAM,IAAI,UAAU,UAAU,QAAQ;AAE9D,QAAM,UAAU,gBAAgB,UAAU,KAAK;AAC/C,QAAM,MAAM,CAAC,KAAa,UACxB,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,EAAE;AAE1C,QAAM,WAAW,OAAO,MAAuB;AAC7C,MAAE,eAAe;AACjB,QAAI,QAAQ,SAAS,KAAK,OAAQ;AAClC,QAAI;AACF,YAAM,UAAU,MAAM,OAAO,gBAAgB,UAAU,KAAK,CAAC;AAC7D,gBAAU,QAAQ,EAAE;AAAA,IACtB,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SACE,gBAAAD,MAAC,UAAK,UAAoB,WAAU,YAClC;AAAA,oBAAAA,MAAC,SAAI,WAAU,iBACZ;AAAA,aAAO,IAAI,CAAC,UACX,gBAAAD;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,OAAO,MAAM,MAAM,GAAG,KAAK;AAAA,UAC3B,UAAU,CAAC,MAAM,IAAI,MAAM,KAAK,CAAC;AAAA;AAAA,QAH5B,MAAM;AAAA,MAIb,CACD;AAAA,MACA,QAAQ,gBAAAA,KAAC,OAAE,WAAU,aAAa,iBAAM,IAAO;AAAA,OAClD;AAAA,IAEA,gBAAAC,MAAC,YAAO,WAAU,qBAChB;AAAA,sBAAAD,KAAC,YAAO,MAAK,UAAS,SAAS,UAAU,WAAU,oCAAmC,oBAEtF;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAU,QAAQ,SAAS,KAAK;AAAA,UAChC,OACE,QAAQ,SAAS,IAAI,YAAY,QAAQ,KAAK,IAAI,CAAC,KAAK;AAAA,UAE1D,WAAU;AAAA,UAET,mBAAS,mBAAc,UAAU,eAAe,QAAQ,CAAC;AAAA;AAAA,MAC5D;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,KAAK,SAAS,MAAM,GAAG;AAC7B,SACE,gBAAAC,MAAC,SAAI,WAAU,aACb;AAAA,oBAAAA,MAAC,WAAM,SAAS,IAAI,WAAW,mBAC5B;AAAA,YAAM;AAAA,MACN,MAAM,WAAW,gBAAAD,KAAC,UAAK,WAAU,WAAU,gBAAE,IAAU;AAAA,OAC1D;AAAA,IACC,MAAM,SAAS,aACd,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,aAAa,MAAM;AAAA,QACnB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAW;AAAA;AAAA,IACb,IACE,MAAM,SAAS,WACjB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAW;AAAA,QAEX;AAAA,0BAAAD,KAAC,YAAO,OAAM,IAAG,oBAAC;AAAA,UACjB,MAAM,SAAS,IAAI,CAAC,QACnB,gBAAAA,KAAC,YAAiB,OAAO,KACtB,iBADU,GAEb,CACD;AAAA;AAAA;AAAA,IACH,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAM,MAAM,SAAS,WAAW,WAAW;AAAA,QAC3C;AAAA,QACA,aAAa,MAAM;AAAA,QACnB,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,QACxC,WAAW;AAAA;AAAA,IACb;AAAA,KAEJ;AAEJ;;;AI3IA,SAAS,WAAAG,UAAS,YAAAC,iBAAgB;;;ACMlC,SAAS,iBAAiD;AAW1D,IAAM,iBAA2C;AAAA,EAC/C,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,0BAA0B;AAAA,EAC1B,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,iBAAiB;AACnB;AAGO,SAAS,gBAAgB,UAAoC;AAClE,SAAQ,OAAO,KAAK,SAAS,EAC1B,OAAO,CAAC,MAAM,UAAU,CAAC,EAAE,KAAK,aAAa,QAAQ,EACrD,IAAI,CAAC,cAAc;AAAA,IAClB;AAAA,IACA,OAAO,eAAe,QAAQ;AAAA,IAC9B,gBAAgB,UAAU,QAAQ,EAAE;AAAA,EACtC,EAAE;AACN;;;AD4BM,gBAAAC,MAEE,QAAAC,aAFF;AAzCC,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,UAAUC,SAAQ,MAAM,gBAAgB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AACnE,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAS,EAAE;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,EAAE;AAC3C,QAAM,EAAE,MAAM,SAAS,MAAM,IAAI,QAAQ,QAAQ;AAEjD,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ,KAAK;AAC/D,QAAM,EAAE,QAAQ,IAAI;AAAA,IACjB,QAAQ,kBAAkB;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,WAAW,WAAW,CAAC,GAAG;AAAA,IAC9B,CAAC,MAAM,EAAE,QAAQ,mBAAmB,YAAY,EAAE,OAAO;AAAA,EAC3D;AAEA,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,QAAM,SAAS,YAAY;AACzB,QAAI,CAAC,UAAU,CAAC,YAAY,QAAS;AACrC,QAAI;AACF,YAAM,KAAK;AAAA,QACT,UAAU,OAAO;AAAA,QACjB,MAAM,EAAE,UAAU,IAAI,SAAS;AAAA,QAC/B,IAAI,EAAE,UAAU,OAAO,gBAAgB,IAAI,SAAS;AAAA,MACtD,CAAC;AACD,kBAAY,EAAE;AACd,kBAAY,EAAE;AACd,eAAS;AAAA,IACX,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SACE,gBAAAF,MAAC,aAAQ,WAAU,gBACjB;AAAA,oBAAAD,KAAC,QAAG,WAAU,gBAAe,2BAAa;AAAA,IAC1C,gBAAAC,MAAC,SAAI,WAAU,mBACb;AAAA,sBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,cAAW;AAAA,UACX,OAAO;AAAA,UACP,UAAU,CAAC,MAAM;AACf,wBAAY,EAAE,OAAO,KAAK;AAC1B,wBAAY,EAAE;AAAA,UAChB;AAAA,UACA,WAAW;AAAA,UAEX;AAAA,4BAAAD,KAAC,YAAO,OAAM,IAAG,qCAAkB;AAAA,YAClC,QAAQ,IAAI,CAAC,MACZ,gBAAAA,KAAC,YAAwB,OAAO,EAAE,UAC/B,YAAE,SADQ,EAAE,QAEf,CACD;AAAA;AAAA;AAAA,MACH;AAAA,MAEC,SACC,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,cAAW;AAAA,UACX,OAAO;AAAA,UACP,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,UAC3C,WAAW;AAAA,UAEX;AAAA,4BAAAD,KAAC,YAAO,OAAM,IAAG,mCAAgB;AAAA,YAChC,QAAQ,IAAI,CAAC,MACZ,gBAAAA,KAAC,YAAkB,OAAO,EAAE,IACzB,uBAAa,CAAC,KADJ,EAAE,EAEf,CACD;AAAA;AAAA;AAAA,MACH,IACE;AAAA,MAEH,QAAQ,gBAAAA,KAAC,OAAE,WAAU,aAAa,iBAAM,IAAO;AAAA,MAEhD,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,UAAU,CAAC,UAAU,CAAC,YAAY;AAAA,UAClC,WAAU;AAAA,UACV,OAAO,EAAE,WAAW,aAAa;AAAA,UAEhC,oBAAU,kBAAa;AAAA;AAAA,MAC1B;AAAA,OACF;AAAA,KACF;AAEJ;;;AfjEQ,SACE,OAAAI,MADF,QAAAC,aAAA;AArBD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,EAAE,SAAS,SAAS,OAAO,SAAS,YAAY,IAAI;AAAA,IACxD;AAAA,IACA;AAAA,EACF;AACA,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAwB,IAAI;AACxD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,EACX,IAAI,UAAU,UAAU,QAAQ,QAAQ;AAExC,SACE,gBAAAD,MAAC,SACC;AAAA,oBAAAA,MAAC,SAAI,WAAU,YACb;AAAA,sBAAAA,MAAC,SACC;AAAA,wBAAAD,KAAC,QAAI,yBAAe,QAAQ,GAAE;AAAA,QAC7B,WAAW,gBAAAA,KAAC,OAAG,oBAAS,IAAO;AAAA,SAClC;AAAA,MACA,gBAAAA,KAAC,SAAI,WAAU,cAAa;AAAA,MAC5B,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,YAAY;AAAA,UAC3B,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,MACA,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,WAAU;AAAA,UACX;AAAA;AAAA,YACQ,kBAAkB,QAAQ;AAAA;AAAA;AAAA,MACnC;AAAA,OACF;AAAA,IAEC,WAAW,CAAC,UACX,gBAAAA,MAAC,OAAE,WAAU,aAAY;AAAA;AAAA,MACd,eAAe,QAAQ,EAAE,YAAY;AAAA,MAAE;AAAA,OAClD,IACE,QACF,gBAAAD,KAAC,OAAE,WAAU,aAAa,iBAAM,IAEhC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,SAAS,WAAW,CAAC;AAAA,QACrB,YAAY;AAAA,QACZ,YAAY;AAAA;AAAA,IACd;AAAA,IAGF,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,MAAM,WAAW;AAAA,QACjB,SAAS,MAAM,UAAU,IAAI;AAAA,QAC7B;AAAA,QACA,WAAW,MAAM;AACf,wBAAc;AACd,sBAAY;AAAA,QACd;AAAA,QAEC,mBACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,UAAU;AAAA,YACV;AAAA,YACA,UAAU,MAAM;AACd,4BAAc;AACd,0BAAY;AAAA,YACd;AAAA;AAAA,QACF,IACE;AAAA;AAAA,IACN;AAAA,IAEA,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,MAAM,YAAY,KAAK;AAAA,QAChC,WAAW,OAAO,kBAAkB,QAAQ,CAAC;AAAA,QAE7C;AAAA,0BAAAD,KAAC,YAAO,WAAU,qBAChB,0BAAAC,MAAC,SACC;AAAA,4BAAAD,KAAC,OAAE,WAAU,sBAAqB,iBAAG;AAAA,YACrC,gBAAAA,KAAC,QAAG,WAAU,oBAAoB,4BAAkB,QAAQ,GAAE;AAAA,aAChE,GACF;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA,WAAW,CAAC,OAAO;AACjB,4BAAY,KAAK;AACjB,4BAAY;AACZ,0BAAU,EAAE;AAAA,cACd;AAAA,cACA,UAAU,MAAM,YAAY,KAAK;AAAA;AAAA,UACnC;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;AiB1FU,gBAAAG,MAEE,QAAAC,aAFF;AAjBH,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,SAAS,gBAAgB,IAAI,CAAC,OAAO;AAAA,IACzC,GAAG;AAAA,IACH,WAAW,YACP,EAAE,UAAU,OAAO,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC,IAC/C,EAAE;AAAA,EACR,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,CAAC;AAExC,SACE,gBAAAD,KAAC,SAAI,WAAU,WAAU,cAAW,aACjC,iBAAO,IAAI,CAAC,UACX,gBAAAC,MAAC,SACC;AAAA,oBAAAD,KAAC,SAAI,WAAU,iBAAiB,gBAAM,OAAM;AAAA,IAC3C,MAAM,UAAU,IAAI,CAAC,aACpB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAW,gBAAgB,aAAa,SAAS,cAAc,EAAE;AAAA,QACjE,gBAAc,aAAa,SAAS,SAAS;AAAA,QAC7C,SAAS,MAAM,SAAS,QAAQ;AAAA,QAEhC;AAAA,0BAAAD,KAAC,UAAK,WAAU,cAAa,eAAY,QACtC,wBAAc,QAAQ,GACzB;AAAA,UACC,eAAe,QAAQ;AAAA,UACxB,gBAAAA,KAAC,UAAK,WAAU,yBACb,mBAAS,QAAQ,MAAM,SACpB,YAAY,OAAO,QAAQ,KAAK,CAAC,IACjC,QACN;AAAA;AAAA;AAAA,MAdK;AAAA,IAeP,CACD;AAAA,OApBO,MAAM,KAqBhB,CACD,GACH;AAEJ;;;ACrEA,SAAS,eAAAE,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAiB1C,SAAS,UAAU,WAAW,QAAyB;AAC5D,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAwB,IAAI;AACxD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAwB,IAAI;AACtD,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,CAAC;AAElC,EAAAD,WAAU,MAAM;AACd,QAAI,OAAO;AACX,eAAW,IAAI;AACf,UAAM,GAAG,QAAQ,SAAS,EACvB,KAAK,OAAO,QAAQ;AACnB,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,0BAA0B,IAAI,MAAM,GAAG;AACpE,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB,CAAC,EACA,KAAK,CAAC,SAAS;AACd,UAAI,CAAC,KAAM;AACX,gBAAU,KAAK,MAAM;AACrB,eAAS,IAAI;AAAA,IACf,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,UAAI,CAAC,KAAM;AACX,eAAS,aAAa,QAAQ,EAAE,UAAU,uBAAuB;AAAA,IACnE,CAAC,EACA,QAAQ,MAAM;AACb,UAAI,KAAM,YAAW,KAAK;AAAA,IAC5B,CAAC;AACH,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,UAAU,IAAI,CAAC;AAEnB,QAAM,UAAUD,aAAY,MAAM,QAAQ,CAACG,OAAMA,KAAI,CAAC,GAAG,CAAC,CAAC;AAC3D,SAAO,EAAE,QAAQ,SAAS,OAAO,QAAQ;AAC3C;;;ApBgEM,SAGM,OAAAC,OAHN,QAAAC,cAAA;AAzEN,SAAS,WAAW,MAAsB;AACxC,QAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK;AACrC,QAAM,QAAQ,MAAM,CAAC,IAAI,CAAC,KAAK;AAC/B,QAAM,OAAO,MAAM,SAAS,IAAK,MAAM,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,KAAM;AACvE,UAAQ,QAAQ,MAAM,YAAY,KAAK;AACzC;AAGA,SAAS,iBAAiB,WAA4C;AACpE,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,OAAO,OAAO,SAAS,KAAK,QAAQ,SAAS,EAAE;AACrD,SAAQ,UAAuB,SAAS,IAAI,IAAK,OAAsB;AACzE;AAYO,SAAS,sBAAsB,EAAE,SAAS,CAAC,EAAE,GAA+B;AACjF,QAAM;AAAA,IACJ,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,EACd,IAAI;AAEJ,QAAM,CAAC,QAAQ,SAAS,IAAIC;AAAA,IAC1B,MAAM,iBAAiB,SAAS,KAAK,UAAU,CAAC,KAAK;AAAA,EACvD;AACA,QAAM,EAAE,OAAO,IAAI,UAAU,QAAQ;AAIrC,EAAAC,WAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,SAAS,MAAM;AACnB,YAAM,OAAO,iBAAiB,SAAS;AACvC,UAAI,KAAM,WAAU,IAAI;AAAA,IAC1B;AACA,WAAO,iBAAiB,cAAc,MAAM;AAC5C,WAAO,MAAM,OAAO,oBAAoB,cAAc,MAAM;AAAA,EAC9D,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,SAASC,aAAY,CAAC,aAAyB;AACnD,cAAU,QAAQ;AAClB,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,cAAcA,aAAY,MAAM;AACpC,UAAM,OAAO,SAAS;AACtB,UAAM,UACJ,KAAK,aAAa,YAAY,MAC7B,OAAO,WAAW,8BAA8B,EAAE,UAC/C,SACA;AACN,SAAK,aAAa,cAAc,YAAY,SAAS,UAAU,MAAM;AAAA,EACvE,GAAG,CAAC,CAAC;AAEL,QAAM,YAAY,UAAU,QAAQ;AACpC,QAAM,YAAY,UAAU,YAAY;AAExC,SACE,gBAAAH,OAAC,SAAI,WAAU,WACb;AAAA,oBAAAA,OAAC,SAAI,WAAU,aACb;AAAA,sBAAAD,MAAC,UAAK,WAAU,iBACb,oBAAU,UACT,gBAAAA,MAAC,SAAI,KAAK,SAAS,SAAS,KAAI,IAAG,IAEnC,WAEJ;AAAA,MAAQ;AAAA,MACP;AAAA,OACH;AAAA,IAEA,gBAAAC,OAAC,SAAI,WAAU,cACZ;AAAA,qBACC,gBAAAA,OAAC,SAAI,WAAU,eACb;AAAA,wBAAAD,MAAC,UAAK,WAAU,gBAAe;AAAA,QAAE;AAAA,QAAU,gBAAAA,MAAC,OAAG,wBAAa;AAAA,SAC9D,IACE;AAAA,MACH,aACC,gBAAAC,OAAC,UAAK,WAAU,YAAW;AAAA;AAAA,QAClB,gBAAAD,MAAC,OAAE,OAAO,EAAE,OAAO,kBAAkB,GAAI,sBAAW;AAAA,SAC7D,IACE;AAAA,MACJ,gBAAAA,MAAC,SAAI,WAAU,cAAa;AAAA,MAC5B,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAU,eAAc,SAAS,aAAa,0BAEpE;AAAA,MACC,MAAM,OACL,gBAAAC,OAAC,SAAI,WAAU,YACb;AAAA,wBAAAD,MAAC,UAAK,WAAU,cAAc,qBAAW,KAAK,IAAI,GAAE;AAAA,QACpD,gBAAAC,OAAC,SACC;AAAA,0BAAAD,MAAC,UAAK,WAAU,iBAAiB,eAAK,MAAK;AAAA,UAC1C,KAAK,UAAU,gBAAAA,MAAC,WAAO,eAAK,SAAQ,IAAW;AAAA,WAClD;AAAA,SACF,IACE;AAAA,OACN;AAAA,IAEA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAEA,gBAAAA,MAAC,UAAK,WAAU,YACd,0BAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,UAAU;AAAA,QACV;AAAA,QACA,UAAU,kBAAkB,MAAM;AAAA;AAAA,MAH7B;AAAA,IAIP,GACF;AAAA,KACF;AAEJ;;;AqBxII,SAGM,OAAAK,OAHN,QAAAC,cAAA;AAVG,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,YAAY,eAAe;AAAA,IAC/B,CAAC,MAAuB,OAAO,CAAC,MAAM;AAAA,EACxC;AACA,SACE,gBAAAA,OAAC,aAAQ,cAAW,mBAClB;AAAA,oBAAAD,MAAC,SAAI,WAAU,iBACZ,oBAAU,IAAI,CAAC,aACd,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,OAAO,eAAe,QAAQ;AAAA,QAC9B,OAAO,OAAO,QAAQ,KAAK;AAAA,QAC3B,SAAS,WAAW,MAAM,SAAS,QAAQ,IAAI;AAAA,QAC/C,QAAQ,WAAW;AAAA;AAAA,MAJd;AAAA,IAKP,CACD,GACH;AAAA,IACC,UAAU,gBAAAA,MAAC,OAAE,WAAU,YAAW,OAAO,EAAE,WAAW,GAAG,GAAI,mBAAQ,IAAO;AAAA,KAC/E;AAEJ;","names":["useCallback","useEffect","useState","useState","Fragment","jsx","jsxs","jsx","jsxs","useEffect","useState","str","useEffect","useEffect","t","Fragment","jsx","jsxs","Fragment","jsx","jsxs","useState","useEffect","num","useState","useCallback","useState","jsx","jsxs","useState","useMemo","useState","jsx","jsxs","useMemo","useState","jsx","jsxs","useState","jsx","jsxs","useCallback","useEffect","useState","t","jsx","jsxs","useState","useEffect","useCallback","jsx","jsxs"]}