@odla-ai/brand 0.7.1 → 0.7.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/agent-profile.ts","../src/errors.ts","../src/schema.ts","../src/read-shape.ts","../src/deps.ts","../src/rules.ts","../src/validate.ts","../src/review-json.ts","../src/review.ts","../src/discussion-reference.ts","../src/ops/books.ts","../src/ops/sections.ts","../src/ops/palettes.ts","../src/ops/assets.ts","../src/design/bundle.ts","../src/design/css-scan.ts","../src/color/hex.ts","../src/color/convert.ts","../src/color/contrast.ts","../src/color/harmony.ts","../src/color/ramp.ts","../src/color/delta.ts","../src/color/names.ts","../src/color/palette.ts","../src/tokens/map.ts","../src/design/decompile.ts","../src/design/html-text.ts","../src/design/outline.ts","../src/design/props.ts","../src/design/styles.ts","../src/design/tokens.ts","../src/design/digest.ts","../src/palette-report.ts","../src/tokens/roles.ts","../src/tokens/dark.ts","../src/tokens/css.ts","../src/tokens/compile.ts","../src/skill/asset-tools.ts","../src/skill/source-asset.ts","../src/skill/book-tools.ts","../src/skill/palette-tools.ts","../src/skill/design-tools.ts","../src/skill/read-tools.ts","../src/skill/skill.ts","../src/skill/persona.ts","../src/routes/asset-query.ts","../src/routes/http.ts","../src/routes/asset-upload.ts","../src/routes/assets.ts","../src/routes/books.ts","../src/routes/design-preview.ts","../src/routes/proposal-input.ts","../src/routes/proposal-effects.ts","../src/routes/proposal-resolution-receipts.ts","../src/routes/proposal-dependencies.ts","../src/routes/proposal-state.ts","../src/routes/proposals.ts","../src/routes/tokens.ts","../src/routes/discussion-asset.ts","../src/routes/discussion-references.ts","../src/routes/index.ts","../src/dispatch-assets.ts","../src/triggers.ts","../src/dispatch.ts","../src/descriptor.ts"],"sourcesContent":["// @odla-ai/brand — conversational brand-book builder on odla-db.\n//\n// Pure re-export barrel; the public surface groups as:\n// data model — constants, types, schema, rules, errors, deps, validate\n// ops — pure odla-db op builders shared by routes and skill\n// color engine — zero-dep OKLCH/WCAG math (hex, convert, contrast, harmony,\n// ramp, delta, names, derivePalette)\n// tokens — brand book → --ui-* design tokens + theme CSS\n// skill — the @odla-ai/ai agent skill, persona factory, vision gate\n// worker — route factory, chat-trigger dispatch, integration descriptor\nexport * from \"./constants\";\nexport * from \"./types\";\nexport * from \"./agent-profile\";\nexport * from \"./errors\";\nexport * from \"./deps\";\nexport * from \"./schema\";\nexport * from \"./rules\";\nexport * from \"./validate\";\nexport * from \"./review\";\nexport * from \"./discussion-reference\";\nexport * from \"./ops/index\";\nexport * from \"./design/index\";\nexport * from \"./palette-report\";\nexport * from \"./color/index\";\nexport * from \"./tokens/index\";\nexport * from \"./skill/index\";\nexport * from \"./routes/index\";\nexport * from \"./dispatch\";\nexport * from \"./triggers\";\nexport * from \"./descriptor\";\n","// Namespaces + closed vocabularies for @odla-ai/brand. One brand book is a\n// row-tree across six namespaces: the book (auth roster + compiled tokens),\n// its sections (one per kind, natural-keyed `${bookId}:${kind}`), palettes\n// (the atomic proposal/approval unit), proposals (human-gated agent output),\n// assets (worker-mediated uploads mirroring real R2 objects), and immutable\n// approval receipts recording the exact human-reviewed action.\n\n/** The odla-db namespaces @odla-ai/brand installs and writes. */\nexport const BRAND_NS = {\n book: \"brand_book\",\n section: \"brand_section\",\n palette: \"brand_palette\",\n proposal: \"brand_proposal\",\n approvalReceipt: \"brand_approval_receipt\",\n asset: \"brand_asset\",\n} as const;\n\n/** Brand-book lifecycle: authored → adopted → retired (delete is owner-only). */\nexport const BOOK_STATUSES = [\"draft\", \"active\", \"archived\"] as const;\n/** Where a brand book stands in its lifecycle. */\nexport type BookStatus = (typeof BOOK_STATUSES)[number];\n\n/** The section kinds a book carries — one row per kind, upserted by natural key. */\nexport const SECTION_KINDS = [\"palette\", \"typography\", \"voice\", \"logo\", \"imagery\"] as const;\n/** Which facet of the brand a section documents. */\nexport type SectionKind = (typeof SECTION_KINDS)[number];\n\n/** Section review state: agent drafts, a human approves. */\nexport const SECTION_STATUSES = [\"draft\", \"approved\"] as const;\n/** Whether a section's content has human sign-off. */\nexport type SectionStatus = (typeof SECTION_STATUSES)[number];\n\n/** Palette lifecycle — palettes are never row-deleted, only archived. */\nexport const PALETTE_STATUSES = [\"active\", \"archived\"] as const;\n/** Whether a palette is the live one or a retired predecessor. */\nexport type PaletteStatus = (typeof PALETTE_STATUSES)[number];\n\n/** How a palette came to be: pulled from an asset, derived from a seed color,\n * or entered by hand. */\nexport const PALETTE_SOURCES = [\"extracted\", \"derived\", \"manual\"] as const;\n/** Provenance of a palette's swatches. */\nexport type PaletteSource = (typeof PALETTE_SOURCES)[number];\n\n/** Every mutable brand facet uses the same proposal/approval contract. */\nexport const PROPOSAL_KINDS = SECTION_KINDS;\n/** Which brand facet a proposal targets. */\nexport type ProposalKind = (typeof PROPOSAL_KINDS)[number];\n\n/** Proposal lifecycle: open until a HUMAN accepts/rejects it (or a newer\n * proposal supersedes it) — agents never resolve their own proposals. */\nexport const PROPOSAL_STATUSES = [\"open\", \"accepted\", \"rejected\", \"superseded\"] as const;\n/** Where a proposal stands in the human-gated review flow. */\nexport type ProposalStatus = (typeof PROPOSAL_STATUSES)[number];\n\n/** What kind of upload an asset row records. `design` is the one kind whose\n * bytes are HTML — a Claude Design standalone export — and the only kind the\n * preview route will ever serve as a document; see `design/` and\n * `routes/design-preview.ts`. */\nexport const ASSET_KINDS = [\n \"logo\",\n \"wordmark\",\n \"inspiration\",\n \"document\",\n \"design\",\n \"other\",\n] as const;\n/** The declared purpose of an uploaded asset. */\nexport type AssetKind = (typeof ASSET_KINDS)[number];\n\n/** The asset kind carrying a Claude Design bundle. Its content type, digest,\n * preview route, and agent tools are all keyed off this one value. */\nexport const DESIGN_ASSET_KIND = \"design\";\n\n/** Every swatch role a palette may assign. `chart` may repeat (a series);\n * `custom` is the escape hatch for roles the token compiler doesn't map. */\nexport const SWATCH_ROLES = [\n \"primary\",\n \"secondary\",\n \"highlight\",\n \"bg\",\n \"surface\",\n \"text\",\n \"neutral\",\n \"good\",\n \"warn\",\n \"danger\",\n \"chart\",\n \"custom\",\n] as const;\n","/** Canonical least-privilege runtime profile for a Brand collaborator agent. */\nexport interface BrandAgentProfile {\n version: 1;\n projectCapabilities: readonly [\"brand.read\", \"brand.edit\"];\n semanticOperations: readonly [\n \"brand.proposal.create\",\n \"brand.asset.analysis.record\",\n \"brand.asset.content.read\",\n ];\n rawBrandWrites: false;\n rawFileOperations: false;\n approval: {\n principalKind: \"human\";\n projectCapability: \"brand.approve\";\n capability: \"brand.proposal.resolve\";\n exactAction: true;\n };\n}\n\n/** Install-time contract: agents use semantic Brand operations; only a direct\n * human may consume exact approval authority for a reviewed proposal. */\nexport const BRAND_AGENT_PROFILE: BrandAgentProfile = {\n version: 1,\n projectCapabilities: [\"brand.read\", \"brand.edit\"],\n semanticOperations: [\n \"brand.proposal.create\",\n \"brand.asset.analysis.record\",\n \"brand.asset.content.read\",\n ],\n rawBrandWrites: false,\n rawFileOperations: false,\n approval: {\n principalKind: \"human\",\n projectCapability: \"brand.approve\",\n capability: \"brand.proposal.resolve\",\n exactAction: true,\n },\n};\n","/** Caller-fault error (bad hex, oversized payload, blocked transition…) — the\n * route layer maps it to a 400. `fields` carries per-field messages when the\n * failure came from input validation. */\nexport class BrandInputError extends Error {\n readonly fields?: Record<string, string>;\n constructor(message: string, fields?: Record<string, string>) {\n super(message);\n this.name = \"BrandInputError\";\n this.fields = fields;\n }\n}\n\n/** Missing entity — the route layer maps it to a 404. */\nexport class BrandNotFoundError extends Error {\n constructor(what: string) {\n super(`${what} not found`);\n this.name = \"BrandNotFoundError\";\n }\n}\n\n/** A once-valid central authority/resource is permanently unavailable. */\nexport class BrandGoneError extends Error {\n constructor(message = \"brand authority or resource is no longer available\") {\n super(message);\n this.name = \"BrandGoneError\";\n }\n}\n\n/** Authenticated principal lacks the required principal kind/capability. */\nexport class BrandForbiddenError extends Error {\n constructor(message = \"forbidden\") {\n super(message);\n this.name = \"BrandForbiddenError\";\n }\n}\n\n/** Reviewed state or an idempotent action no longer matches current state. */\nexport class BrandConflictError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BrandConflictError\";\n }\n}\n\n/**\n * A proposal authority use was consumed, but the local guarded Brand write\n * lost its compare-and-swap race. Clients must preserve the reviewed draft but\n * rotate their idempotency key before a fresh human decision attempt.\n */\nexport class BrandReviewStateChangedError extends BrandConflictError {\n readonly code = \"brand_review_state_changed\";\n\n constructor(\n message = \"proposal or live brand dependencies changed; review and approve again\",\n ) {\n super(message);\n this.name = \"BrandReviewStateChangedError\";\n }\n}\n","// The odla-db schema @odla-ai/brand installs (POST to `/app/:id/schema` as\n// `{ schema: BRAND_SCHEMA }`). Ships pre-serialized (the wire shape) so\n// provisioning needs no schema-builder dependency, mirroring @odla-ai/chat\n// and @odla-ai/crm. The serialized types are inlined so the package has zero\n// deps.\n//\n// Design notes (grounded in the odla-db engine):\n// - Swatches are json ON `brand_palette`, NOT their own namespace: the\n// palette is the atomic proposal/approval unit — a human accepts or rejects\n// a palette whole, and swatches are never queried across palettes.\n// - Every child has a schema link to its book. CEL reads membership from the\n// CURRENT `book.memberIds` via ref(), so roster changes never require an\n// eventually-consistent audience fan-out. Proposal audience remains frozen\n// review provenance, not authorization state.\n// - Entity ids are not attributes in odla-db (`where: { id }` matches\n// nothing), so id-addressed rows mirror their id as a unique attr — the\n// crm pattern.\nimport { BRAND_NS } from \"./constants\";\n\n/** Wire-shape attribute value kinds odla-db stores. */\nexport type AttrType = \"string\" | \"number\" | \"boolean\" | \"date\" | \"json\";\n/** One serialized attribute: its type and index/uniqueness flags. */\nexport interface SerializedAttr {\n type: AttrType;\n unique: boolean;\n indexed: boolean;\n optional: boolean;\n}\n/** One serialized namespace: its attribute map. */\nexport interface SerializedEntity {\n attrs: Record<string, SerializedAttr>;\n}\n/** One end of a serialized schema link. */\nexport interface SerializedLinkEnd {\n on: string;\n has: \"one\" | \"many\";\n label: string;\n}\n/** A serialized schema link used for current-book authorization. */\nexport interface SerializedLink {\n forward: SerializedLinkEnd;\n reverse: SerializedLinkEnd;\n}\n/** The wire-shape schema POSTed to `/app/:id/schema`. */\nexport interface SerializedSchema {\n entities: Record<string, SerializedEntity>;\n links: Record<string, SerializedLink>;\n}\n\ntype Opt = Partial<Omit<SerializedAttr, \"type\">>;\nconst a = (type: AttrType, o: Opt = {}): SerializedAttr => ({\n type,\n unique: false,\n indexed: false,\n optional: false,\n ...o,\n});\nconst uniq = (type: AttrType): SerializedAttr => a(type, { unique: true, indexed: true });\nconst idx = (type: AttrType, optional = false): SerializedAttr => a(type, { indexed: true, optional });\nconst opt = (type: AttrType): SerializedAttr => a(type, { optional: true });\n\n/**\n * The pre-serialized (wire-shape) odla-db schema for the six brand\n * namespaces; POST it to `/app/:id/schema` as `{ schema: BRAND_SCHEMA }`.\n * Natural keys (`book.slug`, `section.key`) make provisioning and section\n * upserts idempotent; mirrored `id` attrs make rows addressable by\n * `where: { id }`.\n */\nexport const BRAND_SCHEMA: SerializedSchema = {\n entities: {\n [BRAND_NS.book]: {\n attrs: {\n id: uniq(\"string\"),\n version: a(\"number\"),\n slug: uniq(\"string\"),\n name: idx(\"string\"),\n status: idx(\"string\"), // draft | active | archived\n ownerId: idx(\"string\"),\n createdAuthorityRef: idx(\"string\"),\n rosterAuthorityRef: opt(\"string\"),\n memberIds: a(\"json\"), // the auth roster, incl. the bot agent id\n channelId: a(\"string\", { unique: true, indexed: true, optional: true }),\n activePaletteId: opt(\"string\"),\n activationRevision: a(\"number\"),\n tokens: opt(\"json\"), // maps + complete palette/typography receipt provenance\n summary: opt(\"string\"),\n createdAt: idx(\"date\"),\n updatedAt: idx(\"date\"),\n },\n },\n [BRAND_NS.section]: {\n attrs: {\n key: uniq(\"string\"), // `${bookId}:${kind}` — one section per kind\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // palette | typography | voice | logo | imagery\n status: idx(\"string\"), // draft | approved\n content: a(\"json\"),\n audience: a(\"json\"),\n updatedBy: a(\"string\"),\n updatedAt: idx(\"date\"),\n approvalReceiptId: opt(\"string\"),\n approvalActionDigest: opt(\"string\"),\n },\n },\n [BRAND_NS.palette]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n name: a(\"string\"),\n status: idx(\"string\"), // active | archived\n swatches: a(\"json\"), // Swatch[] — see the header design note\n seedHex: opt(\"string\"),\n source: a(\"string\"), // extracted | derived | manual\n rationale: opt(\"string\"),\n proposalId: idx(\"string\"),\n approvalReceiptId: a(\"string\"),\n approvalActionDigest: a(\"string\"),\n audience: a(\"json\"),\n createdAt: idx(\"date\"),\n updatedAt: idx(\"date\"),\n },\n },\n [BRAND_NS.proposal]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // palette | typography | voice | logo\n status: idx(\"string\"), // open | accepted | rejected | superseded\n payload: a(\"json\"),\n rationale: a(\"string\"),\n provenance: a(\"json\"), // exact source asset/message/turn ids (nullable asset)\n reviewDigest: idx(\"string\"),\n audience: a(\"json\"),\n createdBy: a(\"string\"),\n createdAuthorityRef: a(\"string\"),\n createdAt: idx(\"date\"),\n resolvedBy: opt(\"string\"),\n resolvedAt: opt(\"date\"),\n resolutionNote: opt(\"string\"),\n approvedBy: opt(\"string\"),\n appliedBy: opt(\"string\"),\n resolutionReceiptId: opt(\"string\"),\n resolutionActionDigest: opt(\"string\"),\n },\n },\n [BRAND_NS.approvalReceipt]: {\n attrs: {\n id: uniq(\"string\"),\n version: a(\"number\"),\n mutationKey: uniq(\"string\"),\n bookId: idx(\"string\"),\n proposalId: idx(\"string\"),\n resolution: idx(\"string\"), // accepted | rejected\n paletteId: opt(\"string\"),\n resolutionNote: opt(\"string\"),\n reviewedProposal: a(\"json\"),\n actionDigest: idx(\"string\"),\n decisionBinding: a(\"json\"),\n approvedBy: idx(\"string\"),\n approvedByKind: a(\"string\"),\n appliedBy: idx(\"string\"),\n appliedByKind: a(\"string\"),\n authorityRef: idx(\"string\"),\n authorityCapability: a(\"string\"),\n authorityConsumption: a(\"json\"),\n createdAt: idx(\"date\"),\n receiptDigest: idx(\"string\"),\n },\n },\n [BRAND_NS.asset]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // logo | wordmark | inspiration | document | design | other\n path: idx(\"string\"),\n storageObjectId: idx(\"string\"),\n contentDigest: idx(\"string\"),\n contentType: a(\"string\"),\n size: a(\"number\"),\n status: idx(\"string\"), // live | deleting | deleted\n title: opt(\"string\"),\n analysis: opt(\"json\"), // { description, dominantColors: hex[], tags }\n analyzedAt: opt(\"date\"),\n // `design` kind only: the DesignDigest computed from the uploaded\n // bundle at upload time. Machine-derived and deterministic — unlike\n // `analysis`, which is what a model reports seeing — so it needs no\n // review gate and is rewritten only by re-uploading.\n design: opt(\"json\"),\n analysisRevision: a(\"number\"),\n analysisDigest: opt(\"string\"),\n analyzedBy: opt(\"string\"),\n analyzedAuthorityRef: opt(\"string\"),\n audience: a(\"json\"),\n uploadedBy: a(\"string\"),\n uploadedAuthorityRef: a(\"string\"),\n createdAt: idx(\"date\"),\n deletedAt: opt(\"date\"), // tombstone — asset rows are never row-deleted\n deletedBy: opt(\"string\"),\n deletedAuthorityRef: opt(\"string\"),\n },\n },\n },\n links: {\n brandSectionBook: {\n forward: { on: BRAND_NS.section, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"sections\" },\n },\n brandPaletteBook: {\n forward: { on: BRAND_NS.palette, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"palettes\" },\n },\n brandProposalBook: {\n forward: { on: BRAND_NS.proposal, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"proposals\" },\n },\n brandApprovalReceiptBook: {\n forward: { on: BRAND_NS.approvalReceipt, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"approvalReceipts\" },\n },\n brandAssetBook: {\n forward: { on: BRAND_NS.asset, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"assets\" },\n },\n },\n};\n","// Reading a stored row back in the shape it was written.\n//\n// Split from review.ts along the seam between NORMALISING a row and VERIFYING\n// one. They are different jobs — the verifier proves self-consistency, this\n// undoes a storage detail — and only the second one needs to know the schema.\n//\n// The engine stores a `date` as the epoch ms it was given and hands a reader\n// ISO-8601 text back. Brand digests rows that CONTAIN dates, so a row read\n// straight out of the store can never match the digest stored beside it.\nimport { BRAND_NS } from \"./constants\";\nimport { BRAND_SCHEMA } from \"./schema\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/**\n * Attrs declared `date`, per namespace, from the schema itself.\n *\n * Derived rather than listed so a new `date` attr is covered the day it is\n * declared: a hand-kept list is the same defect one release later.\n */\nconst DATE_FIELDS = new Map<string, Set<string>>();\nfor (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))\n DATE_FIELDS.set(\n ns,\n new Set(\n Object.entries(entity.attrs)\n .filter(([, attr]) => attr.type === \"date\")\n .map(([label]) => label),\n ),\n );\n\n/**\n * A stored row in the shape it was WRITTEN, ready to verify.\n *\n * The engine stores a `date` as the epoch ms it was given and hands a reader\n * ISO-8601 text back. Brand digests rows that CONTAIN dates — a proposal's\n * `reviewDigest` covers its `createdAt`, and an approval receipt's\n * `receiptDigest` covers its own — so a row read straight out of the store can\n * never match the digest stored beside it. Two production symptoms, both 409:\n * resolving any proposal (\"proposal changed since review\") and reading a book's\n * tokens after approval.\n *\n * Normalising at the READ is the fix, not tolerating both shapes in the\n * verifier. Tolerance would repair a `safeTime` check and leave the digest\n * failing, because the digest was taken over the number and nothing can change\n * that after the fact.\n *\n * Anything that is not date-shaped text passes through untouched, so a row that\n * never round-tripped verifies exactly as before. `json` attrs are left alone:\n * their contents round-trip as written, which is why an `authorityConsumption`\n * and the `createdAt` beside it disagreed at all.\n */\nexport function rowAsWritten<T>(ns: string, row: T): T {\n const dates = DATE_FIELDS.get(ns);\n if (!dates?.size || !record(row)) return row;\n let changed = false;\n const out: Record<string, unknown> = { ...row };\n for (const field of dates) {\n const value = out[field];\n if (typeof value !== \"string\") continue;\n const parsed = Date.parse(value);\n if (!Number.isSafeInteger(parsed) || parsed < 0) continue;\n out[field] = parsed;\n changed = true;\n }\n return (changed ? out : row) as T;\n}\n\n/** A stored approval receipt in the shape it was written. */\nexport function receiptAsWritten<T>(row: T): T {\n return rowAsWritten(BRAND_NS.approvalReceipt, row);\n}\n\n/** A stored proposal in the shape it was written, so `reviewDigest` matches. */\nexport function proposalAsWritten<T>(row: T): T {\n return rowAsWritten(BRAND_NS.proposal, row);\n}\n\n/**\n * Every row of a query result in the shape it was written, keyed by the\n * namespace it came back under.\n *\n * Applied once, where an op resolves its database, rather than at each of the\n * two dozen read sites — which is the arrangement that left `crm` wrong at 26\n * of them after three were fixed by hand. A read site added tomorrow inherits\n * this; it cannot forget it.\n */\nexport function resultAsWritten<T extends Record<string, unknown>>(result: T): T {\n const out: Record<string, unknown> = { ...result };\n for (const [ns, rows] of Object.entries(out)) {\n if (Array.isArray(rows)) out[ns] = rows.map((row) => rowAsWritten(ns, row));\n }\n return out as T;\n}\n","// The dependency bundle brand operations take. `now`/`newId` are injectable\n// so tests can pin time and ids and assert exact written attrs; `fetchBytes`\n// is the one network seam (asset bytes for vision), injectable so tests and\n// service-binding hosts never touch the public internet.\nimport { resultAsWritten } from \"./read-shape\";\nimport type { BrandDb } from \"./types\";\n\n/** What `fetchBytes` resolves to: raw bytes plus the served content type. */\nexport interface BrandFetchedBytes {\n bytes: Uint8Array;\n contentType: string;\n}\n\n/** What every brand operation needs: the injected db, plus test overrides. */\nexport interface BrandDeps {\n db: BrandDb;\n /** Clock override (default `Date.now`). */\n now?: () => number;\n /** Id factory override (default `crypto.randomUUID`). */\n newId?: () => string;\n /** Asset-byte fetcher override (default: global `fetch`). */\n fetchBytes?: (url: string) => Promise<BrandFetchedBytes>;\n}\n\n/** {@link BrandDeps} with the injectable defaults filled in. */\nexport interface ResolvedBrandDeps {\n db: BrandDb;\n now: () => number;\n newId: () => string;\n fetchBytes: (url: string) => Promise<BrandFetchedBytes>;\n}\n\nasync function defaultFetchBytes(url: string): Promise<BrandFetchedBytes> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);\n return {\n bytes: new Uint8Array(await res.arrayBuffer()),\n contentType: res.headers.get(\"content-type\") ?? \"application/octet-stream\",\n };\n}\n\n/**\n * The database every op reads through, with a `date` handed back as the epoch\n * ms it was written as.\n *\n * Brand digests rows that contain dates, so a row read straight out of the\n * store could never match the digest stored beside it — #486 fixed that at\n * roughly a dozen read sites and left the other eleven. Doing it here means a\n * read site added later inherits it. Writes are untouched: only what comes\n * back changes shape.\n *\n * Methods are forwarded one by one rather than spread: the db is often a class\n * instance, and spreading one leaves every prototype method behind.\n */\nfunction readingAsWritten(db: BrandDb): BrandDb {\n return {\n query: async (q) => resultAsWritten(await db.query(q)),\n transact: (ops, opts) => db.transact(ops, opts),\n storage: db.storage,\n };\n}\n\n/** Fill the injectable defaults. */\nexport function resolveDeps(deps: BrandDeps): ResolvedBrandDeps {\n return {\n db: readingAsWritten(deps.db),\n now: deps.now ?? Date.now,\n newId: deps.newId ?? (() => crypto.randomUUID()),\n fetchBytes: deps.fetchBytes ?? defaultFetchBytes,\n };\n}\n","// Default-deny CEL rules for the brand namespaces (POST to\n// `/app/:id/admin/rules`). Access is denormalized (see schema.ts): books gate\n// on `data.memberIds`; child rows follow their required book link and read the\n// current roster with `ref()`. Child writes are closed: proposals and\n// approval receipts all pass through worker routes/tools with explicit actor\n// attribution instead of letting an audience member mutate approval state.\n//\n// Asset writes are closed: rows mirror private object storage and only the\n// worker performs upload/mirror and delete/tombstone pairs.\nimport { BRAND_NS } from \"./constants\";\n\n/** Per-namespace CEL rule strings (missing action = deny). */\nexport interface BrandRule {\n view?: string;\n create?: string;\n update?: string;\n delete?: string;\n}\n/** Namespace → rule set, as installed at `/app/:id/admin/rules`. */\nexport type BrandRules = Record<string, BrandRule>;\n\n// Membership in the audience snapshot — implies a signed identity, since an\n// anonymous auth.id is never written into an audience.\n// A has-one link's ref() result is still a list; the json memberIds value is\n// therefore nested one level (`[[id,…]]`) and must be checked with exists.\nconst CURRENT_BOOK_MEMBER =\n \"ref('book.memberIds').exists(members, auth.id in members)\";\n\n/**\n * Default-deny CEL rules for the six brand namespaces; install at\n * `/app/:id/admin/rules`. Books gate on the `memberIds` roster (owner-only\n * writes); child rows gate reads on current linked-book membership and all\n * writes are worker-mediated. Use\n * {@link brandRules} for a per-install copy.\n */\nexport const BRAND_RULES: BrandRules = {\n [BRAND_NS.book]: {\n view: \"auth.id in data.memberIds\",\n // Every mutation is worker-routed: CEL cannot distinguish an update from\n // a retract, so effect-bearing fields must never be browser-writable.\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.section]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.palette]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.proposal]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.approvalReceipt]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.asset]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n};\n\n/**\n * Rules factory, mirroring `chatRules()`/`crmRules()`. Today it returns a\n * fresh copy of {@link BRAND_RULES}; it exists so a future option (e.g.\n * locking views to an org email domain) can widen or tighten namespaces\n * without apps changing their provisioning call shape.\n */\nexport function brandRules(): BrandRules {\n return Object.fromEntries(Object.entries(BRAND_RULES).map(([ns, r]) => [ns, { ...r }]));\n}\n","// Input validation for brand writes — THE enforcement layer. Taint marking on\n// tool output is advisory; nothing an agent (or a route caller) produces\n// reaches odla-db without passing these checks. Every failure throws\n// {@link BrandInputError} with an actionable message.\nimport { DESIGN_ASSET_KIND, SECTION_KINDS, SWATCH_ROLES } from \"./constants\";\nimport { BrandInputError } from \"./errors\";\nimport type {\n AssetAnalysis,\n ImagerySection,\n LogoSection,\n PaletteSection,\n Swatch,\n SwatchRole,\n TypographySection,\n VoiceSection,\n} from \"./types\";\n\n/** Most swatches a single palette may carry. */\nexport const MAX_SWATCHES = 24;\n\n/** Upload content types the asset pipeline accepts for every kind EXCEPT\n * `design`. Deliberately free of `text/html`: these bytes are handed back to\n * members over signed storage URLs, and an HTML document served from a\n * storage origin is a script-execution surface. */\nexport const ASSET_CONTENT_TYPES: ReadonlySet<string> = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/pdf\",\n]);\n\n/** The only content type a `design` asset may carry. Designs are the one\n * HTML-bearing kind, and they are never served raw — the preview route\n * proxies them under a `sandbox` CSP (see `routes/design-preview.ts`). */\nexport const DESIGN_CONTENT_TYPES: ReadonlySet<string> = new Set([\"text/html\"]);\n\nconst HEX_RGB = /^#[0-9a-f]{3}$/;\nconst HEX_RRGGBB = /^#[0-9a-f]{6}$/;\nconst HEX_ALPHA = /^#[0-9a-f]{4}$|^#[0-9a-f]{8}$/;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/**\n * Assert `value` is a `#rgb`/`#rrggbb` hex color and normalize it to\n * lowercase `#rrggbb`. Alpha channels (`#rgba`/`#rrggbbaa`) and every other\n * color syntax are rejected — tokens and contrast math are defined on opaque\n * sRGB hex.\n */\nexport function assertHex(value: unknown, label = \"color\"): string {\n if (typeof value !== \"string\")\n throw new BrandInputError(`${label} must be a hex string like #1a2b3c`);\n const hex = value.trim().toLowerCase();\n if (HEX_ALPHA.test(hex))\n throw new BrandInputError(`${label} must not carry alpha (got ${value}); use #rrggbb`);\n if (HEX_RGB.test(hex)) return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;\n if (!HEX_RRGGBB.test(hex))\n throw new BrandInputError(`${label} must be #rgb or #rrggbb hex (got ${value})`);\n return hex;\n}\n\n/** Assert a trimmed non-empty string of at most `max` characters. */\nexport function capString(value: unknown, label: string, max: number): string {\n if (typeof value !== \"string\") throw new BrandInputError(`${label} must be a string`);\n const s = value.trim();\n if (s === \"\") throw new BrandInputError(`${label} must not be empty`);\n if (s.length > max)\n throw new BrandInputError(`${label} must be at most ${max} characters (got ${s.length})`);\n return s;\n}\n\n/** Assert an array of capped strings (each trimmed and non-empty). */\nexport function capStringArray(\n value: unknown,\n label: string,\n opts: { maxItems: number; maxLen: number; minItems?: number },\n): string[] {\n if (!Array.isArray(value)) throw new BrandInputError(`${label} must be an array of strings`);\n const min = opts.minItems ?? 0;\n if (value.length < min)\n throw new BrandInputError(`${label} must have at least ${min} item${min === 1 ? \"\" : \"s\"}`);\n if (value.length > opts.maxItems)\n throw new BrandInputError(`${label} must have at most ${opts.maxItems} items`);\n return value.map((v, i) => capString(v, `${label}[${i}]`, opts.maxLen));\n}\n\n/**\n * Assert a swatch list: 1–{@link MAX_SWATCHES} entries, each with a known\n * role, a valid hex (normalized), and capped optional name/rationale.\n * Returns the normalized copy — write THAT, never the raw input.\n */\nexport function assertSwatches(value: unknown): Swatch[] {\n if (!Array.isArray(value) || value.length === 0)\n throw new BrandInputError(\"swatches must be a non-empty array\");\n if (value.length > MAX_SWATCHES)\n throw new BrandInputError(`swatches must have at most ${MAX_SWATCHES} entries`);\n return value.map((raw, i) => {\n if (!isRecord(raw)) throw new BrandInputError(`swatches[${i}] must be an object`);\n const role = raw.role;\n if (typeof role !== \"string\" || !(SWATCH_ROLES as readonly string[]).includes(role))\n throw new BrandInputError(\n `swatches[${i}].role must be one of: ${SWATCH_ROLES.join(\", \")}`,\n );\n const out: Swatch = { role: role as SwatchRole, hex: assertHex(raw.hex, `swatches[${i}].hex`) };\n if (raw.name !== undefined) out.name = capString(raw.name, `swatches[${i}].name`, 80);\n if (raw.rationale !== undefined)\n out.rationale = capString(raw.rationale, `swatches[${i}].rationale`, 500);\n return out;\n });\n}\n\nfunction assertPaletteSection(c: Record<string, unknown>): PaletteSection {\n return {\n paletteId: capString(c.paletteId, \"content.paletteId\", 128),\n name: capString(c.name, \"content.name\", 120),\n swatches: assertSwatches(c.swatches),\n };\n}\n\nfunction assertTypographySection(c: Record<string, unknown>): TypographySection {\n const out: TypographySection = {};\n if (c.fontDisplay !== undefined) out.fontDisplay = capString(c.fontDisplay, \"content.fontDisplay\", 120);\n if (c.fontBody !== undefined) out.fontBody = capString(c.fontBody, \"content.fontBody\", 120);\n if (c.fontMono !== undefined) out.fontMono = capString(c.fontMono, \"content.fontMono\", 120);\n if (c.scale !== undefined) {\n if (typeof c.scale !== \"number\" || !Number.isFinite(c.scale) || c.scale <= 1 || c.scale > 2)\n throw new BrandInputError(\"content.scale must be a modular type-scale ratio in (1, 2]\");\n out.scale = c.scale;\n }\n if (c.notes !== undefined) out.notes = capString(c.notes, \"content.notes\", 2000);\n return out;\n}\n\nfunction assertVoiceSection(c: Record<string, unknown>): VoiceSection {\n const out: VoiceSection = {\n tone: capString(c.tone, \"content.tone\", 200),\n principles: capStringArray(c.principles, \"content.principles\", { maxItems: 12, maxLen: 200, minItems: 1 }),\n };\n if (c.examples !== undefined)\n out.examples = capStringArray(c.examples, \"content.examples\", { maxItems: 12, maxLen: 500 });\n return out;\n}\n\nfunction assertLogoSection(c: Record<string, unknown>): LogoSection {\n const out: LogoSection = {\n usage: capStringArray(c.usage, \"content.usage\", { maxItems: 16, maxLen: 300, minItems: 1 }),\n donts: capStringArray(c.donts, \"content.donts\", { maxItems: 16, maxLen: 300 }),\n };\n if (c.clearspace !== undefined) out.clearspace = capString(c.clearspace, \"content.clearspace\", 120);\n if (c.minSize !== undefined) out.minSize = capString(c.minSize, \"content.minSize\", 120);\n return out;\n}\n\nfunction assertImagerySection(c: Record<string, unknown>): ImagerySection {\n return {\n style: capString(c.style, \"content.style\", 200),\n guidance: capStringArray(c.guidance, \"content.guidance\", { maxItems: 16, maxLen: 300, minItems: 1 }),\n };\n}\n\n/**\n * Validate + normalize a section's `content` payload for its kind. Returns\n * the normalized content to write; throws {@link BrandInputError} on an\n * unknown kind or an invalid payload.\n */\nexport function assertSectionContent(kind: string, content: unknown): Record<string, unknown> {\n if (!isRecord(content)) throw new BrandInputError(\"content must be an object\");\n switch (kind) {\n case \"palette\":\n return { ...assertPaletteSection(content) };\n case \"typography\":\n return { ...assertTypographySection(content) };\n case \"voice\":\n return { ...assertVoiceSection(content) };\n case \"logo\":\n return { ...assertLogoSection(content) };\n case \"imagery\":\n return { ...assertImagerySection(content) };\n default:\n throw new BrandInputError(`unknown section kind ${kind}; expected one of: ${SECTION_KINDS.join(\", \")}`);\n }\n}\n\n/**\n * Validate an upload file name for an R2 key. Path/URL delimiters and control\n * characters are rejected; leading dots are stripped and length is capped.\n */\nexport function safeFileName(name: unknown): string {\n if (typeof name !== \"string\") throw new BrandInputError(\"file name must be a string\");\n // eslint-disable-next-line no-control-regex\n if (/[/\\\\?#%\\u0000-\\u001f\\u007f]/.test(name))\n throw new BrandInputError(\"file name must not contain path or URL delimiter characters\");\n const cleaned = name\n .trim()\n .replace(/^\\.+/, \"\");\n if (cleaned === \"\" || cleaned === \".\" || cleaned === \"..\")\n throw new BrandInputError(\"file name is empty or a dot segment after sanitizing\");\n return cleaned.slice(0, 120);\n}\n\n/**\n * Assert an upload content type is allowed FOR ITS KIND, and return the\n * normalized bare type (case-folded, `; charset=…` stripped).\n *\n * The allowlist is per-kind, not global: `design` accepts\n * {@link DESIGN_CONTENT_TYPES} and nothing else, every other kind accepts\n * {@link ASSET_CONTENT_TYPES} and nothing else. The two sets are disjoint on\n * purpose — it must be impossible to store HTML under a kind whose bytes are\n * handed out by signed URL, or to store an image under the kind the preview\n * route serves as a document.\n */\nexport function assertAssetContentType(value: unknown, kind?: string): string {\n if (typeof value !== \"string\") throw new BrandInputError(\"contentType must be a string\");\n const ct = value.split(\";\")[0]!.trim().toLowerCase();\n const allowed = kind === DESIGN_ASSET_KIND ? DESIGN_CONTENT_TYPES : ASSET_CONTENT_TYPES;\n if (!allowed.has(ct))\n throw new BrandInputError(\n `unsupported content type ${ct || \"(empty)\"} for kind ${kind ?? \"other\"}; allowed: ${[...allowed].join(\", \")}`,\n );\n return ct;\n}\n\n/**\n * Validate + normalize an agent's asset analysis: description ≤ 2000 chars,\n * ≤ 12 dominant colors (each normalized hex), ≤ 24 tags of ≤ 60 chars.\n */\nexport function assertAnalysis(value: unknown): AssetAnalysis {\n if (!isRecord(value)) throw new BrandInputError(\"analysis must be an object\");\n const colors = value.dominantColors;\n if (!Array.isArray(colors)) throw new BrandInputError(\"analysis.dominantColors must be an array\");\n if (colors.length > 12)\n throw new BrandInputError(\"analysis.dominantColors must have at most 12 entries\");\n return {\n description: capString(value.description, \"analysis.description\", 2000),\n dominantColors: colors.map((c, i) => assertHex(c, `analysis.dominantColors[${i}]`)),\n tags: capStringArray(value.tags, \"analysis.tags\", { maxItems: 24, maxLen: 60 }),\n };\n}\n","const record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null);\n\n/** Stay materially below the server's whole-guards parser budget. */\nexport function isBoundedBrandJson(\n root: unknown,\n limits: { maxDepth?: number; maxNodes?: number; maxBytes?: number } = {},\n): boolean {\n const maxDepth = limits.maxDepth ?? 12;\n const maxNodes = limits.maxNodes ?? 2_048;\n const maxBytes = limits.maxBytes ?? 32 * 1024;\n const stack: Array<{ value: unknown; depth: number }> = [{\n value: root,\n depth: 0,\n }];\n const seen = new Set<object>();\n let nodes = 0;\n while (stack.length) {\n const { value, depth } = stack.pop()!;\n if (++nodes > maxNodes || depth > maxDepth) return false;\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) continue;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) return false;\n continue;\n }\n if (typeof value !== \"object\" || seen.has(value)) return false;\n seen.add(value);\n if (Array.isArray(value)) {\n for (const child of value)\n stack.push({ value: child, depth: depth + 1 });\n } else if (record(value)) {\n for (const child of Object.values(value))\n stack.push({ value: child, depth: depth + 1 });\n } else {\n return false;\n }\n }\n try {\n return new TextEncoder().encode(JSON.stringify(root)).byteLength <= maxBytes;\n } catch {\n return false;\n }\n}\n\nfunction canonical(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n const row = value as Record<string, unknown>;\n return `{${Object.keys(row).sort().map((key) =>\n `${JSON.stringify(key)}:${canonical(row[key])}`).join(\",\")}}`;\n}\n\n/** Deterministic JSON with recursively sorted object keys. */\nexport function canonicalBrandJson(value: unknown): string {\n if (!isBoundedBrandJson(value, {\n maxDepth: 20,\n maxNodes: 8_192,\n maxBytes: 128 * 1024,\n })) throw new TypeError(\"brand digest input must be bounded finite JSON\");\n return canonical(value);\n}\n\n/** `sha256:<hex>` over {@link canonicalBrandJson}. */\nexport async function brandJsonDigest(value: unknown): Promise<string> {\n const bytes = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(canonicalBrandJson(value)),\n );\n return `sha256:${[...new Uint8Array(bytes)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n","// Bounded canonical JSON and self-consistency checks for Brand review and\n// approval records. A local digest is not an authenticity proof: authenticity\n// comes from the credential-bound central authority consumption embedded in\n// the receipt.\nimport { PROPOSAL_KINDS } from \"./constants\";\nexport { proposalAsWritten, receiptAsWritten, rowAsWritten } from \"./read-shape\";\nimport type {\n BrandApprovalReceipt,\n BrandHumanAuthorityConsumption,\n BrandProposalReviewSnapshot,\n} from \"./types\";\nimport {\n brandJsonDigest,\n isBoundedBrandJson,\n} from \"./review-json\";\n\nexport {\n brandJsonDigest,\n canonicalBrandJson,\n isBoundedBrandJson,\n} from \"./review-json\";\n\nconst DIGEST = /^sha256:[0-9a-f]{64}$/;\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);\nconst exactKeys = (value: Record<string, unknown>, required: readonly string[], optional: readonly string[] = []) => {\n const allowed = new Set([...required, ...optional]);\n return required.every((key) => Object.hasOwn(value, key)) &&\n Object.keys(value).every((key) => allowed.has(key));\n};\nconst boundedString = (value: unknown, max = 200): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= max;\nconst safeTime = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\n/** Stable local reference to one immutable central grant revision. */\nexport function brandAuthorityRef(\n consumption: Pick<BrandHumanAuthorityConsumption, \"grantId\" | \"grantVersion\">,\n): string {\n return `authority:${consumption.grantId}:v${consumption.grantVersion}`;\n}\n\nconst SNAPSHOT_REQUIRED = [\n \"id\", \"bookId\", \"kind\", \"status\", \"payload\", \"rationale\", \"provenance\",\n \"reviewDigest\", \"audience\", \"createdBy\", \"createdAuthorityRef\", \"createdAt\",\n] as const;\n\nfunction validSnapshotShape(value: unknown): value is BrandProposalReviewSnapshot {\n if (!record(value) || !exactKeys(value, SNAPSHOT_REQUIRED)) return false;\n const provenance = value.provenance;\n return boundedString(value.id) &&\n boundedString(value.bookId) &&\n typeof value.kind === \"string\" &&\n (PROPOSAL_KINDS as readonly string[]).includes(value.kind) &&\n value.status === \"open\" &&\n record(value.payload) &&\n boundedString(value.rationale, 2_000) &&\n record(provenance) &&\n exactKeys(provenance, [\n \"sourceAssetId\", \"sourceAsset\", \"messageId\", \"turnId\", \"taintLabels\",\n ]) &&\n (provenance.sourceAssetId === null ||\n boundedString(provenance.sourceAssetId)) &&\n (provenance.sourceAsset === null ||\n (record(provenance.sourceAsset) &&\n exactKeys(provenance.sourceAsset, [\n \"assetId\", \"contentDigest\", \"objectEtag\", \"objectSize\", \"pathDigest\",\n \"contentType\", \"analysisRevision\", \"analysisDigest\",\n ]) &&\n boundedString(provenance.sourceAsset.assetId) &&\n typeof provenance.sourceAsset.contentDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.contentDigest) &&\n boundedString(provenance.sourceAsset.objectEtag) &&\n Number.isSafeInteger(provenance.sourceAsset.objectSize) &&\n (provenance.sourceAsset.objectSize as number) > 0 &&\n typeof provenance.sourceAsset.pathDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.pathDigest) &&\n (provenance.sourceAsset.contentType === null ||\n boundedString(provenance.sourceAsset.contentType, 160)) &&\n (provenance.sourceAsset.analysisRevision === null ||\n (Number.isSafeInteger(provenance.sourceAsset.analysisRevision) &&\n (provenance.sourceAsset.analysisRevision as number) >= 0)) &&\n (provenance.sourceAsset.analysisDigest === null ||\n (typeof provenance.sourceAsset.analysisDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.analysisDigest))))) &&\n ((provenance.sourceAssetId === null && provenance.sourceAsset === null) ||\n (provenance.sourceAssetId !== null &&\n provenance.sourceAsset !== null &&\n provenance.sourceAsset.assetId === provenance.sourceAssetId)) &&\n (provenance.messageId === null || boundedString(provenance.messageId)) &&\n (provenance.turnId === null || boundedString(provenance.turnId)) &&\n Array.isArray(provenance.taintLabels) &&\n provenance.taintLabels.length <= 16 &&\n provenance.taintLabels.every((label) => boundedString(label, 120)) &&\n new Set(provenance.taintLabels).size === provenance.taintLabels.length &&\n typeof value.reviewDigest === \"string\" && DIGEST.test(value.reviewDigest) &&\n Array.isArray(value.audience) &&\n value.audience.length > 0 && value.audience.length <= 100 &&\n value.audience.every((id) => boundedString(id)) &&\n new Set(value.audience).size === value.audience.length &&\n boundedString(value.createdBy) &&\n boundedString(value.createdAuthorityRef) &&\n safeTime(value.createdAt);\n}\n\nconst CONSUMPTION_REQUIRED = [\n \"id\", \"grantId\", \"grantVersion\", \"useNumber\", \"actorPrincipalId\",\n \"actorKind\", \"credentialId\", \"credentialKind\", \"appId\", \"appIncarnation\",\n \"capability\",\n \"projectCapability\", \"effect\", \"actionDigest\", \"resourceDigest\",\n \"constraintEvidence\",\n \"consumptionIdempotencyKey\", \"requestDigest\", \"consumedAt\",\n] as const;\n\n/** Validate the exact direct-human central authority receipt shape. */\nexport function isBrandHumanAuthorityConsumption(\n value: unknown,\n): value is BrandHumanAuthorityConsumption {\n if (!record(value) || !exactKeys(value, CONSUMPTION_REQUIRED)) return false;\n return boundedString(value.id) &&\n boundedString(value.grantId) &&\n Number.isSafeInteger(value.grantVersion) && (value.grantVersion as number) > 0 &&\n Number.isSafeInteger(value.useNumber) && (value.useNumber as number) > 0 &&\n boundedString(value.actorPrincipalId) &&\n value.actorKind === \"human\" &&\n boundedString(value.credentialId) &&\n value.credentialKind === \"clerk\" &&\n boundedString(value.appId) &&\n typeof value.appIncarnation === \"string\" &&\n /^[a-f0-9]{32}$/.test(value.appIncarnation) &&\n value.capability === \"brand.proposal.resolve\" &&\n value.projectCapability === \"brand.approve\" &&\n value.effect === \"internal\" &&\n typeof value.actionDigest === \"string\" && DIGEST.test(value.actionDigest) &&\n typeof value.resourceDigest === \"string\" && DIGEST.test(value.resourceDigest) &&\n record(value.constraintEvidence) &&\n boundedString(value.consumptionIdempotencyKey) &&\n typeof value.requestDigest === \"string\" && DIGEST.test(value.requestDigest) &&\n safeTime(value.consumedAt);\n}\n\nconst RECEIPT_REQUIRED = [\n \"version\", \"id\", \"mutationKey\", \"bookId\", \"proposalId\", \"resolution\",\n \"reviewedProposal\", \"actionDigest\", \"decisionBinding\", \"approvedBy\", \"approvedByKind\",\n \"appliedBy\", \"appliedByKind\", \"authorityRef\", \"authorityCapability\",\n \"authorityConsumption\", \"createdAt\", \"receiptDigest\",\n] as const;\n\n/** Verify exact shape, cross-field bindings, and every local digest. This\n * proves receipt self-consistency only; the host must authenticate the\n * central consumption behind `authorityConsumption.id`. */\nexport async function verifyBrandApprovalReceipt(receipt: unknown): Promise<boolean> {\n try {\n if (!isBoundedBrandJson(receipt, { maxDepth: 14, maxNodes: 2_500, maxBytes: 48 * 1024 }))\n return false;\n if (!record(receipt) || !exactKeys(receipt, RECEIPT_REQUIRED, [\"paletteId\", \"resolutionNote\"]))\n return false;\n const binding = receipt.decisionBinding;\n if (\n receipt.version !== 1 ||\n !boundedString(receipt.id) ||\n !boundedString(receipt.mutationKey) ||\n !boundedString(receipt.bookId) ||\n !boundedString(receipt.proposalId) ||\n (receipt.resolution !== \"accepted\" && receipt.resolution !== \"rejected\") ||\n !validSnapshotShape(receipt.reviewedProposal) ||\n typeof receipt.actionDigest !== \"string\" || !DIGEST.test(receipt.actionDigest) ||\n !record(binding) ||\n !exactKeys(binding, [\n \"version\", \"bookVersion\", \"activationRevision\", \"activePaletteId\",\n \"memberIdsDigest\", \"activePaletteDigest\", \"typographyDigest\",\n \"sourceAssetDigest\", \"effectDigest\",\n ]) ||\n binding.version !== 1 ||\n !Number.isSafeInteger(binding.bookVersion) || (binding.bookVersion as number) < 1 ||\n !Number.isSafeInteger(binding.activationRevision) ||\n (binding.activationRevision as number) < 0 ||\n (binding.activePaletteId !== null && !boundedString(binding.activePaletteId)) ||\n typeof binding.memberIdsDigest !== \"string\" || !DIGEST.test(binding.memberIdsDigest) ||\n (binding.activePaletteDigest !== null &&\n (typeof binding.activePaletteDigest !== \"string\" ||\n !DIGEST.test(binding.activePaletteDigest))) ||\n (binding.typographyDigest !== null &&\n (typeof binding.typographyDigest !== \"string\" ||\n !DIGEST.test(binding.typographyDigest))) ||\n (binding.sourceAssetDigest !== null &&\n (typeof binding.sourceAssetDigest !== \"string\" ||\n !DIGEST.test(binding.sourceAssetDigest))) ||\n typeof binding.effectDigest !== \"string\" || !DIGEST.test(binding.effectDigest) ||\n !boundedString(receipt.approvedBy) ||\n receipt.approvedByKind !== \"human\" ||\n !boundedString(receipt.appliedBy) ||\n receipt.appliedByKind !== \"human\" ||\n !boundedString(receipt.authorityRef) ||\n receipt.authorityCapability !== \"brand.approve\" ||\n !isBrandHumanAuthorityConsumption(receipt.authorityConsumption) ||\n !safeTime(receipt.createdAt) ||\n typeof receipt.receiptDigest !== \"string\" || !DIGEST.test(receipt.receiptDigest) ||\n (receipt.paletteId !== undefined && !boundedString(receipt.paletteId)) ||\n (receipt.resolutionNote !== undefined && !boundedString(receipt.resolutionNote, 1_000))\n ) return false;\n\n const reviewed = receipt.reviewedProposal;\n const authority = receipt.authorityConsumption;\n if (\n reviewed.id !== receipt.proposalId ||\n reviewed.bookId !== receipt.bookId ||\n receipt.approvedBy !== receipt.appliedBy ||\n authority.actorPrincipalId !== receipt.approvedBy ||\n authority.actionDigest !== receipt.actionDigest ||\n authority.consumptionIdempotencyKey !== receipt.mutationKey ||\n receipt.authorityRef !== brandAuthorityRef(authority) ||\n authority.consumedAt > receipt.createdAt ||\n (receipt.resolution === \"rejected\" && receipt.paletteId !== undefined) ||\n (receipt.resolution === \"accepted\" && reviewed.kind === \"palette\" && !receipt.paletteId) ||\n (reviewed.kind !== \"palette\" && receipt.paletteId !== undefined)\n ) return false;\n\n const { reviewDigest, ...unsignedReview } = reviewed;\n if ((await brandJsonDigest(unsignedReview)) !== reviewDigest) return false;\n const expectedAction = await brandJsonDigest({\n version: 1,\n reviewedProposal: reviewed,\n resolution: receipt.resolution,\n resolutionNote: receipt.resolutionNote ?? null,\n paletteId: receipt.paletteId ?? null,\n decisionBinding: binding,\n });\n if (expectedAction !== receipt.actionDigest) return false;\n if ((await brandJsonDigest({ bookId: receipt.bookId, proposalId: receipt.proposalId })) !==\n authority.resourceDigest) return false;\n\n const { receiptDigest, ...immutable } = receipt;\n return (await brandJsonDigest(immutable)) === receiptDigest;\n } catch {\n return false;\n }\n}\n","/** Brand resources that can be shared into a Discussion message. */\nexport const BRAND_DISCUSSION_REFERENCE_KINDS = [\n \"brand:book\",\n \"brand:asset\",\n \"brand:palette\",\n \"brand:proposal\",\n \"brand:receipt\",\n] as const;\n\n/** One Brand resource kind understood by the native Brand destination. */\nexport type BrandDiscussionReferenceKind =\n (typeof BRAND_DISCUSSION_REFERENCE_KINDS)[number];\n\n/** Canonical Brand destination target parsed from an `odla-ref` deep link. */\nexport interface BrandDiscussionReferenceTarget {\n kind: BrandDiscussionReferenceKind;\n bookId: string;\n resourceId?: string;\n}\n\n/** Bounded color projection shared with Discussion people and agents. */\nexport interface BrandDiscussionSwatch {\n /** Semantic role used by the Brand token compiler. */\n role: string;\n /** Normalized opaque sRGB color (`#rrggbb`). */\n hex: string;\n /** Optional product-authored color name. */\n name?: string;\n}\n\n/** Product-owned projection returned to Discussion typeahead and exact lookup. */\nexport interface BrandDiscussionReference {\n /** Canonical Brand kind used in stored Discussion ref markup. */\n kind: BrandDiscussionReferenceKind;\n /** Opaque durable product id; never infer membership from its segments. */\n id: string;\n /** Product-authored primary display name. */\n label: string;\n /** Short product-authored secondary context for the picker. */\n hint: string;\n /** Bounded product-authored context safe to show an LLM or person. */\n summary: string;\n /** Current product status at inspection time. */\n status: string;\n /** Human-readable native surface the link opens. */\n destination: string;\n /** Same-origin native link; navigation is not mutation authority. */\n href: string;\n /** Present only for a validated Brand palette, capped by Brand's swatch limit. */\n swatches?: BrandDiscussionSwatch[];\n}\n\nconst SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._~-]{0,199}$/;\n\n/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */\nexport function brandDiscussionReferenceId(\n target: BrandDiscussionReferenceTarget,\n): string {\n return target.resourceId\n ? `${target.bookId}/${target.resourceId}`\n : target.bookId;\n}\n\n/** Canonical value stored in the stable `odla-ref` query parameter. */\nexport function formatBrandDiscussionReference(\n target: BrandDiscussionReferenceTarget,\n): string {\n return `${target.kind}/${brandDiscussionReferenceId(target)}`;\n}\n\n/** Parse and validate a Brand `odla-ref`; malformed and cross-product refs fail closed. */\nexport function parseBrandDiscussionReference(\n input: URL | string,\n): BrandDiscussionReferenceTarget | null {\n let raw: string | null;\n try {\n raw = input instanceof URL\n ? input.searchParams.get(\"odla-ref\")\n : new URL(input, \"https://brand.invalid\").searchParams.get(\"odla-ref\");\n } catch {\n return null;\n }\n if (!raw) return null;\n const [kind, bookId, resourceId, extra] = raw.split(\"/\");\n if (\n extra !== undefined ||\n !BRAND_DISCUSSION_REFERENCE_KINDS.includes(\n kind as BrandDiscussionReferenceKind,\n ) ||\n !bookId ||\n !SEGMENT.test(bookId)\n ) return null;\n const typedKind = kind as BrandDiscussionReferenceKind;\n if (typedKind === \"brand:book\") {\n return resourceId === undefined ? { kind: typedKind, bookId } : null;\n }\n return resourceId && SEGMENT.test(resourceId)\n ? { kind: typedKind, bookId, resourceId }\n : null;\n}\n\n/** Build the native Brand deep link while preserving the deployed origin. */\nexport function brandDiscussionReferenceHref(\n current: URL,\n target: BrandDiscussionReferenceTarget,\n basePath = \"/\",\n): string {\n const next = new URL(current.origin);\n next.pathname = basePath.startsWith(\"/\") ? basePath : `/${basePath}`;\n next.searchParams.set(\"odla-ref\", formatBrandDiscussionReference(target));\n return next.toString();\n}\n","// Pure op-builders for brand_book rows: (input) -> BrandOp[]. No I/O — this\n// is the unit-test seam (assert the emitted ops); routes and the skill share\n// these so every write path commits identical shapes.\nimport { BOOK_STATUSES, BRAND_NS, type BookStatus } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandAttrs, BrandBook, BrandEntityRef, BrandOp } from \"../types\";\nimport { capString } from \"../validate\";\n\nconst SLUG_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/** Input to {@link createBookOps}. `memberIds` is the full auth roster —\n * include the bot agent's id so it can pass the audience rules. */\nexport interface CreateBookInput {\n id: string;\n slug: string;\n name: string;\n ownerId: string;\n createdAuthorityRef: string;\n memberIds: string[];\n channelId?: string;\n now: number;\n}\n\n/**\n * Ops to create a brand book: one `brand_book` row in `draft` status with the\n * id mirrored as an attr (odla-db ids aren't attrs), the owner always folded\n * into the deduplicated `memberIds` roster (the create rule requires it), and\n * both timestamps set to `now`.\n */\nexport function createBookOps(input: CreateBookInput): BrandOp[] {\n const slug = capString(input.slug, \"slug\", 80);\n if (!SLUG_RE.test(slug))\n throw new BrandInputError(\"slug must be lowercase letters, digits, and inner hyphens\");\n const name = capString(input.name, \"name\", 120);\n const ownerId = capString(input.ownerId, \"ownerId\", 160);\n const createdAuthorityRef = capString(input.createdAuthorityRef, \"createdAuthorityRef\", 200);\n const memberIds = Array.from(new Set([ownerId, ...input.memberIds.map((id, index) =>\n capString(id, `memberIds[${index}]`, 160))]));\n if (memberIds.length > 100)\n throw new BrandInputError(\"a brand book supports at most 100 members\");\n return [\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: input.id,\n attrs: {\n id: input.id,\n version: 1,\n slug,\n name,\n status: \"draft\",\n ownerId,\n createdAuthorityRef,\n memberIds,\n activationRevision: 0,\n createdAt: input.now,\n updatedAt: input.now,\n ...(input.channelId ? { channelId: input.channelId } : {}),\n },\n },\n ];\n}\n\n// Patchable book columns, and which of them may be cleared with `null`\n// (required attrs can't be retracted — the final-state schema check fails).\nconst PATCHABLE = new Set([\"name\", \"status\", \"channelId\", \"summary\"]);\nconst CLEARABLE = new Set([\"channelId\", \"summary\"]);\n\nfunction validateBookField(key: string, value: unknown): unknown {\n switch (key) {\n case \"name\":\n return capString(value, \"name\", 120);\n case \"status\":\n if (typeof value !== \"string\" || !(BOOK_STATUSES as readonly string[]).includes(value))\n throw new BrandInputError(`status must be one of: ${BOOK_STATUSES.join(\", \")}`);\n return value as BookStatus;\n case \"channelId\":\n return capString(value, \"channelId\", 128);\n case \"summary\":\n return capString(value, \"summary\", 2000);\n default:\n return value;\n }\n}\n\n/**\n * Ops to patch a brand book. `null` means CLEAR (a `retract` op — odla-db has\n * no storable scalar null) and is only allowed on optional columns;\n * `undefined` keys are dropped. Any write stamps `updatedAt`; an empty\n * effective patch emits no ops at all.\n */\nexport function updateBookOps(\n bookId: BrandEntityRef,\n patch: Record<string, unknown>,\n now: number,\n): BrandOp[] {\n const attrs: BrandAttrs = {};\n const retract: string[] = [];\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue;\n if (!PATCHABLE.has(key)) throw new BrandInputError(`unknown book field: ${key}`);\n if (value === null) {\n if (!CLEARABLE.has(key)) throw new BrandInputError(`${key} is required and cannot be cleared`);\n retract.push(key);\n continue;\n }\n attrs[key] = validateBookField(key, value);\n }\n if (Object.keys(attrs).length === 0 && retract.length === 0) return [];\n const ops: BrandOp[] = [\n { t: \"update\", ns: BRAND_NS.book, id: bookId, attrs: { ...attrs, updatedAt: now } },\n ];\n if (retract.length > 0) ops.push({ t: \"retract\", ns: BRAND_NS.book, id: bookId, attrs: retract });\n return ops;\n}\n\n/** The child rows whose `audience` snapshots a roster change must rewrite.\n * Pass the rows you queried — the builder stays pure. */\nexport interface AudienceChildren {\n sections?: Array<{ id: string }>;\n palettes?: Array<{ id: string }>;\n proposals?: Array<{ id: string }>;\n assets?: Array<{ id: string }>;\n}\n\n/**\n * Ops to change a book's roster: rewrite `memberIds` (owner always kept) and\n * fan the new list out to every child row's denormalized `audience` snapshot.\n * Query the children first and pass them in — this builder does no I/O, so\n * tests can assert the exact fan-out.\n */\nexport function audienceFanoutOps(\n book: Pick<BrandBook, \"id\" | \"ownerId\">,\n newMemberIds: string[],\n children: AudienceChildren,\n now: number,\n): BrandOp[] {\n const memberIds = Array.from(new Set([book.ownerId, ...newMemberIds]));\n const ops: BrandOp[] = [\n { t: \"update\", ns: BRAND_NS.book, id: book.id, attrs: { memberIds, updatedAt: now } },\n ];\n const fan = (ns: string, rows?: Array<{ id: string }>) => {\n for (const row of rows ?? []) ops.push({ t: \"update\", ns, id: row.id, attrs: { audience: memberIds } });\n };\n fan(BRAND_NS.section, children.sections);\n fan(BRAND_NS.palette, children.palettes);\n fan(BRAND_NS.proposal, children.proposals);\n fan(BRAND_NS.asset, children.assets);\n return ops;\n}\n","// Pure op-builder for brand_section rows. One section per (book, kind),\n// upserted through a natural-key Lookup ref so re-writing the same section\n// binds to the same row (no read-modify-write race, idempotent installs).\nimport { BRAND_NS, SECTION_STATUSES, type SectionKind, type SectionStatus } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandOp, BrandProposal } from \"../types\";\nimport { assertSectionContent, capString } from \"../validate\";\n\n/** The natural key a section row is upserted by: `${bookId}:${kind}`. */\nexport function sectionKey(bookId: string, kind: SectionKind): string {\n return `${bookId}:${kind}`;\n}\n\n/** Input to {@link upsertSectionOps}. `audience` is the book's roster\n * snapshot; `status` defaults to `draft` (a human approves later). */\nexport interface UpsertSectionInput {\n bookId: string;\n kind: SectionKind;\n content: Record<string, unknown>;\n status?: SectionStatus;\n audience: string[];\n updatedBy: string;\n now: number;\n approvalReceiptId?: string;\n approvalActionDigest?: string;\n}\n\n/**\n * Ops to create-or-replace a book's section of one kind: a single `update`\n * addressed by the `{ ns, attr: \"key\", value }` Lookup ref, carrying the\n * validated + normalized content (see `assertSectionContent`), the audience\n * snapshot, and the author/timestamp.\n */\nexport function upsertSectionOps(input: UpsertSectionInput): BrandOp[] {\n const status = input.status ?? \"draft\";\n if (!(SECTION_STATUSES as readonly string[]).includes(status))\n throw new BrandInputError(`status must be one of: ${SECTION_STATUSES.join(\", \")}`);\n const content = assertSectionContent(input.kind, input.content);\n if (\n status === \"approved\" &&\n (!input.approvalReceiptId || !input.approvalActionDigest)\n ) throw new BrandInputError(\"approved sections require approval receipt provenance\");\n const key = sectionKey(input.bookId, input.kind);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.section,\n id: { ns: BRAND_NS.section, attr: \"key\", value: key },\n attrs: {\n key,\n bookId: input.bookId,\n kind: input.kind,\n status,\n content,\n audience: input.audience,\n updatedBy: input.updatedBy,\n updatedAt: input.now,\n ...(input.approvalReceiptId\n ? { approvalReceiptId: capString(input.approvalReceiptId, \"approvalReceiptId\", 200) }\n : {}),\n ...(input.approvalActionDigest\n ? { approvalActionDigest: capString(input.approvalActionDigest, \"approvalActionDigest\", 80) }\n : {}),\n },\n },\n {\n t: \"link\",\n ns: BRAND_NS.section,\n id: { ns: BRAND_NS.section, attr: \"key\", value: key },\n label: \"book\",\n target: input.bookId,\n },\n ];\n}\n\n/** Input for an agent-authored non-palette facet proposal. */\nexport interface ProposeSectionInput {\n id: string;\n bookId: string;\n kind: Exclude<SectionKind, \"palette\">;\n content: Record<string, unknown>;\n rationale: string;\n audience: string[];\n createdBy: string;\n createdAuthorityRef: string;\n sourceAsset?: BrandProposal[\"provenance\"][\"sourceAsset\"];\n messageId: string;\n turnId: string;\n taintLabels: string[];\n now: number;\n}\n\n/** Validate a facet draft and park it as an immutable OPEN proposal. */\nexport async function proposeSectionOps(input: ProposeSectionInput): Promise<BrandOp[]> {\n if (input.taintLabels.length > 16)\n throw new BrandInputError(\"taintLabels must have at most 16 entries\");\n const proposal = {\n id: input.id,\n bookId: input.bookId,\n kind: input.kind,\n status: \"open\" as const,\n payload: { content: assertSectionContent(input.kind, input.content) },\n rationale: capString(input.rationale, \"rationale\", 2000),\n provenance: {\n sourceAssetId: input.sourceAsset?.assetId ?? null,\n sourceAsset: input.sourceAsset ?? null,\n messageId: capString(input.messageId, \"messageId\", 200),\n turnId: capString(input.turnId, \"turnId\", 200),\n taintLabels: [...new Set(input.taintLabels.map((label, index) =>\n capString(label, `taintLabels[${index}]`, 120)))].sort(),\n },\n audience: input.audience,\n createdBy: input.createdBy,\n createdAuthorityRef: input.createdAuthorityRef,\n createdAt: input.now,\n };\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.id,\n attrs: { ...proposal, reviewDigest: await brandJsonDigest(proposal) },\n },\n { t: \"link\", ns: BRAND_NS.proposal, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n","// Pure op-builders for the palette proposal flow: the agent proposes, a\n// HUMAN accepts or rejects. Acceptance is one atomic transact — palette row,\n// approved palette section, the book's `activePaletteId`, and the proposal's\n// resolution — so a book can never point at a palette that wasn't written.\n//\n// Note on op kinds: the design doc says \"book merge {activePaletteId}\", but\n// odla-db's `merge` op deep-merges JSON attributes only (the engine rejects\n// it on scalars) — a scalar write on an existing row is an attr-merge\n// `update`, which is what these builders emit.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandOp, BrandProposal } from \"../types\";\nimport { assertHex, assertSwatches, capString } from \"../validate\";\nimport { upsertSectionOps } from \"./sections\";\n\n/** Input to {@link proposePaletteOps}. `audience` is the book's roster\n * snapshot; `contrastReport` is stored verbatim in the payload for the\n * human reviewer. */\nexport interface ProposePaletteInput {\n id: string;\n bookId: string;\n name: string;\n rationale: string;\n swatches: unknown;\n seedHex?: string;\n contrastReport?: unknown;\n createdBy: string;\n createdAuthorityRef: string;\n audience: string[];\n sourceAsset?: BrandProposal[\"provenance\"][\"sourceAsset\"];\n messageId: string;\n turnId: string;\n taintLabels: string[];\n now: number;\n}\n\n/**\n * Ops to park a palette proposal for human review: one `brand_proposal` row,\n * `kind: \"palette\"`, `status: \"open\"`, with the validated swatches (and\n * optional seed/contrast report) in `payload`.\n */\nexport async function proposePaletteOps(input: ProposePaletteInput): Promise<BrandOp[]> {\n const name = capString(input.name, \"name\", 120);\n const rationale = capString(input.rationale, \"rationale\", 2000);\n const swatches = assertSwatches(input.swatches);\n const seedHex = input.seedHex === undefined ? undefined : assertHex(input.seedHex, \"seedHex\");\n if (input.taintLabels.length > 16)\n throw new BrandInputError(\"taintLabels must have at most 16 entries\");\n const payload: Record<string, unknown> = {\n name,\n swatches,\n ...(seedHex ? { seedHex } : {}),\n ...(input.contrastReport !== undefined ? { contrastReport: input.contrastReport } : {}),\n };\n const proposal = {\n id: input.id,\n bookId: input.bookId,\n kind: \"palette\" as const,\n status: \"open\" as const,\n payload,\n rationale,\n provenance: {\n sourceAssetId: input.sourceAsset?.assetId ?? null,\n sourceAsset: input.sourceAsset ?? null,\n messageId: capString(input.messageId, \"messageId\", 200),\n turnId: capString(input.turnId, \"turnId\", 200),\n taintLabels: [...new Set(input.taintLabels.map((label, index) =>\n capString(label, `taintLabels[${index}]`, 120)))].sort(),\n },\n audience: input.audience,\n createdBy: input.createdBy,\n createdAuthorityRef: input.createdAuthorityRef,\n createdAt: input.now,\n };\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.id,\n attrs: { ...proposal, reviewDigest: await brandJsonDigest(proposal) },\n },\n { t: \"link\", ns: BRAND_NS.proposal, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n\n/** Input to {@link acceptProposalOps}: the proposal row as read back, the id\n * to mint the palette under, and who resolved it. */\nexport interface AcceptProposalInput {\n proposal: BrandProposal;\n paletteId: string;\n resolvedBy: string;\n approvalReceiptId: string;\n approvalActionDigest: string;\n now: number;\n resolutionNote?: string;\n}\n\n/**\n * Ops to accept an OPEN palette proposal, all in one transact:\n * 1. the `brand_palette` row (source: `extracted` when the proposal came from\n * an asset, `derived` when seeded, else `manual`),\n * 2. the approved `palette` section upsert,\n * 3. the book's `activePaletteId` pointer,\n * 4. the proposal flipped to `accepted` with resolver + timestamp.\n * Throws on a non-palette or already-resolved proposal, or a payload that no\n * longer validates.\n */\nexport function acceptProposalOps(input: AcceptProposalInput): BrandOp[] {\n const {\n proposal,\n paletteId,\n resolvedBy,\n approvalReceiptId,\n approvalActionDigest,\n now,\n } = input;\n if (proposal.kind !== \"palette\")\n throw new BrandInputError(`proposal ${proposal.id} is a ${proposal.kind} proposal, not a palette`);\n if (proposal.status !== \"open\")\n throw new BrandInputError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n const payload = proposal.payload;\n const name = capString(payload.name, \"payload.name\", 120);\n const swatches = assertSwatches(payload.swatches);\n const seedHex = payload.seedHex === undefined ? undefined : assertHex(payload.seedHex, \"payload.seedHex\");\n const source = proposal.provenance.sourceAsset ? \"extracted\" : seedHex ? \"derived\" : \"manual\";\n return [\n {\n t: \"update\",\n ns: BRAND_NS.palette,\n id: paletteId,\n attrs: {\n id: paletteId,\n bookId: proposal.bookId,\n name,\n status: \"active\",\n swatches,\n source,\n rationale: proposal.rationale,\n proposalId: proposal.id,\n approvalReceiptId: capString(approvalReceiptId, \"approvalReceiptId\", 200),\n approvalActionDigest: capString(\n approvalActionDigest,\n \"approvalActionDigest\",\n 80,\n ),\n audience: proposal.audience,\n createdAt: now,\n updatedAt: now,\n ...(seedHex ? { seedHex } : {}),\n },\n },\n { t: \"link\", ns: BRAND_NS.palette, id: paletteId, label: \"book\", target: proposal.bookId },\n ...upsertSectionOps({\n bookId: proposal.bookId,\n kind: \"palette\",\n content: { paletteId, name, swatches },\n status: \"approved\",\n audience: proposal.audience,\n updatedBy: resolvedBy,\n approvalReceiptId,\n approvalActionDigest,\n now,\n }),\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: proposal.bookId,\n attrs: { activePaletteId: paletteId, updatedAt: now },\n },\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: proposal.id,\n attrs: {\n status: \"accepted\",\n resolvedBy,\n resolvedAt: now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n}\n\n/** Input to {@link rejectProposalOps}. */\nexport interface RejectProposalInput {\n proposal: BrandProposal;\n resolvedBy: string;\n now: number;\n resolutionNote?: string;\n}\n\n/**\n * Ops to reject an OPEN proposal (any kind): flip it to `rejected` with\n * resolver, timestamp, and the optional note. Nothing else is touched — the\n * proposal row itself is the audit trail.\n */\nexport function rejectProposalOps(input: RejectProposalInput): BrandOp[] {\n const { proposal, resolvedBy, now } = input;\n if (proposal.status !== \"open\")\n throw new BrandInputError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: proposal.id,\n attrs: {\n status: \"rejected\",\n resolvedBy,\n resolvedAt: now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n}\n","// Pure op-builders for brand_asset rows. Asset rows are worker-mediated\n// (rules deny everything): the caller uploads to storage FIRST, then commits\n// the mirroring row — and \"delete\" is a `deletedAt` tombstone (an attr-merge\n// `update`; odla-db's `merge` op is json-only), never a row delete, so\n// analyses and proposals that reference the asset stay coherent.\nimport { ASSET_KINDS, BRAND_NS, DESIGN_ASSET_KIND, type AssetKind } from \"../constants\";\nimport type { DesignDigest } from \"../design/types\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandEntityRef, BrandOp } from \"../types\";\nimport { assertAnalysis, assertAssetContentType, capString } from \"../validate\";\n\n/** Input to {@link createAssetOps} — the storage upload's receipt fields\n * (`path`/`size`) plus the declared kind and the book's audience. */\nexport interface CreateAssetInput {\n id: string;\n bookId: string;\n kind: AssetKind;\n path: string;\n storageObjectId: string;\n contentDigest: string;\n contentType: string;\n size: number;\n uploadedBy: string;\n uploadedAuthorityRef: string;\n audience: string[];\n title?: string;\n /** `design` kind only: the digest parsed from the uploaded bundle. */\n design?: DesignDigest;\n now: number;\n}\n\n/**\n * Ops to record one uploaded asset: a single `brand_asset` row mirroring the\n * storage object, with the content type re-checked against the allowlist and\n * the size required to be a positive byte count.\n */\nexport function createAssetOps(input: CreateAssetInput): BrandOp[] {\n if (!(ASSET_KINDS as readonly string[]).includes(input.kind))\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n const contentType = assertAssetContentType(input.contentType, input.kind);\n // The digest and the kind are two halves of one fact; letting them\n // disagree would leave an HTML asset no tool can read, or a digest\n // attached to a PNG.\n if (input.kind === DESIGN_ASSET_KIND && input.design === undefined)\n throw new BrandInputError(\"a design asset must carry its parsed digest\");\n if (input.kind !== DESIGN_ASSET_KIND && input.design !== undefined)\n throw new BrandInputError(`only ${DESIGN_ASSET_KIND} assets may carry a design digest`);\n if (typeof input.size !== \"number\" || !Number.isFinite(input.size) || input.size <= 0)\n throw new BrandInputError(\"size must be a positive byte count\");\n if (!/^sha256:[0-9a-f]{64}$/.test(input.contentDigest))\n throw new BrandInputError(\"contentDigest must be a SHA-256 digest\");\n const title = input.title === undefined ? undefined : capString(input.title, \"title\", 160);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.asset,\n id: input.id,\n attrs: {\n id: input.id,\n bookId: input.bookId,\n kind: input.kind,\n path: capString(input.path, \"path\", 512),\n storageObjectId: capString(input.storageObjectId, \"storageObjectId\", 200),\n contentDigest: capString(input.contentDigest, \"contentDigest\", 80),\n contentType,\n size: input.size,\n status: \"live\",\n analysisRevision: 0,\n audience: input.audience,\n uploadedBy: input.uploadedBy,\n uploadedAuthorityRef: capString(\n input.uploadedAuthorityRef,\n \"uploadedAuthorityRef\",\n 200,\n ),\n createdAt: input.now,\n ...(title ? { title } : {}),\n ...(input.design ? { design: input.design } : {}),\n },\n },\n { t: \"link\", ns: BRAND_NS.asset, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n\n/**\n * Ops to tombstone an asset after its storage object was deleted: stamp\n * `deletedAt` in place. List reads exclude tombstoned rows; the row itself\n * stays for provenance.\n */\nexport function beginAssetDeleteOps(\n assetId: BrandEntityRef,\n now: number,\n deletedBy: string,\n deletedAuthorityRef: string,\n): BrandOp[] {\n return [{\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: {\n status: \"deleting\",\n deletedAt: now,\n deletedBy: capString(deletedBy, \"deletedBy\", 160),\n deletedAuthorityRef: capString(deletedAuthorityRef, \"deletedAuthorityRef\", 200),\n },\n }];\n}\n\n/** Complete a previously authorized deletion after storage is tombstoned. */\nexport function finishAssetDeleteOps(assetId: BrandEntityRef): BrandOp[] {\n return [{\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: { status: \"deleted\" },\n }];\n}\n\n/**\n * Ops to record an agent's analysis of an asset: the validated + capped\n * analysis json plus `analyzedAt`. Replaces any prior analysis whole.\n */\nexport async function recordAnalysisOps(\n assetId: BrandEntityRef,\n analysis: unknown,\n priorRevision: number,\n analyzedBy: string,\n analyzedAuthorityRef: string,\n now: number,\n): Promise<BrandOp[]> {\n if (!Number.isSafeInteger(priorRevision) || priorRevision < 0)\n throw new BrandInputError(\"prior analysis revision must be a non-negative integer\");\n const normalized = assertAnalysis(analysis);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: {\n analysis: normalized,\n analysisRevision: priorRevision + 1,\n analysisDigest: await brandJsonDigest(normalized),\n analyzedBy: capString(analyzedBy, \"analyzedBy\", 160),\n analyzedAuthorityRef: capString(\n analyzedAuthorityRef,\n \"analyzedAuthorityRef\",\n 200,\n ),\n analyzedAt: now,\n },\n },\n ];\n}\n","// Parser for the Claude Design standalone-HTML bundle format.\n//\n// Scanning is deliberately indexOf-based rather than regex-based: a bundle is\n// routinely megabytes of base64 on a single line, where a `[\\s\\S]*?` pattern\n// is both slow and a backtracking risk. Every scan here is linear.\n//\n// Asset PAYLOADS are never decoded — only measured. A manifest entry's byte\n// length is derived from its base64 length, so parsing a 30 MB bundle costs\n// one JSON.parse and no binary allocation.\nimport { BrandInputError } from \"../errors\";\nimport type { DesignBundle, DesignBundleAsset } from \"./types\";\n\n/** Longest poster SVG carried into a digest; larger ones are dropped. */\nexport const MAX_THUMBNAIL_CHARS = 16_384;\n\nconst ISLAND_TYPES = [\"manifest\", \"ext_resources\", \"page_order\", \"template\"] as const;\ntype IslandType = (typeof ISLAND_TYPES)[number];\n\n/** Extract one `<script type=\"__bundler/NAME\">` island's raw text. */\nfunction island(html: string, name: IslandType): string | null {\n const open = `<script type=\"__bundler/${name}\">`;\n const start = html.indexOf(open);\n if (start < 0) return null;\n const from = start + open.length;\n const end = html.indexOf(\"</script>\", from);\n return end < 0 ? null : html.slice(from, end);\n}\n\n/**\n * Cheap structural sniff: does this text look like a Claude Design bundle?\n * Checks for the two islands that carry the design itself, so a plain HTML\n * page (or an unrelated file that happens to be HTML) is rejected before any\n * parsing work happens.\n */\nexport function isDesignBundle(html: string): boolean {\n return (\n html.includes('<script type=\"__bundler/manifest\">') &&\n html.includes('<script type=\"__bundler/template\">')\n );\n}\n\n/** Decoded byte length of a base64 payload, without decoding it. */\nexport function base64ByteLength(data: string): number {\n const len = data.length;\n if (len === 0) return 0;\n const pad = data.endsWith(\"==\") ? 2 : data.endsWith(\"=\") ? 1 : 0;\n return Math.max(0, Math.floor((len * 3) / 4) - pad);\n}\n\nfunction parseIslandJson(text: string, name: IslandType): unknown {\n try {\n return JSON.parse(text);\n } catch {\n throw new BrandInputError(`design bundle's ${name} island is not valid JSON`);\n }\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Manifest object → payload-free asset summaries, in manifest order. */\nfunction readAssets(raw: unknown): DesignBundleAsset[] {\n if (!isRecord(raw)) throw new BrandInputError(\"design bundle's manifest island must be an object\");\n const assets: DesignBundleAsset[] = [];\n for (const [uuid, value] of Object.entries(raw)) {\n if (!isRecord(value)) continue;\n const data = value.data;\n const mime = value.mime;\n if (typeof data !== \"string\" || typeof mime !== \"string\") continue;\n assets.push({\n uuid,\n mime: mime.slice(0, 120),\n bytes: base64ByteLength(data),\n compressed: value.compressed === true,\n });\n }\n return assets;\n}\n\n/** ext_resources array → the CDN URLs the design was authored against. */\nfunction readExternals(raw: unknown): string[] {\n if (raw === null || raw === undefined) return [];\n if (!Array.isArray(raw))\n throw new BrandInputError(\"design bundle's ext_resources island must be an array\");\n const out: string[] = [];\n for (const entry of raw) {\n if (isRecord(entry) && typeof entry.id === \"string\") out.push(entry.id.slice(0, 512));\n }\n return out;\n}\n\n/** page_order array → nested page-bundle uuids. */\nfunction readPageOrder(raw: unknown): string[] {\n if (raw === null || raw === undefined) return [];\n if (!Array.isArray(raw))\n throw new BrandInputError(\"design bundle's page_order island must be an array\");\n return raw.filter((v): v is string => typeof v === \"string\");\n}\n\n/**\n * The loader's poster: the `<svg>` inside `#__bundler_thumbnail`. It renders\n * with no JavaScript and no blob URLs, so it is the one part of a design that\n * can be shown anywhere. Returns undefined when absent or over\n * {@link MAX_THUMBNAIL_CHARS}.\n */\nexport function extractThumbnailSvg(html: string): string | undefined {\n const anchor = html.indexOf(\"__bundler_thumbnail\");\n if (anchor < 0) return undefined;\n const open = html.indexOf(\"<svg\", anchor);\n if (open < 0) return undefined;\n const close = html.indexOf(\"</svg>\", open);\n if (close < 0) return undefined;\n const svg = html.slice(open, close + \"</svg>\".length);\n return svg.length > MAX_THUMBNAIL_CHARS ? undefined : svg;\n}\n\n/** One manifest entry WITH its base64 payload. */\nexport interface DesignManifestEntry {\n mime: string;\n compressed: boolean;\n /** Base64 payload, gzipped first when `compressed`. */\n data: string;\n}\n\n/**\n * Read the manifest island's entries INCLUDING their payloads, keyed by uuid.\n *\n * Everything else in this module deliberately leaves payloads encoded and\n * only measures them, because the worker never needs the bytes. This is the\n * one exception, for callers that genuinely write assets out — the CLI's\n * `brand design unpack`. It holds the whole manifest in memory, so use it\n * only where that is affordable.\n */\nexport function readDesignManifest(html: string): Record<string, DesignManifestEntry> {\n const raw = island(html, \"manifest\");\n if (raw === null) throw new BrandInputError(\"design bundle has no manifest island\");\n const parsed = parseIslandJson(raw, \"manifest\");\n if (!isRecord(parsed)) throw new BrandInputError(\"design bundle's manifest island must be an object\");\n const out: Record<string, DesignManifestEntry> = {};\n for (const [uuid, value] of Object.entries(parsed)) {\n if (!isRecord(value)) continue;\n const { data, mime } = value;\n if (typeof data !== \"string\" || typeof mime !== \"string\") continue;\n out[uuid] = { mime, compressed: value.compressed === true, data };\n }\n return out;\n}\n\n/**\n * Parse a Claude Design standalone-HTML export into its parts: the real\n * document (JSON-decoded from the template island), payload-free manifest\n * summaries, the external-resource index, nested page uuids, and the poster\n * SVG.\n *\n * Throws {@link BrandInputError} when the text is not a bundle or an island\n * is malformed — the messages are safe to return to a caller as a 400.\n */\nexport function parseDesignBundle(html: string): DesignBundle {\n if (!isDesignBundle(html))\n throw new BrandInputError(\n \"not a Claude Design bundle: no __bundler/manifest and __bundler/template script islands. \" +\n \"Export the design as standalone HTML and upload that file.\",\n );\n const templateRaw = island(html, \"template\");\n if (templateRaw === null)\n throw new BrandInputError(\"design bundle's template island is unterminated\");\n const template = parseIslandJson(templateRaw, \"template\");\n if (typeof template !== \"string\")\n throw new BrandInputError(\"design bundle's template island must be a JSON string\");\n\n const manifestRaw = island(html, \"manifest\");\n if (manifestRaw === null)\n throw new BrandInputError(\"design bundle's manifest island is unterminated\");\n\n const extRaw = island(html, \"ext_resources\");\n const pageRaw = island(html, \"page_order\");\n const thumbnailSvg = extractThumbnailSvg(html);\n return {\n template,\n assets: readAssets(parseIslandJson(manifestRaw, \"manifest\")),\n externals: readExternals(extRaw === null ? null : parseIslandJson(extRaw, \"ext_resources\")),\n pageOrder: readPageOrder(pageRaw === null ? null : parseIslandJson(pageRaw, \"page_order\")),\n ...(thumbnailSvg ? { thumbnailSvg } : {}),\n };\n}\n","// A small, linear CSS scanner — enough to read custom-property declarations\n// out of a design's stylesheets, and nothing more.\n//\n// This is NOT a CSS parser and does not try to be one. It answers one\n// question: which `--name: value` declarations does this document make, on\n// document-level selectors, in cascade order. That is all the token\n// extractor needs, and a real parser would be a dependency this\n// zero-dependency package does not take.\n//\n// Known limits (documented rather than papered over): specificity is not\n// modelled — declarations are applied in document order, last one wins,\n// which matches how token sheets are actually authored (a base tier, then\n// theme overrides). Comment stripping is textual, so a `/*` inside a string\n// literal would confuse it; token sheets do not contain those.\n\n/** One declaration the scanner found, with the selectors it was nested in. */\nexport interface ScannedDeclaration {\n /** Outermost → innermost selector/at-rule preludes. */\n selectors: string[];\n /** Property name, including the leading `--`. */\n name: string;\n /** Declaration value, trimmed, with comments already removed. */\n value: string;\n}\n\n/** Remove `/* … *​/` comments so they cannot break declaration splitting. */\nexport function stripCssComments(css: string): string {\n let out = \"\";\n let i = 0;\n for (;;) {\n const start = css.indexOf(\"/*\", i);\n if (start < 0) return out + css.slice(i);\n out += css.slice(i, start);\n const end = css.indexOf(\"*/\", start + 2);\n if (end < 0) return out;\n i = end + 2;\n }\n}\n\n/**\n * Concatenate every `<style>` element's text in document order. Designs ship\n * their theme as a sequence of style blocks (a vendored base tier, then\n * overrides), and the cascade between them is exactly this order.\n */\nexport function styleSheetText(html: string): string {\n const parts: string[] = [];\n let i = 0;\n for (;;) {\n const open = html.indexOf(\"<style\", i);\n if (open < 0) break;\n const gt = html.indexOf(\">\", open);\n if (gt < 0) break;\n const close = html.indexOf(\"</style>\", gt);\n if (close < 0) break;\n parts.push(html.slice(gt + 1, close));\n i = close + \"</style>\".length;\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * Walk `css` and yield every custom-property declaration with its enclosing\n * selector stack, in document order. Brace and paren depth are tracked so\n * nested at-rules (`@media { :root { … } }`) and parenthesised values\n * (`color-mix(in srgb, …)`) are handled correctly.\n *\n * Only `--*` declarations are reported; ordinary properties are skipped.\n */\nexport function scanCustomProperties(css: string): ScannedDeclaration[] {\n const text = stripCssComments(css);\n const found: ScannedDeclaration[] = [];\n const stack: string[] = [];\n let paren = 0;\n let start = 0;\n\n const flush = (end: number): void => {\n if (stack.length === 0) return;\n const chunk = text.slice(start, end).trim();\n if (!chunk.startsWith(\"--\")) return;\n const colon = chunk.indexOf(\":\");\n if (colon < 0) return;\n const name = chunk.slice(0, colon).trim();\n if (name.length < 3) return;\n found.push({ selectors: [...stack], name, value: chunk.slice(colon + 1).trim() });\n };\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (ch === \"(\") paren++;\n else if (ch === \")\") paren = Math.max(0, paren - 1);\n if (paren !== 0) continue;\n if (ch === \"{\") {\n stack.push(text.slice(start, i).trim());\n start = i + 1;\n } else if (ch === \"}\") {\n flush(i);\n stack.pop();\n start = i + 1;\n } else if (ch === \";\") {\n flush(i);\n start = i + 1;\n }\n }\n return found;\n}\n","// Hex color parsing and formatting.\n//\n// Accepts the CSS `#rgb` and `#rrggbb` forms (case-insensitive, surrounding\n// whitespace tolerated) and normalizes to lowercase `#rrggbb`. Alpha forms\n// (`#rgba` / `#rrggbbaa`) are rejected on purpose: the brand color engine\n// works in opaque colors only — translucency is expressed downstream by the\n// token compiler via `color-mix()` strings, never baked into swatches.\n//\n// Errors are plain RangeError so the color engine stays dependency-free;\n// the package's validate layer wraps them in BrandInputError where a typed\n// HTTP-facing error is needed.\n\n/** An sRGB color with channels as fractions in [0, 1]. */\nexport interface Rgb {\n /** Red channel, 0..1. */\n r: number;\n /** Green channel, 0..1. */\n g: number;\n /** Blue channel, 0..1. */\n b: number;\n}\n\n/** Clamps a number into [0, 1]; NaN clamps to 0. */\nexport function clamp01(x: number): number {\n return Number.isNaN(x) ? 0 : x < 0 ? 0 : x > 1 ? 1 : x;\n}\n\nconst HEX3 = /^#[0-9a-f]{3}$/;\nconst HEX6 = /^#[0-9a-f]{6}$/;\nconst HEX_ALPHA = /^#([0-9a-f]{4}|[0-9a-f]{8})$/;\n\n/**\n * Parses `#rgb` or `#rrggbb` (case-insensitive) into channel fractions.\n *\n * @throws RangeError for anything else — named colors, missing `#`, wrong\n * digit counts; alpha forms (`#rgba`/`#rrggbbaa`) get a dedicated message.\n */\nexport function parseHex(hex: string): Rgb {\n const s = hex.trim().toLowerCase();\n if (HEX_ALPHA.test(s)) {\n throw new RangeError(\n `parseHex: alpha hex \"${hex}\" is not supported — use an opaque \"#rrggbb\" value`,\n );\n }\n if (HEX3.test(s)) {\n return {\n r: parseInt(s[1]! + s[1]!, 16) / 255,\n g: parseInt(s[2]! + s[2]!, 16) / 255,\n b: parseInt(s[3]! + s[3]!, 16) / 255,\n };\n }\n if (HEX6.test(s)) {\n return {\n r: parseInt(s.slice(1, 3), 16) / 255,\n g: parseInt(s.slice(3, 5), 16) / 255,\n b: parseInt(s.slice(5, 7), 16) / 255,\n };\n }\n throw new RangeError(`parseHex: expected \"#rgb\" or \"#rrggbb\", got \"${hex}\"`);\n}\n\n/** Formats channel fractions as lowercase `#rrggbb`, clamping each into [0, 1]. */\nexport function toHex(rgb: Rgb): string {\n const ch = (c: number): string =>\n Math.round(clamp01(c) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${ch(rgb.r)}${ch(rgb.g)}${ch(rgb.b)}`;\n}\n\n/** Normalizes any accepted hex form to lowercase `#rrggbb` (throws like parseHex). */\nexport function normalizeHex(hex: string): string {\n return toHex(parseHex(hex));\n}\n","// Color space conversions: sRGB ↔ HSL, sRGB ↔ linear-light, sRGB ↔ OKLab,\n// OKLab ↔ OKLCH — plus an sRGB gamut clamp that reduces OKLCH chroma while\n// preserving lightness and hue.\n//\n// Algorithm sources:\n// - sRGB transfer function: IEC 61966-2-1 (electro-optical form: c ≤ 0.04045\n// → c/12.92, else ((c+0.055)/1.055)^2.4), as restated in CSS Color 4.\n// - HSL: CSS Color 4 § 7 (the hue-sextant algorithm inherited from CSS3\n// Color § 4.2.4).\n// - OKLab: Björn Ottosson, \"A perceptual color space for image processing\"\n// (bottosson.github.io/posts/oklab, 2020; sRGB matrices as updated\n// 2021-01-25): linear sRGB → LMS via M1, per-component cube root, → OKLab\n// via M2, and his published inverse matrices for the way back.\n// - OKLCH: CSS Color 4 § 9.2 — the polar form of OKLab (C = chroma radius,\n// h = hue angle in degrees).\n\nimport { clamp01, parseHex, toHex, type Rgb } from \"./hex\";\n\n/** A color in HSL: hue in degrees [0, 360), saturation and lightness 0..1. */\nexport interface Hsl {\n /** Hue angle in degrees, [0, 360); 0 when achromatic. */\n h: number;\n /** Saturation, 0..1. */\n s: number;\n /** Lightness, 0..1. */\n l: number;\n}\n\n/** A color in OKLab: L 0..1, a/b roughly within ±0.4 for sRGB colors. */\nexport interface Oklab {\n /** Perceived lightness, 0..1. */\n L: number;\n /** Green–red axis. */\n a: number;\n /** Blue–yellow axis. */\n b: number;\n}\n\n/** A color in OKLCH — OKLab in polar form. */\nexport interface Oklch {\n /** Perceived lightness, 0..1. */\n L: number;\n /** Chroma (radius in the a/b plane), ≥ 0. */\n C: number;\n /** Hue angle in degrees, [0, 360); 0 when achromatic. */\n h: number;\n}\n\n/** IEC 61966-2-1 sRGB decoding: gamma-encoded channel → linear-light, both 0..1. */\nexport function srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\n/** IEC 61966-2-1 sRGB encoding: linear-light channel → gamma-encoded, both 0..1. */\nexport function linearToSrgb(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;\n}\n\n/** Converts sRGB channel fractions to HSL (CSS Color 4 § 7). */\nexport function rgbToHsl({ r, g, b }: Rgb): Hsl {\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d === 0) return { h: 0, s: 0, l };\n const s = d / (1 - Math.abs(2 * l - 1));\n let h: number;\n if (max === r) h = 60 * (((g - b) / d) % 6);\n else if (max === g) h = 60 * ((b - r) / d + 2);\n else h = 60 * ((r - g) / d + 4);\n return { h: (h + 360) % 360, s, l };\n}\n\n/** Converts HSL to sRGB channel fractions (CSS Color 4 § 7; any hue angle accepted). */\nexport function hslToRgb({ h, s, l }: Hsl): Rgb {\n const hue = ((h % 360) + 360) % 360;\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = l - c / 2;\n const sextants: ReadonlyArray<readonly [number, number, number]> = [\n [c, x, 0],\n [x, c, 0],\n [0, c, x],\n [0, x, c],\n [x, 0, c],\n [c, 0, x],\n ];\n const [r, g, b] = sextants[Math.floor(hue / 60) % 6]!;\n return { r: r + m, g: g + m, b: b + m };\n}\n\n/** Converts gamma-encoded sRGB to OKLab (Ottosson M1 → cbrt → M2). */\nexport function rgbToOklab({ r, g, b }: Rgb): Oklab {\n const R = srgbToLinear(r);\n const G = srgbToLinear(g);\n const B = srgbToLinear(b);\n const l = Math.cbrt(0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B);\n const m = Math.cbrt(0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B);\n const s = Math.cbrt(0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B);\n return {\n L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\n/**\n * Converts OKLab to gamma-encoded sRGB (Ottosson's inverse matrices).\n * Out-of-gamut inputs yield channels outside [0, 1] — feed the OKLCH form\n * through {@link clampToGamut} first when hue fidelity matters (toHex would\n * clip per channel, which distorts hue).\n */\nexport function oklabToRgb({ L, a, b }: Oklab): Rgb {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return {\n r: linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),\n g: linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),\n b: linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),\n };\n}\n\n/** OKLab → OKLCH (polar form). Hue is 0 for achromatic colors (C ≈ 0). */\nexport function oklabToOklch({ L, a, b }: Oklab): Oklch {\n const C = Math.hypot(a, b);\n const h = C < 1e-9 ? 0 : ((Math.atan2(b, a) * 180) / Math.PI + 360) % 360;\n return { L, C, h };\n}\n\n/** OKLCH → OKLab (rectangular form). */\nexport function oklchToOklab({ L, C, h }: Oklch): Oklab {\n const rad = (h * Math.PI) / 180;\n return { L, a: C * Math.cos(rad), b: C * Math.sin(rad) };\n}\n\n/** Convenience: hex → OKLCH (throws like parseHex on bad input). */\nexport function hexToOklch(hex: string): Oklch {\n return oklabToOklch(rgbToOklab(parseHex(hex)));\n}\n\n/**\n * Convenience: OKLCH → lowercase `#rrggbb`. Out-of-gamut input is clipped\n * per channel by toHex; call {@link clampToGamut} first to reduce chroma\n * instead (preserving hue) when the input may be out of gamut.\n */\nexport function oklchToHex(lch: Oklch): string {\n return toHex(oklabToRgb(oklchToOklab(lch)));\n}\n\nconst GAMUT_EPS = 1e-6;\n\n/** True when every sRGB channel is within [0, 1] (tiny epsilon for float noise). */\nexport function inSrgbGamut({ r, g, b }: Rgb): boolean {\n const ok = (c: number): boolean => c >= -GAMUT_EPS && c <= 1 + GAMUT_EPS;\n return ok(r) && ok(g) && ok(b);\n}\n\n/**\n * Brings an OKLCH color into the sRGB gamut by reducing chroma only —\n * lightness and hue are preserved exactly (binary search, 24 iterations,\n * chroma precision well under one 8-bit quantum). L is clamped into [0, 1]\n * first; C = 0 (a pure gray) is always representable, so the search always\n * lands in gamut.\n */\nexport function clampToGamut(lch: Oklch): Oklch {\n const L = clamp01(lch.L);\n const h = lch.h;\n if (inSrgbGamut(oklabToRgb(oklchToOklab({ L, C: lch.C, h })))) return { L, C: lch.C, h };\n let lo = 0;\n let hi = lch.C;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (inSrgbGamut(oklabToRgb(oklchToOklab({ L, C: mid, h })))) lo = mid;\n else hi = mid;\n }\n return { L, C: lo, h };\n}\n","// WCAG 2.1 contrast — relative luminance, contrast ratio, and AA/AAA checks\n// per technique G18 and success criteria 1.4.3 / 1.4.6 / 1.4.11.\n//\n// relativeLuminance: Y = 0.2126·R + 0.7152·G + 0.0722·B over linear-light\n// sRGB channels. Channels are linearized with the IEC 61966-2-1 constant\n// (0.04045) rather than WCAG's 0.03928; the two never disagree for 8-bit\n// channel values (no n/255 falls between them) and CSS Color 4 standardizes\n// on 0.04045.\n// contrastRatio: (L1 + 0.05) / (L2 + 0.05) with the lighter luminance on\n// top — white on black is exactly 21:1, a color against itself 1:1.\n\nimport { parseHex } from \"./hex\";\nimport { srgbToLinear } from \"./convert\";\n\n/** Contrast contexts with distinct WCAG thresholds. */\nexport type ContrastKind = \"text\" | \"large-text\" | \"ui\";\n\n/** WCAG 2.1 relative luminance of a hex color: 0 = black, 1 = white. */\nexport function relativeLuminance(hex: string): number {\n const { r, g, b } = parseHex(hex);\n return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);\n}\n\n/** WCAG 2.1 contrast ratio between two hex colors, in [1, 21]; order-independent. */\nexport function contrastRatio(hexA: string, hexB: string): number {\n const la = relativeLuminance(hexA);\n const lb = relativeLuminance(hexB);\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\nconst AA: Record<ContrastKind, number> = { text: 4.5, \"large-text\": 3, ui: 3 };\nconst AAA: Record<Exclude<ContrastKind, \"ui\">, number> = { text: 7, \"large-text\": 4.5 };\n\n/**\n * WCAG 2.1 level-AA check for a contrast ratio: 4.5:1 for body text\n * (SC 1.4.3), 3:1 for large text, 3:1 for UI components and graphical\n * objects (SC 1.4.11).\n */\nexport function meetsAA(ratio: number, kind: ContrastKind = \"text\"): boolean {\n return ratio >= AA[kind];\n}\n\n/**\n * WCAG 2.1 level-AAA check for a contrast ratio (SC 1.4.6): 7:1 for body\n * text, 4.5:1 for large text. WCAG defines no AAA bar for non-text UI, so\n * \"ui\" is not an accepted kind here.\n */\nexport function meetsAAA(ratio: number, kind: Exclude<ContrastKind, \"ui\"> = \"text\"): boolean {\n return ratio >= AAA[kind];\n}\n\n/**\n * Default {@link pickTextOn} candidates: white and a near-black chosen so\n * that the better of the two clears 4.5:1 against ANY background. The worst\n * case is a mid-gray backdrop (luminance ≈ 0.18), where this pair still\n * yields ≈ 4.51:1; a softer near-black (e.g. #111111) would drop that floor\n * below 4.5.\n */\nexport const PICK_TEXT_DEFAULT_CANDIDATES: readonly string[] = [\"#ffffff\", \"#050505\"];\n\n/**\n * Picks the candidate with the highest contrast ratio against `bgHex`\n * (earliest candidate wins ties). With the default candidates the winner is\n * always ≥ 4.5:1 — see {@link PICK_TEXT_DEFAULT_CANDIDATES}.\n *\n * @throws RangeError when `candidates` is empty.\n */\nexport function pickTextOn(\n bgHex: string,\n candidates: readonly string[] = PICK_TEXT_DEFAULT_CANDIDATES,\n): string {\n if (candidates.length === 0) throw new RangeError(\"pickTextOn: candidates must be non-empty\");\n let best = candidates[0]!;\n let bestRatio = -1;\n for (const candidate of candidates) {\n const ratio = contrastRatio(bgHex, candidate);\n if (ratio > bestRatio) {\n best = candidate;\n bestRatio = ratio;\n }\n }\n return best;\n}\n","// Classic color-harmony companions, computed as OKLCH hue rotations at\n// constant lightness and chroma so companions keep the seed's perceived\n// lightness and vividness (the same rotations in HSL shift both wildly —\n// compare HSL yellow vs blue at \"50%\"). Results are chroma-clamped into the\n// sRGB gamut, which preserves hue and lightness exactly.\n//\n// Angles follow the traditional color-wheel definitions: complementary 180°,\n// analogous ±30°, triadic ±120°, split-complementary ±150°, tetradic\n// (square) +90°/180°/270°. Hue math per CSS Color 4 § 9.2 OKLCH.\n\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\n\n/**\n * Rotates a color's OKLCH hue by `degrees` (any sign/magnitude), keeping\n * lightness and chroma constant, then chroma-clamps into sRGB. Rotating an\n * achromatic color is a no-op up to 8-bit rounding (its chroma is ~0).\n */\nexport function rotateHue(hex: string, degrees: number): string {\n const { L, C, h } = hexToOklch(hex);\n return oklchToHex(clampToGamut({ L, C, h: (((h + degrees) % 360) + 360) % 360 }));\n}\n\n/** The 180° opposite on the OKLCH hue wheel. */\nexport function complementary(hex: string): string {\n return rotateHue(hex, 180);\n}\n\n/** The two neighbors at ±`angle` (default 30°), as [minus, plus]. */\nexport function analogous(hex: string, angle = 30): [string, string] {\n return [rotateHue(hex, -angle), rotateHue(hex, angle)];\n}\n\n/** The two colors completing an equilateral triad (±120°), as [minus, plus]. */\nexport function triadic(hex: string): [string, string] {\n return [rotateHue(hex, -120), rotateHue(hex, 120)];\n}\n\n/** The two colors flanking the complement (±150°), as [minus, plus]. */\nexport function splitComplementary(hex: string): [string, string] {\n return [rotateHue(hex, -150), rotateHue(hex, 150)];\n}\n\n/** The three colors completing a square (+90°, +180°, +270°). */\nexport function tetradic(hex: string): [string, string, string] {\n return [rotateHue(hex, 90), rotateHue(hex, 180), rotateHue(hex, 270)];\n}\n\n/**\n * A monochrome chroma scale: `steps` colors at the seed's lightness and hue,\n * fading chroma linearly from the seed's own chroma down to 0 (a pure gray).\n * The first entry is the seed itself (normalized).\n *\n * @throws RangeError when `steps` is not an integer ≥ 2.\n */\nexport function monochrome(hex: string, steps = 5): string[] {\n if (!Number.isInteger(steps) || steps < 2) {\n throw new RangeError(`monochrome: steps must be an integer >= 2, got ${steps}`);\n }\n const { L, C, h } = hexToOklch(hex);\n const out: string[] = [];\n for (let i = 0; i < steps; i++) {\n out.push(oklchToHex(clampToGamut({ L, C: C * (1 - i / (steps - 1)), h })));\n }\n return out;\n}\n","// Tint/shade ramps and predicate-driven lightness adjustment, both in OKLCH\n// so steps are perceptually even (equal OKLab ΔL per step; OKLab per Björn\n// Ottosson — see convert.ts for the matrices and citations).\n//\n// tintShadeRamp walks lightness from RAMP_L_MAX down to RAMP_L_MIN with a\n// chroma taper: full chroma mid-ramp, fading toward both ends. Very light\n// tints and very dark shades can't hold much chroma in sRGB anyway, and a\n// deliberate taper reads better than the hard cut the gamut clamp would\n// otherwise apply.\n//\n// adjustLightnessUntil binary-searches lightness (constant chroma and hue,\n// gamut-clamped) for the value nearest the input that satisfies a caller\n// predicate — the workhorse behind \"darken this accent until it clears\n// 4.5:1 on the page background\".\n\nimport { normalizeHex } from \"./hex\";\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\n\n/** Lightest OKLab L emitted by {@link tintShadeRamp} (first step). */\nexport const RAMP_L_MAX = 0.96;\n\n/** Darkest OKLab L emitted by {@link tintShadeRamp} (last step). */\nexport const RAMP_L_MIN = 0.27;\n\n/** Fraction of the seed's chroma kept at the ramp's endpoints. */\nconst CHROMA_FLOOR = 0.25;\n\n/**\n * A light-to-dark ramp of `steps` colors (default 9) built from the seed's\n * hue and chroma: OKLab lightness runs linearly from {@link RAMP_L_MAX} down\n * to {@link RAMP_L_MIN}, and chroma tapers from 100% of the seed's chroma at\n * mid-ramp to 25% at both ends (then gamut-clamps, preserving hue).\n *\n * @throws RangeError when `steps` is not an integer ≥ 2.\n */\nexport function tintShadeRamp(hex: string, steps = 9): string[] {\n if (!Number.isInteger(steps) || steps < 2) {\n throw new RangeError(`tintShadeRamp: steps must be an integer >= 2, got ${steps}`);\n }\n const { C, h } = hexToOklch(hex);\n const out: string[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = RAMP_L_MAX + (RAMP_L_MIN - RAMP_L_MAX) * t;\n const taper = CHROMA_FLOOR + (1 - CHROMA_FLOOR) * (1 - Math.abs(2 * t - 1));\n out.push(oklchToHex(clampToGamut({ L, C: C * taper, h })));\n }\n return out;\n}\n\n/** Direction {@link adjustLightnessUntil} may move lightness. */\nexport type LightnessDirection = \"lighten\" | \"darken\";\n\nconst SCAN_STEPS = 16;\nconst BISECT_STEPS = 22;\n\n/**\n * Moves a color's OKLCH lightness toward white (\"lighten\") or black\n * (\"darken\") until `predicate(hex)` holds, returning the passing color\n * nearest the input (chroma and hue constant, gamut-clamped per step).\n *\n * Returns the input itself (normalized) when it already passes, and null\n * when no lightness in that direction satisfies the predicate. Work is\n * bounded: a 16-step coarse scan plus 22 bisection rounds. The predicate is\n * always evaluated on exact 8-bit hex strings, including the returned one.\n */\nexport function adjustLightnessUntil(\n hex: string,\n predicate: (hex: string) => boolean,\n direction: LightnessDirection,\n): string | null {\n const start = normalizeHex(hex);\n if (predicate(start)) return start;\n const { L, C, h } = hexToOklch(start);\n const bound = direction === \"lighten\" ? 1 : 0;\n const at = (l: number): string => oklchToHex(clampToGamut({ L: l, C, h }));\n let lastFail = L;\n let firstPass = Number.NaN;\n for (let i = 1; i <= SCAN_STEPS; i++) {\n const l = L + ((bound - L) * i) / SCAN_STEPS;\n if (predicate(at(l))) {\n firstPass = l;\n break;\n }\n lastFail = l;\n }\n if (Number.isNaN(firstPass)) return null;\n for (let i = 0; i < BISECT_STEPS; i++) {\n const mid = (lastFail + firstPass) / 2;\n if (predicate(at(mid))) firstPass = mid;\n else lastFail = mid;\n }\n return at(firstPass);\n}\n","// ΔEOK — the OKLab color-difference metric adopted by CSS Color 4 (§ \"the\n// deltaEOK function\"): plain Euclidean distance in OKLab coordinates.\n// Scale intuition: ~0.02 is roughly one just-noticeable difference, and\n// white ↔ black is exactly 1.\n\nimport { parseHex } from \"./hex\";\nimport { rgbToOklab, type Oklab } from \"./convert\";\n\n/** Euclidean distance between two OKLab coordinates (CSS Color 4 ΔEOK). */\nexport function deltaEOKLab(x: Oklab, y: Oklab): number {\n return Math.hypot(x.L - y.L, x.a - y.a, x.b - y.b);\n}\n\n/**\n * ΔEOK between two hex colors. 0 = identical; ~0.02 ≈ one just-noticeable\n * difference; white ↔ black = 1. Symmetric in its arguments.\n *\n * @throws RangeError on malformed hex (see parseHex).\n */\nexport function deltaEOK(hexA: string, hexB: string): number {\n return deltaEOKLab(rgbToOklab(parseHex(hexA)), rgbToOklab(parseHex(hexB)));\n}\n","// The 148 CSS named colors — CSS Color 4 § 6.1 \"Named colors\" (the CSS3\n// keyword list plus rebeccapurple), with the spec's exact hex values —\n// and nearest-name lookup by ΔEOK (CSS Color 4's OKLab distance metric,\n// see delta.ts). Alphabetical order; gray/grey-style aliases are separate\n// entries sharing one hex.\n\nimport { parseHex } from \"./hex\";\nimport { rgbToOklab, type Oklab } from \"./convert\";\nimport { deltaEOKLab } from \"./delta\";\n\n/** One CSS named color: the keyword and its spec hex value. */\nexport interface NamedColor {\n /** The CSS keyword, e.g. \"rebeccapurple\". */\n name: string;\n /** The spec's `#rrggbb` value, lowercase. */\n hex: string;\n}\n\nconst TABLE: ReadonlyArray<readonly [string, string]> = [\n [\"aliceblue\", \"#f0f8ff\"],\n [\"antiquewhite\", \"#faebd7\"],\n [\"aqua\", \"#00ffff\"],\n [\"aquamarine\", \"#7fffd4\"],\n [\"azure\", \"#f0ffff\"],\n [\"beige\", \"#f5f5dc\"],\n [\"bisque\", \"#ffe4c4\"],\n [\"black\", \"#000000\"],\n [\"blanchedalmond\", \"#ffebcd\"],\n [\"blue\", \"#0000ff\"],\n [\"blueviolet\", \"#8a2be2\"],\n [\"brown\", \"#a52a2a\"],\n [\"burlywood\", \"#deb887\"],\n [\"cadetblue\", \"#5f9ea0\"],\n [\"chartreuse\", \"#7fff00\"],\n [\"chocolate\", \"#d2691e\"],\n [\"coral\", \"#ff7f50\"],\n [\"cornflowerblue\", \"#6495ed\"],\n [\"cornsilk\", \"#fff8dc\"],\n [\"crimson\", \"#dc143c\"],\n [\"cyan\", \"#00ffff\"],\n [\"darkblue\", \"#00008b\"],\n [\"darkcyan\", \"#008b8b\"],\n [\"darkgoldenrod\", \"#b8860b\"],\n [\"darkgray\", \"#a9a9a9\"],\n [\"darkgreen\", \"#006400\"],\n [\"darkgrey\", \"#a9a9a9\"],\n [\"darkkhaki\", \"#bdb76b\"],\n [\"darkmagenta\", \"#8b008b\"],\n [\"darkolivegreen\", \"#556b2f\"],\n [\"darkorange\", \"#ff8c00\"],\n [\"darkorchid\", \"#9932cc\"],\n [\"darkred\", \"#8b0000\"],\n [\"darksalmon\", \"#e9967a\"],\n [\"darkseagreen\", \"#8fbc8f\"],\n [\"darkslateblue\", \"#483d8b\"],\n [\"darkslategray\", \"#2f4f4f\"],\n [\"darkslategrey\", \"#2f4f4f\"],\n [\"darkturquoise\", \"#00ced1\"],\n [\"darkviolet\", \"#9400d3\"],\n [\"deeppink\", \"#ff1493\"],\n [\"deepskyblue\", \"#00bfff\"],\n [\"dimgray\", \"#696969\"],\n [\"dimgrey\", \"#696969\"],\n [\"dodgerblue\", \"#1e90ff\"],\n [\"firebrick\", \"#b22222\"],\n [\"floralwhite\", \"#fffaf0\"],\n [\"forestgreen\", \"#228b22\"],\n [\"fuchsia\", \"#ff00ff\"],\n [\"gainsboro\", \"#dcdcdc\"],\n [\"ghostwhite\", \"#f8f8ff\"],\n [\"gold\", \"#ffd700\"],\n [\"goldenrod\", \"#daa520\"],\n [\"gray\", \"#808080\"],\n [\"green\", \"#008000\"],\n [\"greenyellow\", \"#adff2f\"],\n [\"grey\", \"#808080\"],\n [\"honeydew\", \"#f0fff0\"],\n [\"hotpink\", \"#ff69b4\"],\n [\"indianred\", \"#cd5c5c\"],\n [\"indigo\", \"#4b0082\"],\n [\"ivory\", \"#fffff0\"],\n [\"khaki\", \"#f0e68c\"],\n [\"lavender\", \"#e6e6fa\"],\n [\"lavenderblush\", \"#fff0f5\"],\n [\"lawngreen\", \"#7cfc00\"],\n [\"lemonchiffon\", \"#fffacd\"],\n [\"lightblue\", \"#add8e6\"],\n [\"lightcoral\", \"#f08080\"],\n [\"lightcyan\", \"#e0ffff\"],\n [\"lightgoldenrodyellow\", \"#fafad2\"],\n [\"lightgray\", \"#d3d3d3\"],\n [\"lightgreen\", \"#90ee90\"],\n [\"lightgrey\", \"#d3d3d3\"],\n [\"lightpink\", \"#ffb6c1\"],\n [\"lightsalmon\", \"#ffa07a\"],\n [\"lightseagreen\", \"#20b2aa\"],\n [\"lightskyblue\", \"#87cefa\"],\n [\"lightslategray\", \"#778899\"],\n [\"lightslategrey\", \"#778899\"],\n [\"lightsteelblue\", \"#b0c4de\"],\n [\"lightyellow\", \"#ffffe0\"],\n [\"lime\", \"#00ff00\"],\n [\"limegreen\", \"#32cd32\"],\n [\"linen\", \"#faf0e6\"],\n [\"magenta\", \"#ff00ff\"],\n [\"maroon\", \"#800000\"],\n [\"mediumaquamarine\", \"#66cdaa\"],\n [\"mediumblue\", \"#0000cd\"],\n [\"mediumorchid\", \"#ba55d3\"],\n [\"mediumpurple\", \"#9370db\"],\n [\"mediumseagreen\", \"#3cb371\"],\n [\"mediumslateblue\", \"#7b68ee\"],\n [\"mediumspringgreen\", \"#00fa9a\"],\n [\"mediumturquoise\", \"#48d1cc\"],\n [\"mediumvioletred\", \"#c71585\"],\n [\"midnightblue\", \"#191970\"],\n [\"mintcream\", \"#f5fffa\"],\n [\"mistyrose\", \"#ffe4e1\"],\n [\"moccasin\", \"#ffe4b5\"],\n [\"navajowhite\", \"#ffdead\"],\n [\"navy\", \"#000080\"],\n [\"oldlace\", \"#fdf5e6\"],\n [\"olive\", \"#808000\"],\n [\"olivedrab\", \"#6b8e23\"],\n [\"orange\", \"#ffa500\"],\n [\"orangered\", \"#ff4500\"],\n [\"orchid\", \"#da70d6\"],\n [\"palegoldenrod\", \"#eee8aa\"],\n [\"palegreen\", \"#98fb98\"],\n [\"paleturquoise\", \"#afeeee\"],\n [\"palevioletred\", \"#db7093\"],\n [\"papayawhip\", \"#ffefd5\"],\n [\"peachpuff\", \"#ffdab9\"],\n [\"peru\", \"#cd853f\"],\n [\"pink\", \"#ffc0cb\"],\n [\"plum\", \"#dda0dd\"],\n [\"powderblue\", \"#b0e0e6\"],\n [\"purple\", \"#800080\"],\n [\"rebeccapurple\", \"#663399\"],\n [\"red\", \"#ff0000\"],\n [\"rosybrown\", \"#bc8f8f\"],\n [\"royalblue\", \"#4169e1\"],\n [\"saddlebrown\", \"#8b4513\"],\n [\"salmon\", \"#fa8072\"],\n [\"sandybrown\", \"#f4a460\"],\n [\"seagreen\", \"#2e8b57\"],\n [\"seashell\", \"#fff5ee\"],\n [\"sienna\", \"#a0522d\"],\n [\"silver\", \"#c0c0c0\"],\n [\"skyblue\", \"#87ceeb\"],\n [\"slateblue\", \"#6a5acd\"],\n [\"slategray\", \"#708090\"],\n [\"slategrey\", \"#708090\"],\n [\"snow\", \"#fffafa\"],\n [\"springgreen\", \"#00ff7f\"],\n [\"steelblue\", \"#4682b4\"],\n [\"tan\", \"#d2b48c\"],\n [\"teal\", \"#008080\"],\n [\"thistle\", \"#d8bfd8\"],\n [\"tomato\", \"#ff6347\"],\n [\"turquoise\", \"#40e0d0\"],\n [\"violet\", \"#ee82ee\"],\n [\"wheat\", \"#f5deb3\"],\n [\"white\", \"#ffffff\"],\n [\"whitesmoke\", \"#f5f5f5\"],\n [\"yellow\", \"#ffff00\"],\n [\"yellowgreen\", \"#9acd32\"],\n];\n\n/**\n * All 148 CSS named colors in alphabetical order. Aliases (aqua/cyan,\n * fuchsia/magenta, the gray/grey pairs) are separate entries sharing a hex.\n */\nexport const CSS_NAMED_COLORS: readonly NamedColor[] = TABLE.map(([name, hex]) => ({\n name,\n hex,\n}));\n\n/** A nearest-name match: the keyword, its spec hex, and the ΔEOK distance. */\nexport interface NearestNamedColor extends NamedColor {\n /** ΔEOK from the query color to this named color (0 = exact hit). */\n deltaEOK: number;\n}\n\nlet labCache: Oklab[] | null = null;\n\n/**\n * The CSS named color perceptually closest to `hex`, by ΔEOK in OKLab.\n * Exact hits return distance 0. Ties — including shared-hex aliases like\n * aqua/cyan — go to the alphabetically first keyword. As a rough guide,\n * distances ≲ 0.02 are visually indistinguishable and ≳ 0.1 is only a loose\n * \"same family\" match.\n *\n * @throws RangeError on malformed hex (see parseHex).\n */\nexport function nearestNamedColor(hex: string): NearestNamedColor {\n const target = rgbToOklab(parseHex(hex));\n labCache ??= TABLE.map(([, value]) => rgbToOklab(parseHex(value)));\n let bestIdx = 0;\n let bestD = Infinity;\n for (let i = 0; i < labCache.length; i++) {\n const d = deltaEOKLab(target, labCache[i]!);\n if (d < bestD) {\n bestD = d;\n bestIdx = i;\n }\n }\n const [name, value] = TABLE[bestIdx]!;\n return { name, hex: value, deltaEOK: bestD };\n}\n","// Full-palette derivation from a single seed color. All deterministic —\n// no randomness, no clock — so the same seed always yields the same\n// palette (proposals are reviewable and reproducible).\n//\n// Strategy:\n// - primary: the seed itself (normalized).\n// - secondary / highlight: classic harmony rotations of the seed in OKLCH\n// (complementary 180°, triadic ±120°, split-complementary ±150°).\n// secondary maximizes ΔEOK from the primary; highlight maximizes the\n// minimum ΔEOK to both, so the three accents spread apart. Near-achromatic\n// seeds (C < 0.02) have no usable hue, so rotations run from a synthetic\n// chromatic anchor at ANCHOR_HUE instead (a gray seed still deserves\n// real accents).\n// - good / warn / danger: hue-anchored at 145° / 85° / 25° OKLCH (green /\n// amber / red), darkened via adjustLightnessUntil until they clear WCAG's\n// 3:1 non-text bar (SC 1.4.11) against the derived background.\n// - chart set: hue rotations at a constant, gamut-safe (CHART_L, CHART_C)\n// chosen so every hue fits sRGB without chroma clamping. Adjacent 60°\n// hues then sit 2·C·sin(30°) = C apart in OKLab, so with C = 0.115 the\n// pairwise ΔEOK floor CHART_DELTA_MIN = 0.1 holds by construction.\n// - neutrals bg / surface / neutral / text: a near-achromatic ladder tinted\n// with the seed hue (C ≤ 0.012), L 0.985 → 0.24; text vs bg lands well\n// past 7:1 (AAA).\n\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { normalizeHex } from \"./hex\";\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\nimport { contrastRatio } from \"./contrast\";\nimport { rotateHue } from \"./harmony\";\nimport { adjustLightnessUntil } from \"./ramp\";\nimport { deltaEOK } from \"./delta\";\nimport { nearestNamedColor } from \"./names\";\n\n/**\n * Documented floor for pairwise ΔEOK between derived chart colors. The\n * default chart constants guarantee it by construction (see file header);\n * deriveChartColors also enforces it as a filter.\n */\nexport const CHART_DELTA_MIN = 0.1;\n\n/** Chart lightness: chosen with CHART_C so all hues are in-gamut (min max-chroma over hues ≈ 0.119 at L = 0.7). */\nconst CHART_L = 0.7;\n/** Chart chroma: gamut-safe at CHART_L for every hue, so no clamping ever shifts a chart color. */\nconst CHART_C = 0.115;\n/** Hue used when a seed is too gray to have one (a mid blue). */\nconst ANCHOR_HUE = 250;\n/** Below this OKLCH chroma a seed is treated as achromatic. */\nconst ACHROMATIC_C = 0.02;\n/** Status swatch anchors (OKLCH hue degrees): green / amber / red. */\nconst STATUS_HUES = { good: 145, warn: 85, danger: 25 } as const;\nconst STATUS_L = 0.7;\nconst STATUS_C = 0.14;\n/** Harmony rotations tried for secondary/highlight, in tie-break order. */\nconst ROTATIONS = [180, 120, -120, 150, -150] as const;\n\n/** Options for {@link deriveChartColors}. */\nexport interface DeriveChartOptions {\n /** How many colors to return, 1..12 (default 6). */\n count?: number;\n /** Pairwise ΔEOK floor (default {@link CHART_DELTA_MIN}). Best-effort above the default. */\n deltaMin?: number;\n}\n\n/**\n * Derives categorical chart colors from a seed: hue rotations (60° grid,\n * then 30° offsets) around the seed's hue at a constant, gamut-safe\n * lightness/chroma. Candidates are kept only if they stay at least\n * `deltaMin` ΔEOK from every accepted color; if the requested floor is\n * unattainable for `count` colors, remaining distinct candidates fill the\n * set in hue order so callers always get `count` colors back.\n *\n * @throws RangeError when `count` is not an integer in 1..12, or on\n * malformed hex.\n */\nexport function deriveChartColors(seedHex: string, opts: DeriveChartOptions = {}): string[] {\n const count = opts.count ?? 6;\n const deltaMin = opts.deltaMin ?? CHART_DELTA_MIN;\n if (!Number.isInteger(count) || count < 1 || count > 12) {\n throw new RangeError(`deriveChartColors: count must be an integer in 1..12, got ${count}`);\n }\n const lch = hexToOklch(normalizeHex(seedHex));\n const base = lch.C < ACHROMATIC_C ? ANCHOR_HUE : lch.h;\n const offsets = [0, 60, 120, 180, 240, 300, 30, 90, 150, 210, 270, 330];\n const candidates = offsets.map((deg) =>\n oklchToHex(clampToGamut({ L: CHART_L, C: CHART_C, h: (base + deg) % 360 })),\n );\n const picked: string[] = [];\n for (const hex of candidates) {\n if (picked.length >= count) break;\n if (picked.includes(hex)) continue;\n if (picked.every((p) => deltaEOK(p, hex) >= deltaMin)) picked.push(hex);\n }\n for (const hex of candidates) {\n if (picked.length >= count) break;\n if (!picked.includes(hex)) picked.push(hex);\n }\n return picked;\n}\n\n/** Options for {@link derivePalette}. */\nexport interface DerivePaletteOptions {\n /** Attach nearest-CSS-keyword `name`s to every swatch (default true). */\n names?: boolean;\n}\n\n/**\n * Derives a complete brand palette from one seed color: one swatch each for\n * primary, secondary, highlight, good, warn, danger, bg, surface, text and\n * neutral, plus six chart swatches (16 total) — see the file header for the\n * derivation strategy and its WCAG guarantees.\n *\n * @throws RangeError on malformed seed hex (see parseHex).\n */\nexport function derivePalette(seedHex: string, opts: DerivePaletteOptions = {}): Swatch[] {\n const withNames = opts.names !== false;\n const seed = normalizeHex(seedHex);\n const seedLch = hexToOklch(seed);\n const achromatic = seedLch.C < ACHROMATIC_C;\n const hue = achromatic ? ANCHOR_HUE : seedLch.h;\n\n const neutralAt = (L: number, C: number): string => oklchToHex(clampToGamut({ L, C, h: hue }));\n const bg = neutralAt(0.985, 0.005);\n const surface = neutralAt(0.955, 0.008);\n const text = neutralAt(0.24, 0.012);\n const neutral = neutralAt(0.62, 0.012);\n\n const accentBase = achromatic\n ? oklchToHex(\n clampToGamut({ L: Math.min(Math.max(seedLch.L, 0.45), 0.75), C: CHART_C, h: ANCHOR_HUE }),\n )\n : seed;\n const cands = ROTATIONS.map((deg) => {\n const hex = rotateHue(accentBase, deg);\n return { deg, hex, d: deltaEOK(seed, hex) };\n });\n let secondary = cands[0]!;\n for (const c of cands) if (c.d > secondary.d) secondary = c;\n let highlight = cands[0] === secondary ? cands[1]! : cands[0]!;\n let hiScore = Math.min(highlight.d, deltaEOK(highlight.hex, secondary.hex));\n for (const c of cands) {\n if (c === secondary || c === highlight) continue;\n const score = Math.min(c.d, deltaEOK(c.hex, secondary.hex));\n if (score > hiScore) {\n highlight = c;\n hiScore = score;\n }\n }\n\n const status = (anchor: number): string => {\n const start = oklchToHex(clampToGamut({ L: STATUS_L, C: STATUS_C, h: anchor }));\n return adjustLightnessUntil(start, (c) => contrastRatio(c, bg) >= 3, \"darken\") ?? text;\n };\n\n const sw = (role: SwatchRole, hex: string, rationale: string): Swatch => ({\n role,\n hex,\n rationale,\n });\n const swatches: Swatch[] = [\n sw(\"primary\", seed, \"seed color\"),\n sw(\"secondary\", secondary.hex, `harmony rotation ${secondary.deg}°, ΔEOK ${secondary.d.toFixed(3)} from primary`),\n sw(\"highlight\", highlight.hex, `harmony rotation ${highlight.deg}°, spread from primary and secondary`),\n sw(\"good\", status(STATUS_HUES.good), \"green anchor 145°, ≥3:1 on bg\"),\n sw(\"warn\", status(STATUS_HUES.warn), \"amber anchor 85°, ≥3:1 on bg\"),\n sw(\"danger\", status(STATUS_HUES.danger), \"red anchor 25°, ≥3:1 on bg\"),\n sw(\"bg\", bg, \"near-white tinted with the seed hue\"),\n sw(\"surface\", surface, \"raised surface, one step below bg\"),\n sw(\"text\", text, \"near-black tinted with the seed hue\"),\n sw(\"neutral\", neutral, \"mid neutral for borders and muted marks\"),\n ...deriveChartColors(seed).map((hex, i) => sw(\"chart\", hex, `chart series ${i + 1}`)),\n ];\n return withNames\n ? swatches.map((s) => ({ ...s, name: nearestNamedColor(s.hex).name }))\n : swatches;\n}\n","// Palette → light-mode @odla-ai/ui tokens.\n//\n// Every name in BRAND_EMITTED_TOKENS is always emitted. Real swatches map\n// directly; missing roles fall back to derivePalette() output seeded from\n// the accent (with a warning); derived/composed roles use the EXACT\n// var()/color-mix() composition strings @odla-ai/ui css/tokens.css uses as\n// defaults, so the object works as a scoped override-island payload (the\n// compositions recompute at the declaring element — see roles.ts).\n//\n// Contrast guarantees (WCAG 2.1, enforced with adjustLightnessUntil and\n// recorded as warnings with `adjustedFrom` whenever a color had to move):\n// --ui-text ≥ 4.5:1 and --ui-text-muted ≥ 4.5:1 on --ui-bg (SC 1.4.3),\n// --ui-accent-strong ≥ 4.5:1 on --ui-bg (darkened on a light bg),\n// --ui-good/warn/danger ≥ 3:1 on --ui-bg (SC 1.4.11), and --ui-on-accent\n// via pickTextOn (≥ 4.5:1 with the default white/near-black candidates).\n\nimport type { Swatch, SwatchRole } from \"../types\";\nimport {\n adjustLightnessUntil,\n clamp01,\n clampToGamut,\n contrastRatio,\n deriveChartColors,\n derivePalette,\n hexToOklch,\n normalizeHex,\n oklchToHex,\n parseHex,\n pickTextOn,\n relativeLuminance,\n type LightnessDirection,\n} from \"../color\";\nimport type { BrandTokens, CompileInput, TokenWarning } from \"./types\";\n\n/**\n * Seed used when the palette has no usable chromatic swatch at all — the\n * @odla-ai/ui neutral default accent (css/tokens.css restrained blue).\n */\nexport const DEFAULT_ACCENT_SEED = \"#3b5e8c\";\n\n/** Below this OKLCH chroma a swatch is too gray for accent/chart duty. */\nconst CHROMATIC_C = 0.02;\n\n// System font stacks, verbatim from @odla-ai/ui css/tokens.css.\nconst SANS_STACK = `ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif`;\nconst SERIF_STACK = `\"Iowan Old Style\", \"Palatino Linotype\", Palatino, Georgia, serif`;\nconst MONO_STACK = `ui-monospace, \"SF Mono\", Menlo, Consolas, monospace`;\nconst DISPLAY_STACK = `ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif`;\n\n// ui css/tokens.css chart defaults — emitted when the palette lacks ≥3\n// chromatic chart swatches, so an override island never keeps root values.\nconst UI_CHART_DEFAULTS = [\n \"var(--ui-accent)\",\n \"var(--ui-good)\",\n \"var(--ui-warn)\",\n \"var(--ui-danger)\",\n \"color-mix(in srgb, var(--ui-accent) 45%, var(--ui-text))\",\n \"var(--ui-text-faint)\",\n] as const;\n\n/**\n * The token a missing swatch role is reported against — and the canonical\n * role → `--ui-*` correspondence. Exported so the design decompiler can\n * invert exactly this map rather than restating it (see\n * `design/decompile.ts`); a round-trip test pins the two together.\n */\nexport const ROLE_TOKEN: Partial<Record<SwatchRole, string>> = {\n primary: \"--ui-accent\",\n secondary: \"--ui-accent-2\",\n highlight: \"--ui-highlight\",\n bg: \"--ui-bg\",\n surface: \"--ui-surface\",\n text: \"--ui-text\",\n neutral: \"--ui-border-strong\",\n good: \"--ui-good\",\n warn: \"--ui-warn\",\n danger: \"--ui-danger\",\n chart: \"--ui-chart-1\",\n};\n\nconst mixVar = (name: string, pct: number): string =>\n `color-mix(in srgb, var(${name}) ${pct}%, transparent)`;\n\n/** Shift OKLab lightness by dL, constant chroma/hue, gamut-clamped. */\nfunction shiftL(hex: string, dL: number): string {\n const { L, C, h } = hexToOklch(hex);\n return oklchToHex(clampToGamut({ L: clamp01(L + dL), C, h }));\n}\n\n/** Move `fromHex` a fraction `t` of the way to `toHex` in OKLab lightness only. */\nfunction lerpL(fromHex: string, toHex: string, t: number): string {\n const a = hexToOklch(fromHex);\n const b = hexToOklch(toHex);\n return oklchToHex(clampToGamut({ L: a.L + (b.L - a.L) * t, C: a.C, h: a.h }));\n}\n\n/**\n * Push `hex` away from `bg` in lightness until it clears `min`:1. Tries the\n * away-from-bg direction (darken on a light bg), then the other direction,\n * then falls back to pickTextOn(bg) — which always clears 4.5:1.\n */\nfunction ensureOnBg(hex: string, bg: string, min: number): string {\n const pred = (c: string): boolean => contrastRatio(c, bg) >= min;\n const away: LightnessDirection =\n relativeLuminance(bg) >= relativeLuminance(hex) ? \"darken\" : \"lighten\";\n return (\n adjustLightnessUntil(hex, pred, away) ??\n adjustLightnessUntil(hex, pred, away === \"darken\" ? \"lighten\" : \"darken\") ??\n pickTextOn(bg)\n );\n}\n\nconst rgbaOf = (hex: string, alpha: number): string => {\n const { r, g, b } = parseHex(hex);\n const c = (v: number): number => Math.round(v * 255);\n return `rgba(${c(r)}, ${c(g)}, ${c(b)}, ${alpha})`;\n};\n\n/** Brand family + system stack; quotes a single family name when needed. */\nfunction fontValue(family: string | undefined, stack: string): string {\n const f = family?.trim() ?? \"\";\n if (f === \"\") return stack;\n if (f.includes(\",\") || /^[\"']/.test(f) || /^[a-zA-Z][a-zA-Z0-9-]*$/.test(f))\n return `${f}, ${stack}`;\n return `\"${f.replaceAll('\"', \"\")}\", ${stack}`;\n}\n\ninterface Collected {\n byRole: Partial<Record<SwatchRole, string>>;\n charts: string[];\n}\n\n/** First-wins role → hex map + ordered chart swatches; bad hexes dropped. */\nfunction collect(swatches: unknown, warnings: TokenWarning[]): Collected {\n const byRole: Partial<Record<SwatchRole, string>> = {};\n const charts: string[] = [];\n if (!Array.isArray(swatches)) {\n warnings.push({ token: \"--ui-accent\", message: \"swatches is not an array; compiling from defaults\" });\n return { byRole, charts };\n }\n (swatches as Array<Swatch | null>).forEach((s, i) => {\n let hex: string;\n try {\n hex = normalizeHex(String(s?.hex));\n } catch {\n warnings.push({\n token: (s?.role !== undefined && ROLE_TOKEN[s.role]) || \"--ui-accent\",\n message: `swatches[${i}] dropped: invalid hex ${String(s?.hex)}`,\n });\n return;\n }\n const role = s?.role;\n if (role === \"chart\") charts.push(hex);\n else if (role !== undefined && role !== \"custom\" && byRole[role] === undefined) byRole[role] = hex;\n });\n return { byRole, charts };\n}\n\n/** What {@link mapPaletteToTokens} returns. */\nexport interface MapResult {\n /** The light-mode token map — every name in BRAND_EMITTED_TOKENS. */\n tokens: BrandTokens;\n /** Fallbacks taken and contrast adjustments made. */\n warnings: TokenWarning[];\n}\n\n/**\n * Maps a palette (+ optional typography) onto the full light-mode\n * @odla-ai/ui token set. Never throws on bad palettes: invalid swatches are\n * dropped, missing roles derive from the accent via derivePalette, and every\n * degradation is recorded as a {@link TokenWarning}.\n */\nexport function mapPaletteToTokens(input: CompileInput): MapResult {\n const warnings: TokenWarning[] = [];\n const { byRole, charts } = collect(input?.swatches, warnings);\n\n let accent = byRole.primary;\n if (accent === undefined) {\n const chromatic = [...Object.values(byRole), ...charts].find(\n (h) => h !== undefined && hexToOklch(h).C >= CHROMATIC_C,\n );\n accent = chromatic ?? DEFAULT_ACCENT_SEED;\n warnings.push({\n token: \"--ui-accent\",\n message: `no primary swatch; using ${chromatic !== undefined ? \"the first chromatic swatch\" : \"the neutral default seed\"} ${accent}`,\n });\n }\n\n const fb = new Map<SwatchRole, string>();\n for (const s of derivePalette(accent, { names: false })) if (!fb.has(s.role)) fb.set(s.role, s.hex);\n const pick = (role: SwatchRole): string => {\n const own = byRole[role];\n if (own !== undefined) return own;\n const derived = fb.get(role)!;\n warnings.push({ token: ROLE_TOKEN[role]!, message: `no ${role} swatch; derived ${derived} from ${accent}` });\n return derived;\n };\n\n const bg = pick(\"bg\");\n const surface = pick(\"surface\");\n const neutral = pick(\"neutral\");\n const surface2 = shiftL(surface, -0.035);\n\n const rawText = pick(\"text\");\n const text = ensureOnBg(rawText, bg, 4.5);\n if (text !== rawText)\n warnings.push({ token: \"--ui-text\", message: \"adjusted to reach 4.5:1 on --ui-bg\", adjustedFrom: rawText });\n\n const accentStrong = ensureOnBg(accent, bg, 4.5);\n if (accentStrong !== accent)\n warnings.push({\n token: \"--ui-accent-strong\",\n message: \"moved --ui-accent in lightness to reach 4.5:1 on --ui-bg\",\n adjustedFrom: accent,\n });\n\n const status = (role: \"good\" | \"warn\" | \"danger\"): string => {\n const own = pick(role);\n const fixed = ensureOnBg(own, bg, 3);\n if (fixed !== own)\n warnings.push({ token: ROLE_TOKEN[role]!, message: \"adjusted to reach 3:1 on --ui-bg\", adjustedFrom: own });\n return fixed;\n };\n\n const chromaticCharts = charts.filter((h) => hexToOklch(h).C >= CHROMATIC_C);\n let chartValues: readonly string[];\n if (chromaticCharts.length >= 3) {\n const picked = chromaticCharts.slice(0, 6);\n for (const c of deriveChartColors(accent, { count: 12 })) {\n if (picked.length >= 6) break;\n if (!picked.includes(c)) picked.push(c);\n }\n chartValues = picked;\n } else {\n warnings.push({\n token: \"--ui-chart-1\",\n message: `fewer than 3 chromatic chart swatches (${chromaticCharts.length}); using the ui derived chart defaults`,\n });\n chartValues = UI_CHART_DEFAULTS;\n }\n\n const secondary = byRole.secondary;\n if (secondary === undefined)\n warnings.push({ token: \"--ui-accent-2\", message: \"no secondary swatch; --ui-accent-2 collapses onto var(--ui-accent) (ui default)\" });\n const highlight = byRole.highlight;\n if (highlight === undefined)\n warnings.push({ token: \"--ui-highlight\", message: \"no highlight swatch; --ui-highlight aliases var(--ui-accent-strong) (ui default)\" });\n\n const t = input?.typography ?? {};\n const tokens: BrandTokens = {\n \"--ui-bg\": bg,\n \"--ui-surface\": surface,\n \"--ui-surface-2\": surface2,\n \"--ui-text\": text,\n \"--ui-text-muted\": ensureOnBg(lerpL(text, bg, 0.35), bg, 4.5),\n \"--ui-text-faint\": lerpL(text, bg, 0.58),\n \"--ui-border\": lerpL(neutral, bg, 0.55),\n \"--ui-border-strong\": neutral,\n \"--ui-accent\": accent,\n \"--ui-accent-strong\": accentStrong,\n \"--ui-accent-soft\": mixVar(\"--ui-accent\", 10),\n \"--ui-on-accent\": pickTextOn(accent),\n \"--ui-good\": status(\"good\"),\n \"--ui-good-soft\": mixVar(\"--ui-good\", 12),\n \"--ui-warn\": status(\"warn\"),\n \"--ui-warn-soft\": mixVar(\"--ui-warn\", 12),\n \"--ui-danger\": status(\"danger\"),\n \"--ui-danger-soft\": mixVar(\"--ui-danger\", 10),\n \"--ui-code-bg\": surface2,\n \"--ui-code-text\": text,\n \"--ui-shadow\": `0 1px 2px ${rgbaOf(text, 0.04)}, 0 8px 24px ${rgbaOf(text, 0.06)}`,\n \"--ui-font-sans\": fontValue(t.fontBody, SANS_STACK),\n \"--ui-font-serif\": SERIF_STACK,\n \"--ui-font-mono\": fontValue(t.fontMono, MONO_STACK),\n \"--ui-font-display\": fontValue(t.fontDisplay ?? t.fontBody, DISPLAY_STACK),\n \"--ui-accent-glow\": mixVar(\"--ui-accent\", 16),\n \"--ui-accent-2\": secondary ?? \"var(--ui-accent)\",\n \"--ui-accent-2-soft\": mixVar(\"--ui-accent-2\", 10),\n \"--ui-highlight\": highlight ?? \"var(--ui-accent-strong)\",\n \"--ui-focus\": \"0 0 0 3px var(--ui-accent-soft)\",\n \"--ui-shadow-strong\": \"var(--ui-shadow)\",\n \"--ui-chart-1\": chartValues[0]!,\n \"--ui-chart-2\": chartValues[1]!,\n \"--ui-chart-3\": chartValues[2]!,\n \"--ui-chart-4\": chartValues[3]!,\n \"--ui-chart-5\": chartValues[4]!,\n \"--ui-chart-6\": chartValues[5]!,\n \"--ui-chart-band\": mixVar(\"--ui-accent\", 10),\n \"--ui-chart-band-strong\": mixVar(\"--ui-accent\", 22),\n \"--ui-chart-flow\": \"var(--ui-accent)\",\n \"--ui-chart-glow\": \"var(--ui-accent-strong)\",\n \"--ui-chat-user-bg\": \"var(--ui-accent-soft)\",\n \"--ui-chat-user-text\": \"var(--ui-text)\",\n \"--ui-chat-assistant-bg\": \"var(--ui-surface)\",\n \"--ui-chat-thinking-bg\": \"var(--ui-surface-2)\",\n \"--ui-chat-thinking-text\": \"var(--ui-text-muted)\",\n \"--ui-chat-tool-accent\": \"var(--ui-accent)\",\n };\n return { tokens, warnings };\n}\n","// The reverse token compiler: a design's `--ui-*` declarations → brand\n// swatches.\n//\n// `mapPaletteToTokens` runs brand book → tokens. A Claude design authored on\n// the @odla-ai/ui contract arrives with the OUTPUT of that mapping already\n// filled in, so reading it back is how a design becomes a brand book instead\n// of a one-off page. The inverse is built from the forward map's own\n// ROLE_TOKEN table, so the two cannot drift apart.\n//\n// Only opaque, literal colours convert. A token left as `color-mix(…)`,\n// `rgba(…, 0.13)`, or an unresolved `var(…)` is REPORTED, not guessed at:\n// swatches feed contrast math and a fabricated hex would quietly poison it.\nimport { ROLE_TOKEN } from \"../tokens/map\";\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { assertHex } from \"../validate\";\nimport type { DesignTokenSets } from \"./types\";\n\n/** The chart-series tokens read back as repeated `chart` swatches. */\nconst CHART_TOKENS = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n] as const;\n\n/** One token that could not become a swatch, and why. */\nexport interface DesignTokenSkip {\n token: string;\n value: string;\n reason: string;\n}\n\n/** What {@link swatchesFromDesignTokens} produced. */\nexport interface DesignDecompilation {\n swatches: Swatch[];\n /** Tokens present but not literal opaque colours. */\n skipped: DesignTokenSkip[];\n /** Roles the design declared no token for at all. */\n missing: SwatchRole[];\n}\n\n/** Parse one CSS colour value to `#rrggbb`, or null when it is not a literal\n * opaque colour. Accepts hex and `rgb()`/`rgba()` with alpha exactly 1. */\nexport function cssColorToHex(value: string): string | null {\n const text = value.trim();\n if (text.startsWith(\"#\")) {\n try {\n return assertHex(text);\n } catch {\n return null;\n }\n }\n const fn = /^rgba?\\(([^)]*)\\)$/i.exec(text);\n if (!fn) return null;\n const parts = (fn[1] ?? \"\").split(/[,/\\s]+/).filter((p) => p !== \"\");\n if (parts.length < 3 || parts.length > 4) return null;\n if (parts.length === 4) {\n const alpha = parts[3]!.endsWith(\"%\")\n ? Number.parseFloat(parts[3]!) / 100\n : Number.parseFloat(parts[3]!);\n if (!Number.isFinite(alpha) || alpha < 1) return null;\n }\n const channels = parts.slice(0, 3).map((part) => {\n const n = Number.parseFloat(part);\n if (!Number.isFinite(n)) return Number.NaN;\n return Math.round(part.endsWith(\"%\") ? (n / 100) * 255 : n);\n });\n if (channels.some((c) => !Number.isFinite(c) || c < 0 || c > 255)) return null;\n return `#${channels.map((c) => c.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nconst skipReason = (value: string): string =>\n value.includes(\"var(\")\n ? \"unresolved var() reference\"\n : value.includes(\"color-mix(\")\n ? \"composed with color-mix()\"\n : /rgba?\\(/i.test(value)\n ? \"not fully opaque\"\n : \"not a literal color\";\n\n/**\n * Read a design's declared `--ui-*` tokens back into brand swatches.\n *\n * Reads the LIGHT set: brand palettes are authored light-first and\n * `deriveDarkTokens` regenerates dark on compile, so importing a design's\n * dark values would be overwritten anyway. The design's dark tokens stay\n * visible in the digest for reference.\n */\nexport function swatchesFromDesignTokens(tokens: DesignTokenSets): DesignDecompilation {\n const light = tokens.light;\n const swatches: Swatch[] = [];\n const skipped: DesignTokenSkip[] = [];\n const missing: SwatchRole[] = [];\n\n for (const [role, token] of Object.entries(ROLE_TOKEN) as [SwatchRole, string][]) {\n // `chart` is the series head; the whole series is read below instead.\n if (role === \"chart\") continue;\n const value = light[token];\n if (value === undefined) {\n missing.push(role);\n continue;\n }\n const hex = cssColorToHex(value);\n if (hex === null) {\n skipped.push({ token, value, reason: skipReason(value) });\n continue;\n }\n swatches.push({ role, hex, rationale: `declared by the design as ${token}` });\n }\n\n let anyChart = false;\n for (const token of CHART_TOKENS) {\n const value = light[token];\n if (value === undefined) continue;\n const hex = cssColorToHex(value);\n if (hex === null) {\n skipped.push({ token, value, reason: skipReason(value) });\n continue;\n }\n anyChart = true;\n swatches.push({ role: \"chart\", hex, rationale: `declared by the design as ${token}` });\n }\n if (!anyChart) missing.push(\"chart\");\n\n return { swatches, skipped, missing };\n}\n","// Minimal HTML text helpers shared by the design extractors: entity decoding,\n// tag stripping, and whitespace collapsing.\n//\n// These exist because a design digest quotes human-readable text (headings,\n// prop defaults) that must survive into a model prompt or a JSON file\n// looking like what a person wrote — `&amp;` and `&#39;` in a heading are\n// noise an agent would otherwise reproduce in the site it builds.\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: \"&\",\n lt: \"<\",\n gt: \">\",\n quot: '\"',\n apos: \"'\",\n nbsp: \" \",\n mdash: \"—\",\n ndash: \"–\",\n hellip: \"…\",\n rsquo: \"’\",\n lsquo: \"‘\",\n ldquo: \"“\",\n rdquo: \"”\",\n};\n\n/** Decode the named and numeric HTML entities that appear in real markup. */\nexport function decodeEntities(text: string): string {\n return text.replace(/&(#x[0-9a-fA-F]+|#\\d+|[a-zA-Z][a-zA-Z0-9]{1,31});/g, (whole, body: string) => {\n if (body.startsWith(\"#x\") || body.startsWith(\"#X\")) {\n const code = Number.parseInt(body.slice(2), 16);\n return Number.isFinite(code) && code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : whole;\n }\n if (body.startsWith(\"#\")) {\n const code = Number.parseInt(body.slice(1), 10);\n return Number.isFinite(code) && code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : whole;\n }\n return NAMED_ENTITIES[body.toLowerCase()] ?? whole;\n });\n}\n\n/** Collapse every run of whitespace to a single space and trim. */\nexport const collapseWhitespace = (text: string): string => text.replace(/\\s+/g, \" \").trim();\n\n/**\n * Strip tags and decode entities, yielding the visible text of a markup\n * fragment. Script and style element contents are dropped whole — a heading\n * containing an inline `<style>` would otherwise contribute CSS as prose.\n */\nexport function htmlToText(fragment: string): string {\n const withoutCode = fragment\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script\\s*>/gi, \" \")\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style\\s*>/gi, \" \");\n return collapseWhitespace(decodeEntities(withoutCode.replace(/<[^>]*>/g, \" \")));\n}\n","// The design's information architecture: its title and its heading outline.\n//\n// This is the part of a digest a building agent reads first — it is the site\n// map and the real copy, in document order, at a size that fits in a prompt\n// while the 150 KB template stays on disk.\nimport { htmlToText } from \"./html-text\";\nimport type { DesignOutlineEntry } from \"./types\";\n\n/** Most headings carried into a digest. */\nexport const MAX_OUTLINE_ENTRIES = 120;\n/** Longest single heading kept, in characters. */\nexport const MAX_HEADING_CHARS = 200;\n\n/** The document `<title>`, decoded and collapsed; undefined when unset. */\nexport function extractTitle(html: string): string | undefined {\n const match = /<title\\b[^>]*>([\\s\\S]{0,2000}?)<\\/title\\s*>/i.exec(html);\n if (!match) return undefined;\n const text = htmlToText(match[1] ?? \"\");\n return text === \"\" ? undefined : text.slice(0, MAX_HEADING_CHARS);\n}\n\n/**\n * Headings (`<h1>`…`<h6>`) in document order, as level + visible text.\n *\n * Empty headings — icon-only or decorative — are skipped rather than emitted\n * as blanks. The scan stops at {@link MAX_OUTLINE_ENTRIES}; the caller\n * reports the truncation in the digest.\n */\nexport function extractOutline(html: string): { entries: DesignOutlineEntry[]; truncated: boolean } {\n const pattern = /<h([1-6])\\b[^>]*>([\\s\\S]{0,4000}?)<\\/h\\1\\s*>/gi;\n const entries: DesignOutlineEntry[] = [];\n for (;;) {\n const match = pattern.exec(html);\n if (match === null) break;\n const text = htmlToText(match[2] ?? \"\");\n if (text === \"\") continue;\n if (entries.length >= MAX_OUTLINE_ENTRIES) return { entries, truncated: true };\n entries.push({ level: Number(match[1]), text: text.slice(0, MAX_HEADING_CHARS) });\n }\n return { entries, truncated: false };\n}\n","// The design's declared configuration surface.\n//\n// Claude Design attaches a `data-props` map to the component's logic script:\n// each entry names an editor (text, boolean, enum, …), a default, a\n// TypeScript type, and the panel section it groups under. That map is the\n// design's own statement of WHAT IS MEANT TO VARY — which copy is a\n// placeholder, which layout choices are switches, which values are enums\n// with a fixed set. A building agent that reads it stops guessing which\n// strings are real content and which are stand-ins.\nimport { decodeEntities } from \"./html-text\";\nimport type { DesignProp } from \"./types\";\n\n/** Most props carried into a digest. */\nexport const MAX_PROPS = 60;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Read one HTML attribute's raw (still-escaped) value from a tag soup. */\nfunction attributeValue(html: string, attr: string): string | null {\n const at = html.indexOf(`${attr}=\"`);\n if (at >= 0) {\n const from = at + attr.length + 2;\n const end = html.indexOf('\"', from);\n return end < 0 ? null : html.slice(from, end);\n }\n const single = html.indexOf(`${attr}='`);\n if (single < 0) return null;\n const from = single + attr.length + 2;\n const end = html.indexOf(\"'\", from);\n return end < 0 ? null : html.slice(from, end);\n}\n\n/** Stringify a declared default without inventing a representation. */\nfunction defaultText(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value.slice(0, 400);\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value).slice(0, 400);\n } catch {\n return undefined;\n }\n}\n\nfunction toProp(name: string, spec: Record<string, unknown>): DesignProp {\n const options = Array.isArray(spec.options)\n ? spec.options.filter((v): v is string => typeof v === \"string\").slice(0, 24)\n : undefined;\n const declared = defaultText(spec.default);\n return {\n name: name.slice(0, 80),\n editor: typeof spec.editor === \"string\" ? spec.editor.slice(0, 40) : \"unknown\",\n ...(options && options.length > 0 ? { options } : {}),\n ...(declared !== undefined ? { default: declared } : {}),\n ...(typeof spec.section === \"string\" ? { section: spec.section.slice(0, 80) } : {}),\n ...(typeof spec.tsType === \"string\" ? { tsType: spec.tsType.slice(0, 200) } : {}),\n };\n}\n\n/**\n * Extract the design's declared props, in declaration order.\n *\n * Returns an empty list — never throws — when the design declares none or\n * the attribute is unparseable: props are a bonus signal, and a design\n * without them is still perfectly usable.\n */\nexport function extractProps(html: string): { props: DesignProp[]; truncated: boolean } {\n const at = html.indexOf(\"data-props=\");\n if (at < 0) return { props: [], truncated: false };\n const raw = attributeValue(html.slice(at), \"data-props\");\n if (raw === null) return { props: [], truncated: false };\n let parsed: unknown;\n try {\n parsed = JSON.parse(decodeEntities(raw));\n } catch {\n return { props: [], truncated: false };\n }\n if (!isRecord(parsed)) return { props: [], truncated: false };\n const entries = Object.entries(parsed).filter((entry): entry is [string, Record<string, unknown>] =>\n isRecord(entry[1]),\n );\n return {\n props: entries.slice(0, MAX_PROPS).map(([name, spec]) => toProp(name, spec)),\n truncated: entries.length > MAX_PROPS,\n };\n}\n","// Typeface and colour facts read out of a design's stylesheets.\n//\n// Fonts come from `@font-face` first, on purpose: those are the families the\n// bundle actually SHIPS webfont bytes for, which is a precise answer, where\n// scanning `font-family` stacks yields every system fallback the design ever\n// names. Stacks are only the fallback when a design links its fonts instead\n// of embedding them.\nimport { stripCssComments, styleSheetText } from \"./css-scan\";\nimport type { DesignColorUse } from \"./types\";\n\n/** Most typeface families reported. */\nexport const MAX_FONTS = 16;\n/** Most distinct literal colours reported. */\nexport const MAX_COLORS = 24;\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"inherit\",\n \"initial\",\n \"revert\",\n \"unset\",\n \"currentcolor\",\n]);\n\n/** Strip quotes from one family name and normalize its whitespace. */\nconst familyName = (raw: string): string => raw.trim().replace(/^[\"']|[\"']$/g, \"\").trim();\n\n/** Families the document embeds webfont bytes for, in first-seen order. */\nfunction fontFaceFamilies(css: string): string[] {\n const seen = new Set<string>();\n const blocks = /@font-face\\s*\\{([^}]{0,4000})\\}/gi;\n for (;;) {\n const block = blocks.exec(css);\n if (block === null) break;\n const declared = /font-family\\s*:\\s*([^;]{1,200})/i.exec(block[1] ?? \"\");\n if (!declared) continue;\n const name = familyName(declared[1] ?? \"\");\n if (name !== \"\" && !GENERIC_FAMILIES.has(name.toLowerCase())) seen.add(name);\n }\n return [...seen];\n}\n\n/** Quoted families named anywhere in a `font-family` stack, most-used first. */\nfunction stackFamilies(css: string): string[] {\n const counts = new Map<string, number>();\n const stacks = /font-family\\s*:\\s*([^;{}]{1,400})/gi;\n for (;;) {\n const stack = stacks.exec(css);\n if (stack === null) break;\n for (const part of (stack[1] ?? \"\").split(\",\")) {\n if (!/[\"']/.test(part)) continue;\n const name = familyName(part);\n if (name === \"\" || GENERIC_FAMILIES.has(name.toLowerCase()) || name.includes(\"var(\")) continue;\n counts.set(name, (counts.get(name) ?? 0) + 1);\n }\n }\n return [...counts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)).map(([name]) => name);\n}\n\n/**\n * The typeface families a design uses: the ones it embeds when it embeds\n * any, otherwise the quoted families its font stacks name, ranked by how\n * often they appear.\n */\nexport function extractFonts(templateHtml: string): string[] {\n const css = stripCssComments(styleSheetText(templateHtml));\n const embedded = fontFaceFamilies(css);\n return (embedded.length > 0 ? embedded : stackFamilies(css)).slice(0, MAX_FONTS);\n}\n\n/**\n * Literal `#rrggbb`/`#rgb` colours in the design's CSS, most-used first.\n *\n * Complements the token extractor rather than duplicating it: tokens say\n * what the design DECLARES as its contract, this says what its stylesheets\n * actually paint with — including one-off colours never promoted to a token.\n * Function-syntax colours (`rgba()`, `color-mix()`, `oklch()`) are not\n * counted; they carry alpha or composition that a flat hex tally would\n * misrepresent.\n */\nexport function extractColors(templateHtml: string): DesignColorUse[] {\n const css = stripCssComments(styleSheetText(templateHtml));\n const counts = new Map<string, number>();\n const hexes = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})\\b/g;\n for (;;) {\n const found = hexes.exec(css);\n if (found === null) break;\n const raw = (found[1] ?? \"\").toLowerCase();\n const hex =\n raw.length === 3 ? `#${raw[0]}${raw[0]}${raw[1]}${raw[1]}${raw[2]}${raw[2]}` : `#${raw}`;\n counts.set(hex, (counts.get(hex) ?? 0) + 1);\n }\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1))\n .slice(0, MAX_COLORS)\n .map(([hex, count]): DesignColorUse => ({ hex, count }));\n}\n","// Read a design's effective `--ui-*` design tokens out of its stylesheets.\n//\n// Why resolution is needed rather than a grep: a design authored on the\n// @odla-ai/ui contract typically VENDORS the ui token sheet and then re-keys\n// it, so the final `:root` declares `--ui-accent: var(--accent)` while the\n// brand's own block declares `--accent: #e2562e` several blocks later. The\n// literal declaration is a var() reference; the useful answer is the colour.\n// So the extractor collects every custom property (not just `--ui-*`), folds\n// them in cascade order, and then resolves var() chains — including\n// `var(--x, fallback)` — against that table.\nimport { scanCustomProperties, styleSheetText } from \"./css-scan\";\nimport type { DesignTokenSets } from \"./types\";\n\n/** Deepest var() chain resolved before giving up (cycle guard). */\nconst MAX_VAR_DEPTH = 8;\n\n/** Selectors whose declarations count as document-level tokens. */\nconst DOC_SELECTOR = /(^|,)\\s*(:root|html)\\b|\\[data-theme\\s*=|\\.ui-invert\\b/;\n/** Selectors or at-rule preludes that put a declaration in the dark theme. */\nconst DARK_SELECTOR = /data-theme\\s*=\\s*[\"']?dark|prefers-color-scheme\\s*:\\s*dark|\\.ui-invert\\b/;\n\n/** Split `var(` arguments at the first top-level comma: name, fallback. */\nfunction splitVarArgs(inner: string): { name: string; fallback?: string } {\n let paren = 0;\n for (let i = 0; i < inner.length; i++) {\n const ch = inner[i];\n if (ch === \"(\") paren++;\n else if (ch === \")\") paren--;\n else if (ch === \",\" && paren === 0)\n return { name: inner.slice(0, i).trim(), fallback: inner.slice(i + 1).trim() };\n }\n return { name: inner.trim() };\n}\n\n/**\n * Substitute every `var(--name[, fallback])` in `value` using `table`,\n * recursively. An unresolvable reference falls back to its declared fallback\n * when it has one, and is otherwise left literal so the caller can see that\n * the value did not resolve.\n */\nexport function resolveVarRefs(\n value: string,\n table: ReadonlyMap<string, string>,\n depth = 0,\n): string {\n if (depth >= MAX_VAR_DEPTH || !value.includes(\"var(\")) return value;\n let out = \"\";\n let i = 0;\n for (;;) {\n const at = value.indexOf(\"var(\", i);\n if (at < 0) return out + value.slice(i);\n out += value.slice(i, at);\n let paren = 1;\n let j = at + \"var(\".length;\n for (; j < value.length && paren > 0; j++) {\n if (value[j] === \"(\") paren++;\n else if (value[j] === \")\") paren--;\n }\n // Unbalanced: emit the rest verbatim rather than losing it.\n if (paren > 0) return out + value.slice(at);\n const { name, fallback } = splitVarArgs(value.slice(at + \"var(\".length, j - 1));\n const referenced = table.get(name);\n const replacement =\n referenced !== undefined\n ? resolveVarRefs(referenced, table, depth + 1)\n : fallback !== undefined\n ? resolveVarRefs(fallback, table, depth + 1)\n : `var(${name})`;\n out += replacement;\n i = j;\n }\n}\n\n/** Fold declarations into light/dark custom-property tables (last wins). */\nfunction foldDeclarations(html: string): { light: Map<string, string>; dark: Map<string, string> } {\n const light = new Map<string, string>();\n const darkOverrides: [string, string][] = [];\n for (const decl of scanCustomProperties(styleSheetText(html))) {\n const innermost = decl.selectors[decl.selectors.length - 1] ?? \"\";\n if (!DOC_SELECTOR.test(innermost)) continue;\n if (decl.selectors.some((sel) => DARK_SELECTOR.test(sel))) darkOverrides.push([decl.name, decl.value]);\n else light.set(decl.name, decl.value);\n }\n const dark = new Map(light);\n for (const [name, value] of darkOverrides) dark.set(name, value);\n return { light, dark };\n}\n\n/** Resolve one table's `--ui-*` entries into a plain, var-free record. */\nfunction resolveUiTokens(table: ReadonlyMap<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of table) {\n if (!name.startsWith(\"--ui-\")) continue;\n out[name] = resolveVarRefs(value, table);\n }\n return out;\n}\n\n/**\n * Extract the `--ui-*` tokens a design effectively declares, per theme, with\n * var() chains resolved to their computed text.\n *\n * Declarations are read from document-level selectors only (`:root`, `html`,\n * `[data-theme=…]`, `.ui-invert`); component-scoped custom properties are\n * ignored. Dark inherits every light token it does not override, mirroring\n * how theme sheets are written.\n */\nexport function extractDesignTokens(templateHtml: string): DesignTokenSets {\n const { light, dark } = foldDeclarations(templateHtml);\n return { light: resolveUiTokens(light), dark: resolveUiTokens(dark) };\n}\n","// Assemble the stored, shareable summary of a design.\n//\n// A digest is what everything downstream reads: the preview header, the\n// agent tools, the CLI's `digest.json`, and the palette decompiler. It is\n// deterministic — the same bundle always digests identically — so a stored\n// digest can be compared, diffed, and regenerated without surprises.\n//\n// Every list here is capped, and every cap that actually bit is named in\n// `truncated`. Silently shortening a heading outline would read to an agent\n// as \"that is the whole site\".\nimport { parseDesignBundle } from \"./bundle\";\nimport { extractOutline, extractTitle } from \"./outline\";\nimport { extractProps } from \"./props\";\nimport { extractColors, extractFonts } from \"./styles\";\nimport { extractDesignTokens } from \"./tokens\";\nimport type { DesignAssetGroup, DesignBundle, DesignDigest } from \"./types\";\n\n/** Most external-resource URLs carried into a digest. */\nexport const MAX_EXTERNALS = 24;\n\n/** Group manifest assets by MIME type, heaviest group first. */\nexport function groupAssets(bundle: DesignBundle): DesignAssetGroup[] {\n const groups = new Map<string, DesignAssetGroup>();\n for (const asset of bundle.assets) {\n const group = groups.get(asset.mime) ?? { mime: asset.mime, count: 0, bytes: 0 };\n group.count += 1;\n group.bytes += asset.bytes;\n groups.set(asset.mime, group);\n }\n return [...groups.values()].sort((a, b) => b.bytes - a.bytes || (a.mime < b.mime ? -1 : 1));\n}\n\n/**\n * Build the digest for an already-parsed bundle.\n *\n * `templateBytes` is measured in UTF-8 bytes, not characters, so it matches\n * what the CLI writes to disk for a template full of typographic quotes.\n */\nexport function digestDesignBundle(bundle: DesignBundle): DesignDigest {\n const template = bundle.template;\n const outline = extractOutline(template);\n const props = extractProps(template);\n const assetGroups = groupAssets(bundle);\n const title = extractTitle(template);\n const truncated: string[] = [];\n if (outline.truncated) truncated.push(\"outline\");\n if (props.truncated) truncated.push(\"props\");\n if (bundle.externals.length > MAX_EXTERNALS) truncated.push(\"externals\");\n\n return {\n format: \"claude-design-bundle/1\",\n ...(title ? { title } : {}),\n templateBytes: new TextEncoder().encode(template).byteLength,\n assetBytes: bundle.assets.reduce((total, asset) => total + asset.bytes, 0),\n assetCount: bundle.assets.length,\n assetGroups,\n externals: bundle.externals.slice(0, MAX_EXTERNALS),\n pageCount: bundle.pageOrder.length,\n tokens: extractDesignTokens(template),\n fonts: extractFonts(template),\n colors: extractColors(template),\n props: props.props,\n outline: outline.entries,\n ...(bundle.thumbnailSvg ? { thumbnailSvg: bundle.thumbnailSvg } : {}),\n truncated,\n };\n}\n\n/**\n * Parse a Claude Design standalone-HTML export and digest it in one step.\n * Throws {@link import(\"../errors\").BrandInputError} when the file is not a\n * design bundle.\n */\nexport function digestDesignHtml(html: string): DesignDigest {\n return digestDesignBundle(parseDesignBundle(html));\n}\n","// The WCAG contrast report attached to every palette proposal.\n//\n// Shared by `propose_palette` (colors the agent reasoned its way to) and\n// `propose_palette_from_design` (colors read back out of a design), so a\n// human reviews the same numbers whichever door a palette came through.\nimport { contrastRatio, pickTextOn } from \"./color/index\";\nimport type { Swatch, SwatchRole } from \"./types\";\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100;\n\n/**\n * WCAG contrast ratios (2 dp) for a palette's key role pairs, stored\n * verbatim in the proposal payload so review is numbers, not vibes.\n *\n * Every foreground is measured against the palette's own `bg` (white when\n * it declares none), plus the readability of text placed on `primary`.\n */\nexport function contrastReport(swatches: Swatch[]): Record<string, number> {\n const byRole = (role: SwatchRole): string | undefined =>\n swatches.find((s) => s.role === role)?.hex;\n const bg = byRole(\"bg\") ?? \"#ffffff\";\n const report: Record<string, number> = {};\n const put = (label: string, fg?: string): void => {\n if (fg) report[label] = round2(contrastRatio(fg, bg));\n };\n put(\"text-on-bg\", byRole(\"text\"));\n put(\"primary-on-bg\", byRole(\"primary\"));\n put(\"good-on-bg\", byRole(\"good\"));\n put(\"warn-on-bg\", byRole(\"warn\"));\n put(\"danger-on-bg\", byRole(\"danger\"));\n const primary = byRole(\"primary\");\n if (primary) report[\"text-on-primary\"] = round2(contrastRatio(pickTextOn(primary), primary));\n return report;\n}\n","// The --ui-* custom-property names @odla-ai/brand emits, as data.\n//\n// PROVENANCE: mirrors @odla-ai/ui — the REQUIRED_TOKENS / ACCENT_TOKENS /\n// CHART_TOKENS / CHAT_TOKENS tiers in js/tokens.js, and the\n// :where([data-ui-accent]) re-declaration block in css/tokens.css.\n//\n// Why more than the required tier: a compiled token object doubles as a\n// runtime override-island payload, and CSS custom properties substitute\n// var() at computed-value time ON THE DECLARING ELEMENT. An island that\n// overrides --ui-accent alone would keep the :root-computed --ui-chart-1,\n// --ui-accent-glow, … stale. So besides the required tier the compiler\n// re-declares the whole accent-composing derived family — everything the\n// ui root's :where([data-ui-accent]) block re-declares, plus the remaining\n// chart series and chat roles so charts and chat surfaces recompute against\n// the brand palette too. test/tokens/map.test.ts cross-checks these lists\n// against the real @odla-ai/ui export, so they cannot drift silently.\n\n/**\n * The @odla-ai/ui required tier (js/tokens.js REQUIRED_TOKENS), in the ui\n * contract's order. The compiler always emits a concrete value for every\n * one of these.\n */\nexport const BRAND_REQUIRED_TOKENS = [\n \"--ui-bg\",\n \"--ui-surface\",\n \"--ui-surface-2\",\n \"--ui-text\",\n \"--ui-text-muted\",\n \"--ui-text-faint\",\n \"--ui-border\",\n \"--ui-border-strong\",\n \"--ui-accent\",\n \"--ui-accent-strong\",\n \"--ui-accent-soft\",\n \"--ui-on-accent\",\n \"--ui-good\",\n \"--ui-good-soft\",\n \"--ui-warn\",\n \"--ui-warn-soft\",\n \"--ui-danger\",\n \"--ui-danger-soft\",\n \"--ui-code-bg\",\n \"--ui-code-text\",\n \"--ui-shadow\",\n \"--ui-font-sans\",\n \"--ui-font-serif\",\n \"--ui-font-mono\",\n \"--ui-font-display\",\n] as const;\n\n/**\n * Accent-composing derived roles from the ui defaulted tier. All five\n * accent-family members of the :where([data-ui-accent]) re-declaration set\n * (--ui-accent-glow, --ui-accent-2, --ui-accent-2-soft, --ui-highlight,\n * --ui-focus) plus --ui-shadow-strong, which composes var(--ui-shadow) —\n * a token this compiler re-declares, so the island rule applies to it too.\n */\nexport const BRAND_DERIVED_TOKENS = [\n \"--ui-accent-glow\",\n \"--ui-accent-2\",\n \"--ui-accent-2-soft\",\n \"--ui-highlight\",\n \"--ui-focus\",\n \"--ui-shadow-strong\",\n] as const;\n\n/**\n * Chart roles the compiler emits: the six series slots (real palette\n * swatches when the palette carries them, ui var() compositions otherwise)\n * and the four accent-composing chart roles the :where([data-ui-accent])\n * block re-declares (band, band-strong, flow, glow).\n */\nexport const BRAND_CHART_TOKENS = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n \"--ui-chart-band\",\n \"--ui-chart-band-strong\",\n \"--ui-chart-flow\",\n \"--ui-chart-glow\",\n] as const;\n\n/**\n * Chat surface roles (js/tokens.js CHAT_TOKENS, complete). Two are in the\n * accent-swap set (user-bg, tool-accent); the other four compose surface /\n * text tokens the compiler also re-declares, so an island stays coherent.\n */\nexport const BRAND_CHAT_TOKENS = [\n \"--ui-chat-user-bg\",\n \"--ui-chat-user-text\",\n \"--ui-chat-assistant-bg\",\n \"--ui-chat-thinking-bg\",\n \"--ui-chat-thinking-text\",\n \"--ui-chat-tool-accent\",\n] as const;\n\n/**\n * Every token the compiler emits, in emission order — also the deterministic\n * declaration order renderTokensCss uses, so golden CSS fixtures are stable.\n */\nexport const BRAND_EMITTED_TOKENS: readonly string[] = [\n ...BRAND_REQUIRED_TOKENS,\n ...BRAND_DERIVED_TOKENS,\n ...BRAND_CHART_TOKENS,\n ...BRAND_CHAT_TOKENS,\n];\n","// Light → dark token derivation.\n//\n// Neutrals (bg / text ladder / borders / code text) flip around OKLab L 0.5:\n// L' = 1 − L reflected, then squeezed into [DARK_FLIP_L_MIN,\n// DARK_FLIP_L_MAX] so the background lands dark but never black and text\n// lands light but never pure white. Chroma and hue are untouched, so tinted\n// neutrals keep their brand tint.\n//\n// Surfaces are the one place a mirror is wrong: light surfaces sit ABOVE\n// the light bg (lighter), so mirroring would drop them BELOW the dark bg —\n// inverted elevation. Instead the surface ladder is rebuilt upward from the\n// derived dark bg (the @odla-ai/ui dark-neutral pattern: bg < surface <\n// surface-2), reusing the light ladder's own lightness gaps as rung heights\n// (with a small minimum so equal-ish inputs still separate).\n//\n// Accents (accent family, statuses) and chart series keep their hue/chroma\n// and are re-lightened with adjustLightnessUntil until they clear WCAG bars\n// against the derived dark bg: 4.5:1 for the accent family and statuses\n// (SC 1.4.3), 3:1 for chart series (SC 1.4.11 graphics). --ui-on-accent is\n// re-picked against the dark accent. Everything else — var()/color-mix()\n// compositions, font stacks, focus ring — passes through unchanged and\n// recomputes in CSS against the dark values (--ui-shadow is the one literal\n// that gets the ui dark shadow instead).\n\nimport {\n adjustLightnessUntil,\n clampToGamut,\n contrastRatio,\n hexToOklch,\n oklchToHex,\n pickTextOn,\n} from \"../color\";\nimport type { BrandTokens } from \"./types\";\n\n/** Darkest OKLab L a flipped neutral may take — the dark bg floor (never black). */\nexport const DARK_FLIP_L_MIN = 0.2;\n\n/** Lightest OKLab L a flipped neutral may take — keeps flipped text off pure white. */\nexport const DARK_FLIP_L_MAX = 0.95;\n\n/** The ui neutral dark shadow (css/tokens.css `[data-theme=\"dark\"]` value). */\nconst DARK_SHADOW = \"0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35)\";\n\nconst HEX6 = /^#[0-9a-f]{6}$/;\n\n/** Neutral ladder: flipped around L 0.5 with the floor/ceiling squeeze.\n * Surfaces/code-bg are here only as a fallback — with a hex bg present they\n * are rebuilt upward from the dark bg instead (see file header). */\nconst NEUTRAL_FLIP = new Set([\n \"--ui-bg\",\n \"--ui-surface\",\n \"--ui-surface-2\",\n \"--ui-text\",\n \"--ui-text-muted\",\n \"--ui-text-faint\",\n \"--ui-border\",\n \"--ui-border-strong\",\n \"--ui-code-bg\",\n \"--ui-code-text\",\n]);\n\n/** Minimum OKLab ΔL between dark surface rungs, so elevation always reads. */\nconst MIN_RUNG = 0.02;\n\n/** Re-lightened until ≥ 4.5:1 on the dark bg (readable as text). */\nconst ACCENT_AA = [\n \"--ui-accent\",\n \"--ui-accent-strong\",\n \"--ui-accent-2\",\n \"--ui-highlight\",\n \"--ui-good\",\n \"--ui-warn\",\n \"--ui-danger\",\n] as const;\n\n/** Re-lightened until ≥ 3:1 on the dark bg (graphics bar). */\nconst CHART_UI = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n] as const;\n\nfunction flipNeutral(hex: string): string {\n const { L, C, h } = hexToOklch(hex);\n const flipped = DARK_FLIP_L_MIN + (1 - L) * (DARK_FLIP_L_MAX - DARK_FLIP_L_MIN);\n return oklchToHex(clampToGamut({ L: flipped, C, h }));\n}\n\n/**\n * Rebuild bg < surface < surface-2 upward from the dark bg, using the light\n * ladder's own |ΔL| gaps as rung heights (floored at MIN_RUNG). code-bg\n * follows surface-2 when the light map aliased them, else takes its own\n * bg-relative rung. Mutates `out`; skips any token that is absent/non-hex.\n */\nfunction rebuildSurfaces(out: BrandTokens, light: BrandTokens, lightBgL: number, darkBgL: number): void {\n const lightSurface = light[\"--ui-surface\"];\n const lightSurface2 = light[\"--ui-surface-2\"];\n let surfaceDarkL: number | undefined;\n let surfaceLightL = lightBgL;\n if (lightSurface !== undefined && HEX6.test(lightSurface)) {\n const { L, C, h } = hexToOklch(lightSurface);\n surfaceLightL = L;\n surfaceDarkL = darkBgL + Math.max(Math.abs(L - lightBgL), MIN_RUNG);\n out[\"--ui-surface\"] = oklchToHex(clampToGamut({ L: surfaceDarkL, C, h }));\n }\n if (lightSurface2 !== undefined && HEX6.test(lightSurface2)) {\n const { L, C, h } = hexToOklch(lightSurface2);\n const base = surfaceDarkL ?? darkBgL + MIN_RUNG;\n const L2 = base + Math.max(Math.abs(L - surfaceLightL), MIN_RUNG);\n out[\"--ui-surface-2\"] = oklchToHex(clampToGamut({ L: L2, C, h }));\n }\n const lightCodeBg = light[\"--ui-code-bg\"];\n if (lightCodeBg !== undefined && HEX6.test(lightCodeBg)) {\n if (lightCodeBg === lightSurface2 && out[\"--ui-surface-2\"] !== undefined) {\n out[\"--ui-code-bg\"] = out[\"--ui-surface-2\"];\n } else {\n const { L, C, h } = hexToOklch(lightCodeBg);\n const codeL = darkBgL + Math.max(Math.abs(L - lightBgL), MIN_RUNG);\n out[\"--ui-code-bg\"] = oklchToHex(clampToGamut({ L: codeL, C, h }));\n }\n }\n}\n\n/** Lighten (else darken; else pickTextOn) until ≥ `min`:1 on `bg`. */\nfunction relight(hex: string, bg: string, min: number): string {\n const pred = (c: string): boolean => contrastRatio(c, bg) >= min;\n return (\n adjustLightnessUntil(hex, pred, \"lighten\") ??\n adjustLightnessUntil(hex, pred, \"darken\") ??\n pickTextOn(bg)\n );\n}\n\n/**\n * Derives the dark-mode token map from a light one (see the file header for\n * the flip / re-lighten / passthrough rules). Pure and total: tokens the\n * rules don't recognize — including non-hex values in recognized slots —\n * pass through unchanged, and the result always has exactly the input's\n * key set. Deterministic, never throws.\n */\nexport function deriveDarkTokens(light: BrandTokens): BrandTokens {\n const out: BrandTokens = {};\n for (const [name, value] of Object.entries(light)) {\n if (name === \"--ui-shadow\") out[name] = DARK_SHADOW;\n else if (NEUTRAL_FLIP.has(name) && HEX6.test(value)) out[name] = flipNeutral(value);\n else out[name] = value;\n }\n\n const bg = out[\"--ui-bg\"];\n const lightBg = light[\"--ui-bg\"];\n if (bg === undefined || !HEX6.test(bg) || lightBg === undefined || !HEX6.test(lightBg)) return out;\n\n rebuildSurfaces(out, light, hexToOklch(lightBg).L, hexToOklch(bg).L);\n\n for (const name of [\"--ui-text\", \"--ui-text-muted\"]) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 4.5);\n }\n const codeBg = out[\"--ui-code-bg\"];\n const codeText = out[\"--ui-code-text\"];\n if (codeText !== undefined && HEX6.test(codeText))\n out[\"--ui-code-text\"] = relight(codeText, codeBg !== undefined && HEX6.test(codeBg) ? codeBg : bg, 4.5);\n\n for (const name of ACCENT_AA) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 4.5);\n }\n for (const name of CHART_UI) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 3);\n }\n\n const accent = out[\"--ui-accent\"];\n const onAccent = out[\"--ui-on-accent\"];\n if (accent !== undefined && HEX6.test(accent) && onAccent !== undefined && HEX6.test(onAccent))\n out[\"--ui-on-accent\"] = pickTextOn(accent);\n\n return out;\n}\n","// Compiled tokens → theme CSS text.\n//\n// The output's shape mirrors a real @odla-ai/ui theme tokens file\n// (themes/juniper/tokens.css): a light block, a `[data-theme=\"dark\"]`\n// attribute block, the same dark values repeated under\n// `@media (prefers-color-scheme: dark)` guarded by\n// `:root:not([data-theme=\"light\"])` (so an explicit light preference beats\n// the system's dark scheme), and optionally a `.ui-invert` island block.\n// The attribute/media blocks carry only the tokens that CHANGE in dark —\n// the ui convention, since var()/color-mix() compositions declared in the\n// light block recompute on the same element. The `.ui-invert` island gets\n// the FULL dark payload: on an island, root-computed composites would be\n// stale (see roles.ts).\n//\n// Declarations render in BRAND_EMITTED_TOKENS order (unknown tokens last,\n// alphabetically), so output is deterministic and golden-testable.\n\nimport { BRAND_EMITTED_TOKENS } from \"./roles\";\nimport type { BrandTokens } from \"./types\";\n\n/** Options for {@link renderTokensCss}. */\nexport interface RenderTokensCssOptions {\n /** Dark-mode tokens (deriveDarkTokens output). Omit for a light-only sheet. */\n dark?: BrandTokens;\n /**\n * Selector the light block declares on (default \":root\"). A scoped\n * selector (e.g. `[data-brand=\"acme\"]`) gets its dark blocks nested under\n * the document-level theme guards instead of replacing them.\n */\n selector?: string;\n /**\n * Also emit a `.ui-invert` block carrying the full dark payload, so the\n * subtree renders dark regardless of the global mode. Requires `dark`.\n */\n includeInvert?: boolean;\n}\n\nconst HEADER =\n \"/* Generated by @odla-ai/brand — @odla-ai/ui token overrides; pair with @odla-ai/ui css/tokens.css. */\";\n\nconst ORDER = new Map<string, number>(\n BRAND_EMITTED_TOKENS.map((name, i): [string, number] => [name, i]),\n);\n\n/** Emission order: BRAND_EMITTED_TOKENS index, then unknown names A→Z. */\nfunction orderedNames(tokens: BrandTokens): string[] {\n return Object.keys(tokens).sort((a, b) => {\n const ia = ORDER.get(a);\n const ib = ORDER.get(b);\n if (ia !== undefined && ib !== undefined) return ia - ib;\n if (ia !== undefined) return -1;\n if (ib !== undefined) return 1;\n return a < b ? -1 : a > b ? 1 : 0;\n });\n}\n\nfunction renderBlock(\n selector: string,\n tokens: BrandTokens,\n names: readonly string[],\n indent: string,\n lead?: string,\n): string {\n const lines: string[] = [];\n if (lead !== undefined) lines.push(`${indent} ${lead}`);\n for (const name of names) lines.push(`${indent} ${name}: ${tokens[name]};`);\n if (lines.length === 0) return `${indent}${selector} {\\n${indent}}`;\n return `${indent}${selector} {\\n${lines.join(\"\\n\")}\\n${indent}}`;\n}\n\n/**\n * Renders a compiled token map (plus optional dark map) as CSS text shaped\n * like an @odla-ai/ui theme tokens file — see the file header for the block\n * structure and ordering guarantees. Deterministic for a given input.\n */\nexport function renderTokensCss(light: BrandTokens, opts: RenderTokensCssOptions = {}): string {\n const selector = opts.selector ?? \":root\";\n const scoped = selector !== \":root\";\n const parts: string[] = [HEADER, renderBlock(selector, light, orderedNames(light), \"\")];\n\n const dark = opts.dark;\n if (dark !== undefined) {\n const diffNames = orderedNames(dark).filter((name) => light[name] !== dark[name]);\n if (diffNames.length > 0) {\n const attrSelector = scoped\n ? `[data-theme=\"dark\"] ${selector}, ${selector}[data-theme=\"dark\"]`\n : `[data-theme=\"dark\"]`;\n const mediaSelector = scoped\n ? `:root:not([data-theme=\"light\"]) ${selector}`\n : `:root:not([data-theme=\"light\"])`;\n parts.push(renderBlock(attrSelector, dark, diffNames, \"\"));\n parts.push(\n `@media (prefers-color-scheme: dark) {\\n${renderBlock(mediaSelector, dark, diffNames, \" \")}\\n}`,\n );\n }\n if (opts.includeInvert === true) {\n parts.push(renderBlock(\".ui-invert\", dark, orderedNames(dark), \"\", \"color-scheme: dark;\"));\n }\n }\n return `${parts.join(\"\\n\\n\")}\\n`;\n}\n","// The compiler facade: palette + typography (+ author overrides) →\n// { light, dark, warnings }. Light comes from mapPaletteToTokens, overrides\n// are layered on last (so authors can pin any token, including ones this\n// compiler doesn't own, like --ui-radius-md), and dark derives from the\n// FINAL light map — an overridden accent flows into the dark derivation.\n//\n// Never throws on bad palettes: map.ts drops invalid swatches and derives\n// missing roles (each degradation becomes a TokenWarning), and malformed\n// overrides are skipped with a warning rather than rejected.\n\nimport { deriveDarkTokens } from \"./dark\";\nimport { mapPaletteToTokens } from \"./map\";\nimport type { CompiledBrandTokens, CompileInput, TokenWarning } from \"./types\";\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Layer `overrides` onto `light` in place; malformed entries warn + skip. */\nfunction applyOverrides(\n light: Record<string, string>,\n overrides: unknown,\n warnings: TokenWarning[],\n): void {\n if (overrides === undefined) return;\n if (!isRecord(overrides)) {\n warnings.push({ token: \"--ui-accent\", message: \"overrides ignored: not an object\" });\n return;\n }\n for (const [name, value] of Object.entries(overrides)) {\n if (!name.startsWith(\"--\")) {\n warnings.push({ token: name, message: \"override ignored: token names must start with --\" });\n continue;\n }\n if (typeof value !== \"string\" || value.trim() === \"\") {\n warnings.push({ token: name, message: \"override ignored: value must be a non-empty string\" });\n continue;\n }\n light[name] = value.trim();\n }\n}\n\n/**\n * Compiles a brand palette into @odla-ai/ui design tokens: a light map\n * covering every name in BRAND_EMITTED_TOKENS (plus overrides), a dark map\n * derived from it (same key set), and the warnings accumulated along the\n * way — missing-role fallbacks and contrast adjustments (`adjustedFrom`).\n *\n * Both maps double as runtime override-island payloads: every derived\n * default that composes the accent family is re-declared, so applying the\n * map on any element recomputes charts, softs, focus and chat roles against\n * the brand palette (see roles.ts). Deterministic; never throws on bad\n * palettes.\n */\nexport function compileBrandTokens(input: CompileInput): CompiledBrandTokens {\n const { tokens: light, warnings } = mapPaletteToTokens(input);\n applyOverrides(light, input?.overrides, warnings);\n const dark = deriveDarkTokens(light);\n return { light, dark, warnings };\n}\n","// Asset tools: view_asset feeds real uploaded bytes to the model as an\n// image/document block inside the tool result (the vision path), and\n// record_asset_analysis persists what the model saw through the validated\n// ops layer. view_asset output is model-visible content fetched from\n// storage, so the tool declares `tool_untrusted:view_asset` taint.\n// @odla-ai/ai is imported for types only.\nimport type { DocumentBlock, ImageBlock, ImageMediaType, TextBlock, ToolDef, ToolOutput } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset } from \"../types\";\nimport { assertAnalysis } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Byte cap for in-conversation asset viewing (4.5 MiB — providers reject\n * larger inline payloads well before context does). */\nexport const MAX_VIEW_BYTES = 4_718_592;\n\nconst IMAGE_TYPES: ReadonlySet<string> = new Set([\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]);\n\n/**\n * Base64-encode bytes without assuming a platform: `btoa` over a chunked\n * binary string where available (workerd, browsers, Node ≥ 16), `Buffer`\n * otherwise. Chunking keeps `String.fromCharCode` off the argument-count\n * cliff for multi-megabyte assets.\n */\nexport function base64FromBytes(bytes: Uint8Array): string {\n if (typeof btoa === \"function\") {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x2000) {\n binary += String.fromCharCode(...bytes.subarray(i, i + 0x2000));\n }\n return btoa(binary);\n }\n return Buffer.from(bytes).toString(\"base64\");\n}\n\nconst bareType = (ct: string): string => (ct.split(\";\")[0] ?? \"\").trim().toLowerCase();\n\nfunction viewOutput(asset: BrandAsset, bytes: Uint8Array, contentType: string): ToolOutput {\n const caption: TextBlock = {\n type: \"text\",\n text: `Asset ${asset.id} (${asset.kind}, ${contentType}, ${bytes.byteLength} bytes${asset.title ? `, \"${asset.title}\"` : \"\"}):`,\n };\n if (IMAGE_TYPES.has(contentType)) {\n const image: ImageBlock = {\n type: \"image\",\n source: { type: \"base64\", mediaType: contentType as ImageMediaType, data: base64FromBytes(bytes) },\n };\n return { content: [caption, image] };\n }\n const document: DocumentBlock = {\n type: \"document\",\n source: { type: \"base64\", mediaType: \"application/pdf\", data: base64FromBytes(bytes) },\n };\n return { content: [caption, document] };\n}\n\n/**\n * The asset tools, scoped to the context's book: `view_asset` (fetch the\n * stored bytes and return them as an image/PDF block, with size and type\n * gates) and `record_asset_analysis` (persist the model's description,\n * dominant colors, and tags onto the asset row).\n */\nexport function assetTools(ctx: BrandToolCtx): ToolDef[] {\n const loadAsset = async (assetId: string): Promise<BrandAsset> => {\n const book = await ctx.loadBook();\n const res = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: assetId, bookId: ctx.bookId } },\n book: {},\n },\n });\n const row = (res[BRAND_NS.asset] ?? [])[0] as\n | (BrandAsset & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n row.status !== \"live\" ||\n row.deletedAt ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== book.id\n ) throw new BrandNotFoundError(`asset ${assetId}`);\n return row;\n };\n\n const viewAsset: ToolDef = {\n name: \"view_asset\",\n description:\n \"Look at an uploaded asset: fetches its bytes and returns the image (png/jpeg/gif/webp) or PDF for you to view. Other types cannot be viewed in-conversation.\",\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: { assetId: { type: \"string\", description: \"The asset row id from list_assets.\" } },\n },\n outputTaint: [\"tool_untrusted:view_asset\"],\n handler: ctx.guard(async (input) => {\n const asset = await loadAsset(String(input.assetId));\n if (!ctx.visionInToolResults) {\n return {\n content:\n `This model cannot take images inside tool results. Asset ${asset.id} must be attached ` +\n \"as a pre-turn image by the host instead — ask the human to re-send their message \" +\n \"referencing the asset (the dispatcher attaches it up front), or describe it from \" +\n \"what they tell you.\",\n };\n }\n const read = await ctx.authority(\"brand.read\");\n const fetched = await ctx.readAssetContent(asset.id);\n if (fetched.bytes.byteLength > MAX_VIEW_BYTES) {\n return {\n content:\n `Asset ${asset.id} is ${fetched.bytes.byteLength} bytes — over the ${MAX_VIEW_BYTES}-byte ` +\n \"(4.5 MB) in-conversation viewing cap. Ask the human for a smaller export of this file.\",\n };\n }\n const served = bareType(fetched.contentType);\n const effective = IMAGE_TYPES.has(served) || served === \"application/pdf\" ? served : bareType(asset.contentType);\n if (!IMAGE_TYPES.has(effective) && effective !== \"application/pdf\") {\n return {\n content:\n `Asset ${asset.id} is ${effective} — stored but not viewable in-conversation. ` +\n \"Ask the human to describe it, or to upload a PNG/JPEG export you can view.\",\n };\n }\n return viewOutput(asset, fetched.bytes, effective);\n }),\n };\n\n const recordAnalysis: ToolDef = {\n name: \"record_asset_analysis\",\n description:\n \"Record what you observed in an asset you viewed. Uses guarded analysis revisions so concurrent agents cannot overwrite each other silently.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\", \"description\", \"dominantColors\", \"tags\"],\n properties: {\n assetId: { type: \"string\" },\n description: { type: \"string\", description: \"What the asset shows (max 2000 chars).\" },\n dominantColors: { type: \"array\", items: { type: \"string\" }, maxItems: 12, description: \"Dominant colors as hex.\" },\n tags: { type: \"array\", items: { type: \"string\" }, maxItems: 24 },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadAsset(String(input.assetId));\n await ctx.authority(\"brand.edit\");\n const analysis = assertAnalysis({\n description: input.description,\n dominantColors: input.dominantColors,\n tags: input.tags,\n });\n const updated = await ctx.recordAssetAnalysis({\n mutationId: ctx.newId(),\n assetId: asset.id,\n analysis,\n expectedAnalysisRevision: asset.analysisRevision,\n });\n if (\n updated.id !== asset.id ||\n updated.bookId !== ctx.bookId ||\n updated.status !== \"live\" ||\n updated.analysisRevision !== asset.analysisRevision + 1 ||\n updated.analyzedBy !== ctx.self.selfId\n ) throw new BrandNotFoundError(\"asset analysis bridge returned invalid state\");\n return {\n content: `Recorded analysis for asset ${asset.id}: ${analysis.dominantColors.length} dominant color(s), ${analysis.tags.length} tag(s).`,\n };\n }),\n };\n\n return [viewAsset, recordAnalysis];\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandBook } from \"../types\";\nimport { capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Validate an optional proposal source against the exact live linked book. */\nexport async function proposalSourceAssetId(\n ctx: BrandToolCtx,\n book: BrandBook,\n value: unknown,\n): Promise<string | undefined> {\n if (value === undefined) return undefined;\n const sourceAssetId = capString(value, \"sourceAssetId\", 200);\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: {\n where: { id: sourceAssetId, bookId: book.id, status: \"live\" },\n limit: 2,\n },\n book: { $: { limit: 2 } },\n },\n });\n const rows = result[BRAND_NS.asset] ?? [];\n const asset = rows.length === 1\n ? rows[0] as {\n id?: string;\n bookId?: string;\n status?: string;\n deletedAt?: number;\n book?: Array<{ id: string }>;\n }\n : undefined;\n if (\n !asset ||\n asset.id !== sourceAssetId ||\n asset.bookId !== book.id ||\n asset.status !== \"live\" ||\n asset.deletedAt !== undefined ||\n !Array.isArray(asset.book) ||\n asset.book.length !== 1 ||\n asset.book[0]?.id !== book.id\n ) throw new BrandInputError(\n \"sourceAssetId must be a live asset in this brand book\",\n );\n return sourceAssetId;\n}\n","// Non-palette brand-facet proposal tool. Agent-authored changes never touch\n// the live natural-key section; a human decision route applies accepted\n// content as an approved section with a durable receipt.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport {\n SECTION_KINDS,\n type SectionKind,\n} from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { assertSectionContent, capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\nimport { proposalSourceAssetId } from \"./source-asset\";\n\nconst PROPOSABLE = SECTION_KINDS.filter((kind) => kind !== \"palette\");\n\n/** `update_section` validates a draft and parks it as an OPEN proposal. */\nexport function bookTools(ctx: BrandToolCtx): ToolDef[] {\n return [{\n name: \"update_section\",\n description:\n \"Propose a typography, voice, logo, or imagery section revision for human approval. This never overwrites the live approved section.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"kind\", \"content\", \"rationale\"],\n properties: {\n kind: { type: \"string\", enum: PROPOSABLE },\n content: { type: \"object\", description: \"The complete proposed section payload.\" },\n rationale: { type: \"string\", description: \"Why this revision should replace the live section.\" },\n sourceAssetId: {\n type: \"string\",\n description: \"Optional exact live Brand asset that grounds this revision.\",\n },\n },\n },\n handler: ctx.guard(async (input) => {\n const allowed = new Set([\"kind\", \"content\", \"rationale\", \"sourceAssetId\"]);\n if (Object.keys(input).some((key) => !allowed.has(key)))\n throw new BrandInputError(\"section proposal has unknown fields\");\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const kind = input.kind as SectionKind;\n if (kind === \"palette\" || !PROPOSABLE.includes(kind))\n throw new BrandInputError(`kind must be one of: ${PROPOSABLE.join(\", \")}`);\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const sourceAssetId = await proposalSourceAssetId(\n ctx,\n book,\n input.sourceAssetId,\n );\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind,\n payload: {\n content: assertSectionContent(kind, input.content),\n },\n rationale,\n ...(sourceAssetId ? { sourceAssetId } : {}),\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== kind ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n return {\n content:\n `Parked ${kind} section proposal ${proposal.id}. The live section is unchanged; ` +\n \"a human must approve this exact revision.\",\n };\n }),\n }];\n}\n","// Color-exploration + proposal tools. analyze_color / evaluate_contrast are\n// pure math over the color engine (the agent's grounding for every hex it\n// suggests); propose_palette PARKS a proposal for human review — it never\n// activates anything. Proposal resolution is intentionally absent from the\n// agent skill; a human uses createBrandRoutes' guarded approval endpoint.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport {\n analogous,\n complementary,\n contrastRatio,\n derivePalette,\n hexToOklch,\n meetsAA,\n meetsAAA,\n monochrome,\n nearestNamedColor,\n pickTextOn,\n relativeLuminance,\n splitComplementary,\n tetradic,\n tintShadeRamp,\n triadic,\n} from \"../color/index\";\nimport { BrandInputError } from \"../errors\";\nimport { contrastReport } from \"../palette-report\";\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { assertHex, assertSwatches, capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\nimport { proposalSourceAssetId } from \"./source-asset\";\n\nconst r2 = (n: number): string => n.toFixed(2);\nconst pf = (ok: boolean): string => (ok ? \"pass\" : \"FAIL\");\n\nconst verdict = (ratio: number): string =>\n `${r2(ratio)}:1 — AA text ${pf(meetsAA(ratio))}, AA large/ui ${pf(meetsAA(ratio, \"large-text\"))}, AAA text ${pf(meetsAAA(ratio))}`;\n\n/** Harmony strategies propose_palette accepts, mapped to the seed companions\n * that replace the derived secondary/highlight (in that order). */\nconst HARMONY_COMPANIONS: Record<string, (seed: string) => string[]> = {\n complementary: (s) => [complementary(s)],\n analogous: (s) => [...analogous(s)],\n triadic: (s) => [...triadic(s)],\n split: (s) => [...splitComplementary(s)],\n tetradic: (s) => tetradic(s).slice(0, 2),\n monochrome: (s) => monochrome(s, 4).slice(1, 3),\n};\n\nfunction applyHarmony(swatches: Swatch[], seedHex: string, harmony: unknown): Swatch[] {\n if (typeof harmony !== \"string\" || !(harmony in HARMONY_COMPANIONS)) {\n throw new BrandInputError(`harmony must be one of: ${Object.keys(HARMONY_COMPANIONS).join(\", \")}`);\n }\n const [secondary, highlight] = HARMONY_COMPANIONS[harmony]!(seedHex);\n return swatches.map((s) => {\n const hex = s.role === \"secondary\" ? secondary : s.role === \"highlight\" ? highlight : undefined;\n if (!hex) return s;\n return { ...s, hex, name: nearestNamedColor(hex).name, rationale: `${harmony} companion of the seed` };\n });\n}\n\nconst INCLUDE_SECTIONS = [\"harmony\", \"ramp\"] as const;\n\nfunction analyzeLines(hex: string, include: string[]): string[] {\n const lch = hexToOklch(hex);\n const named = nearestNamedColor(hex);\n const lines = [\n `${hex} — nearest CSS name: ${named.name} (ΔEOK ${named.deltaEOK.toFixed(3)})`,\n `OKLCH: L ${lch.L.toFixed(3)}, C ${lch.C.toFixed(3)}, h ${lch.h.toFixed(1)}°`,\n `relative luminance ${relativeLuminance(hex).toFixed(3)}; contrast ${r2(contrastRatio(hex, \"#ffffff\"))}:1 on white, ${r2(contrastRatio(hex, \"#000000\"))}:1 on black`,\n `readable text on it: ${pickTextOn(hex)}`,\n ];\n if (include.includes(\"harmony\")) {\n const [aMinus, aPlus] = analogous(hex);\n const [tMinus, tPlus] = triadic(hex);\n const [sMinus, sPlus] = splitComplementary(hex);\n lines.push(\n `harmony — complementary ${complementary(hex)}; analogous ${aMinus} ${aPlus}; triadic ${tMinus} ${tPlus}; split ${sMinus} ${sPlus}`,\n );\n }\n if (include.includes(\"ramp\")) lines.push(`ramp — ${tintShadeRamp(hex).join(\" \")}`);\n return lines;\n}\n\n/**\n * The palette tools: `analyze_color`, `evaluate_contrast` (pure math),\n * `propose_palette` (writes an OPEN proposal with an automatic contrast\n * report). Resolution is deliberately not an agent tool.\n */\nexport function paletteTools(ctx: BrandToolCtx): ToolDef[] {\n const analyzeColor: ToolDef = {\n name: \"analyze_color\",\n description:\n \"Analyze one color: nearest CSS name, OKLCH coordinates, luminance, contrast on white/black. Optionally include harmony companions and a tint/shade ramp.\",\n inputSchema: {\n type: \"object\",\n required: [\"hex\"],\n properties: {\n hex: { type: \"string\", description: \"#rgb or #rrggbb\" },\n include: { type: \"array\", items: { type: \"string\", enum: [...INCLUDE_SECTIONS] } },\n },\n },\n handler: ctx.guard(async (input) => {\n const hex = assertHex(input.hex, \"hex\");\n const include = input.include === undefined ? [] : input.include;\n if (!Array.isArray(include) || include.some((s) => !(INCLUDE_SECTIONS as readonly unknown[]).includes(s))) {\n throw new BrandInputError(`include entries must be one of: ${INCLUDE_SECTIONS.join(\", \")}`);\n }\n return { content: analyzeLines(hex, include as string[]).join(\"\\n\") };\n }),\n };\n\n const evaluateContrast: ToolDef = {\n name: \"evaluate_contrast\",\n description:\n \"WCAG 2.1 contrast: pass pairs ([{fg,bg}]) for specific combinations, or hexes ([…]) for every pairwise ratio. Reports AA/AAA verdicts.\",\n inputSchema: {\n type: \"object\",\n properties: {\n pairs: {\n type: \"array\",\n maxItems: 20,\n items: { type: \"object\", required: [\"fg\", \"bg\"], properties: { fg: { type: \"string\" }, bg: { type: \"string\" } } },\n },\n hexes: { type: \"array\", minItems: 2, maxItems: 8, items: { type: \"string\" } },\n },\n },\n handler: ctx.guard(async (input) => {\n if (Array.isArray(input.pairs) && input.pairs.length > 0) {\n if (input.pairs.length > 20) throw new BrandInputError(\"pairs must have at most 20 entries\");\n const lines = input.pairs.map((raw, i) => {\n const p = (raw ?? {}) as Record<string, unknown>;\n const fg = assertHex(p.fg, `pairs[${i}].fg`);\n const bg = assertHex(p.bg, `pairs[${i}].bg`);\n return `${fg} on ${bg}: ${verdict(contrastRatio(fg, bg))}`;\n });\n return { content: lines.join(\"\\n\") };\n }\n if (Array.isArray(input.hexes)) {\n if (input.hexes.length < 2 || input.hexes.length > 8) {\n throw new BrandInputError(\"hexes must have 2 to 8 entries\");\n }\n const hexes = input.hexes.map((h, i) => assertHex(h, `hexes[${i}]`));\n const lines: string[] = [];\n for (let i = 0; i < hexes.length; i++) {\n for (let j = i + 1; j < hexes.length; j++) {\n lines.push(`${hexes[i]} vs ${hexes[j]}: ${verdict(contrastRatio(hexes[i]!, hexes[j]!))}`);\n }\n }\n return { content: lines.join(\"\\n\") };\n }\n throw new BrandInputError(\"provide pairs ([{fg,bg}, …]) or hexes ([#rrggbb, …])\");\n }),\n };\n\n const proposePalette: ToolDef = {\n name: \"propose_palette\",\n description:\n \"Park a palette proposal for human review (does NOT change the brand). Pass explicit swatches, or a seedHex (and optional harmony) to derive a full palette. A WCAG contrast report is attached automatically.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"name\", \"rationale\"],\n properties: {\n name: { type: \"string\" },\n rationale: { type: \"string\", description: \"Why these colors — cite assets, harmony, contrast.\" },\n seedHex: { type: \"string\" },\n harmony: { type: \"string\", enum: Object.keys(HARMONY_COMPANIONS) },\n sourceAssetId: {\n type: \"string\",\n description: \"Optional exact asset id that grounded this palette.\",\n },\n swatches: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"role\", \"hex\"],\n properties: {\n role: { type: \"string\" },\n hex: { type: \"string\" },\n name: { type: \"string\" },\n rationale: { type: \"string\" },\n },\n },\n },\n },\n },\n handler: ctx.guard(async (input, toolCtx) => {\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const name = capString(input.name, \"name\", 120);\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const sourceAssetId = await proposalSourceAssetId(\n ctx,\n book,\n input.sourceAssetId,\n );\n const seedHex = input.seedHex === undefined ? undefined : assertHex(input.seedHex, \"seedHex\");\n let swatches: Swatch[];\n if (input.swatches !== undefined) {\n swatches = assertSwatches(input.swatches);\n } else {\n if (!seedHex) throw new BrandInputError(\"provide swatches, or a seedHex to derive a palette from\");\n swatches = derivePalette(seedHex);\n if (input.harmony !== undefined) swatches = applyHarmony(swatches, seedHex, input.harmony);\n }\n const report = contrastReport(swatches);\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind: \"palette\",\n payload: {\n name,\n swatches,\n ...(seedHex ? { seedHex } : {}),\n contrastReport: report,\n },\n rationale,\n ...(sourceAssetId ? { sourceAssetId } : {}),\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== \"palette\" ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n const reportText = Object.entries(report).map(([k, v]) => `${k} ${r2(v)}:1`).join(\", \");\n return {\n content:\n `Parked palette proposal ${proposal.id} (\"${name}\", ${swatches.length} swatches` +\n `${seedHex ? `, seeded from ${seedHex}` : \"\"}). Contrast: ${reportText}. ` +\n \"Awaiting a human decision in the brand approval surface.\",\n };\n }),\n };\n\n return [analyzeColor, evaluateContrast, proposePalette];\n}\n","// Design tools: how an agent reads a Claude Design without eating it.\n//\n// A bundle is megabytes of base64 and its template is ~150 KB of markup —\n// neither belongs in a context window. So the tools serve three different\n// resolutions of the same design, and the model picks:\n//\n// read_design the digest: tokens, fonts, props, heading outline.\n// Kilobytes. Enough to plan a build.\n// read_design_source a WINDOW of the real template, by offset or by\n// search term. For porting exact markup.\n// propose_palette_from_design\n// the design's own --ui-* declarations, read back as\n// brand swatches and parked as a proposal.\n//\n// The third is the one that changes anything, and it changes nothing on its\n// own: it parks a proposal a human resolves, exactly like propose_palette.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport { BRAND_NS, DESIGN_ASSET_KIND } from \"../constants\";\nimport { swatchesFromDesignTokens } from \"../design/decompile\";\nimport type { DesignDigest } from \"../design/types\";\nimport { BrandInputError, BrandNotFoundError } from \"../errors\";\nimport { contrastReport } from \"../palette-report\";\nimport type { BrandAsset } from \"../types\";\nimport { capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Largest template window one read_design_source call returns. */\nexport const MAX_SOURCE_WINDOW = 12_000;\n\n/** Render a digest as compact, readable text — cheaper and easier for a\n * model to act on than raw JSON, and it keeps the caps visible. */\nexport function describeDigest(asset: BrandAsset, digest: DesignDigest): string {\n const lines: string[] = [\n `Design ${asset.id}${digest.title ? ` — \"${digest.title}\"` : \"\"}${asset.title ? ` (uploaded as \"${asset.title}\")` : \"\"}`,\n `Template ${digest.templateBytes} bytes; ${digest.assetCount} embedded assets (${digest.assetBytes} bytes); ${digest.pageCount} nested pages.`,\n ];\n if (digest.assetGroups.length > 0)\n lines.push(\n `Assets: ${digest.assetGroups.map((g) => `${g.count}× ${g.mime} (${g.bytes} B)`).join(\", \")}`,\n );\n if (digest.externals.length > 0) lines.push(`Built against: ${digest.externals.join(\", \")}`);\n if (digest.fonts.length > 0) lines.push(`Typefaces: ${digest.fonts.join(\", \")}`);\n const tokenNames = Object.keys(digest.tokens.light);\n lines.push(\n tokenNames.length > 0\n ? `Declares ${tokenNames.length} --ui-* tokens (light) and ${Object.keys(digest.tokens.dark).length} (dark). ` +\n `Key values: ${[\"--ui-bg\", \"--ui-text\", \"--ui-accent\", \"--ui-accent-strong\", \"--ui-surface\"]\n .filter((n) => digest.tokens.light[n])\n .map((n) => `${n}=${digest.tokens.light[n]}`)\n .join(\", \")}`\n : \"Declares no --ui-* tokens; it was not authored on the @odla-ai/ui contract.\",\n );\n if (digest.colors.length > 0)\n lines.push(`Literal colors: ${digest.colors.map((c) => `${c.hex}×${c.count}`).join(\", \")}`);\n if (digest.props.length > 0)\n lines.push(\n \"Configurable props:\\n\" +\n digest.props\n .map(\n (p) =>\n ` ${p.name} (${p.editor}${p.options ? `: ${p.options.join(\"|\")}` : \"\"})` +\n `${p.default === undefined ? \"\" : ` default ${p.default}`}${p.section ? ` [${p.section}]` : \"\"}`,\n )\n .join(\"\\n\"),\n );\n if (digest.outline.length > 0)\n lines.push(\n \"Outline:\\n\" +\n digest.outline.map((h) => `${\" \".repeat(h.level - 1)}h${h.level} ${h.text}`).join(\"\\n\"),\n );\n if (digest.truncated.length > 0)\n lines.push(`NOTE: truncated to fit digest caps: ${digest.truncated.join(\", \")}.`);\n return lines.join(\"\\n\");\n}\n\n/** Locate the requested window of the template. */\nexport function sourceWindow(\n template: string,\n input: { find?: string; offset?: number; length?: number },\n): { text: string; start: number; end: number } {\n const length = Math.min(\n MAX_SOURCE_WINDOW,\n Math.max(1, typeof input.length === \"number\" ? input.length : MAX_SOURCE_WINDOW),\n );\n let start: number;\n if (input.find !== undefined && input.find !== \"\") {\n const at = template.indexOf(input.find);\n if (at < 0) throw new BrandNotFoundError(`\"${input.find}\" in the design source`);\n // Show a little of what precedes the match, so the opening tag of the\n // enclosing element is usually in frame.\n start = Math.max(0, at - 400);\n } else {\n start = Math.max(0, Math.min(template.length, Math.trunc(input.offset ?? 0)));\n }\n const end = Math.min(template.length, start + length);\n return { text: template.slice(start, end), start, end };\n}\n\n/**\n * The design tools, scoped to the context's book. All three refuse any asset\n * that is not a live `design` with a stored digest.\n */\nexport function designTools(ctx: BrandToolCtx): ToolDef[] {\n const loadDesign = async (assetId: string): Promise<BrandAsset> => {\n await ctx.authority(\"brand.read\");\n const res = await ctx.db.query({\n [BRAND_NS.asset]: { $: { where: { id: assetId, bookId: ctx.bookId, status: \"live\" } } },\n });\n const row = (res[BRAND_NS.asset] ?? [])[0] as BrandAsset | undefined;\n if (!row || row.kind !== DESIGN_ASSET_KIND || !row.design)\n throw new BrandNotFoundError(`design asset ${assetId}`);\n return row;\n };\n\n const readDesign: ToolDef = {\n name: \"read_design\",\n description:\n \"Read an uploaded Claude Design: its design tokens, typefaces, colors, configurable props, and heading outline. Start here before building anything from a design — it is the whole design at a size you can reason about.\",\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: {\n assetId: { type: \"string\", description: \"A design asset id from list_assets.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n return { content: describeDigest(asset, asset.design!) };\n }),\n };\n\n const readDesignSource: ToolDef = {\n name: \"read_design_source\",\n description:\n \"Read a window of a design's actual HTML source, to port exact markup or styles. Pass `find` to jump to the first occurrence of a string (a heading, a class name), or `offset` to page through. Returns at most 12000 characters.\",\n // The template is author-supplied content, not instructions.\n outputTaint: [\"tool_untrusted:read_design_source\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: {\n assetId: { type: \"string\" },\n find: { type: \"string\", description: \"Jump to the first occurrence of this string.\" },\n offset: { type: \"number\", description: \"Character offset to read from (ignored with find).\" },\n length: { type: \"number\", description: `Characters to return (max ${MAX_SOURCE_WINDOW}).` },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n const template = await ctx.readDesignTemplate(asset.id);\n const found = sourceWindow(template, {\n ...(typeof input.find === \"string\" ? { find: input.find } : {}),\n ...(typeof input.offset === \"number\" ? { offset: input.offset } : {}),\n ...(typeof input.length === \"number\" ? { length: input.length } : {}),\n });\n return {\n content:\n `Design ${asset.id} source, characters ${found.start}–${found.end} of ${template.length}:\\n` +\n found.text,\n };\n }),\n };\n\n const proposeFromDesign: ToolDef = {\n name: \"propose_palette_from_design\",\n description:\n \"Read a design's own --ui-* token declarations back into a brand palette and park it as a proposal for human review. Use when a design already carries the brand's colors and they should become the brand book's palette. Does NOT change the brand.\",\n acceptsTaint: [\"tool_untrusted:read_design_source\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\", \"rationale\"],\n properties: {\n assetId: { type: \"string\" },\n name: { type: \"string\", description: \"Palette name; defaults to the design's title.\" },\n rationale: { type: \"string\", description: \"Why this design's palette should become the brand's.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n const digest = asset.design!;\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const name = capString(\n input.name ?? digest.title ?? asset.title ?? \"Design palette\",\n \"name\",\n 120,\n );\n const { swatches, skipped, missing } = swatchesFromDesignTokens(digest.tokens);\n if (swatches.length === 0)\n throw new BrandInputError(\n `design ${asset.id} declares no --ui-* tokens that resolve to opaque colors; ` +\n \"propose a palette explicitly instead.\",\n );\n const report = contrastReport(swatches);\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind: \"palette\",\n payload: { name, swatches, contrastReport: report, source: \"design\", designAssetId: asset.id },\n rationale,\n sourceAssetId: asset.id,\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== \"palette\" ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n const notes = [\n skipped.length > 0\n ? `Not imported (not literal opaque colors): ${skipped.map((s) => `${s.token} — ${s.reason}`).join(\"; \")}.`\n : \"\",\n missing.length > 0 ? `Roles the design declares no token for: ${missing.join(\", \")}.` : \"\",\n ].filter((n) => n !== \"\");\n return {\n content:\n `Parked palette proposal ${proposal.id} (\"${name}\") from design ${asset.id}: ` +\n `${swatches.length} swatches read back from its --ui-* declarations. ` +\n `Contrast: ${Object.entries(report).map(([k, v]) => `${k} ${v.toFixed(2)}:1`).join(\", \")}. ` +\n `${notes.join(\" \")} Awaiting a human decision in the brand approval surface.`.trim(),\n };\n }),\n };\n\n return [readDesign, readDesignSource, proposeFromDesign];\n}\n","// Read-only brand tools: a compact structured-text snapshot of the book\n// (read_brand_book) and the live asset list (list_assets). Deterministic, no\n// AI calls, no writes — the agent's orientation step before it proposes\n// anything. @odla-ai/ai is imported for types only.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport { ASSET_KINDS, BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandAsset, BrandBook, BrandPalette, BrandProposal, BrandSection } from \"../types\";\nimport type { BrandToolCtx } from \"./skill\";\nimport type { BrandPrincipalProjection } from \"./skill\";\n\nconst iso = (ms: number): string => new Date(ms).toISOString();\n\nconst shortId = (id: string): string =>\n id.length <= 12 ? id : `${id.slice(0, 6)}…${id.slice(-4)}`;\nconst principalLabel = (\n id: string,\n directory: Map<string, BrandPrincipalProjection>,\n): string => {\n const value = directory.get(id);\n return value\n ? `${value.displayName} [${value.kind} · ${shortId(id)}]`\n : `Unknown principal [${shortId(id)}]`;\n};\n\nfunction bookLines(\n book: BrandBook,\n directory: Map<string, BrandPrincipalProjection>,\n): string[] {\n const lines = [\n `brand book \"${book.name}\" (${book.slug}) — ${book.status}`,\n `members: ${book.memberIds.map((id) => principalLabel(id, directory)).join(\", \")}`,\n `active palette: ${book.activePaletteId ?? \"(none accepted yet)\"}`,\n book.tokens\n ? `tokens: compiled ${iso(book.tokens.compiledAt)} with ${book.tokens.warnings.length} warning(s)`\n : \"tokens: (not compiled)\",\n ];\n if (book.summary) lines.push(`summary: ${book.summary}`);\n return lines;\n}\n\nfunction childLines(\n sections: BrandSection[],\n palettes: BrandPalette[],\n proposals: BrandProposal[],\n directory: Map<string, BrandPrincipalProjection>,\n): string[] {\n return [\n \"sections:\",\n ...(sections.length\n ? sections.map((s) =>\n `- ${s.kind}: ${s.status}, updated ${iso(s.updatedAt)} by ` +\n principalLabel(s.updatedBy, directory))\n : [\"- (none)\"]),\n \"palettes:\",\n ...(palettes.length\n ? palettes.map((p) => `- ${p.id} \"${p.name}\" (${p.status}, ${p.source}, ${p.swatches.length} swatches)`)\n : [\"- (none)\"]),\n \"open proposals:\",\n ...(proposals.length\n ? proposals.map((p) =>\n `- ${p.id} (${p.kind}) by ${principalLabel(p.createdBy, directory)}: ${p.rationale}`)\n : [\"- (none)\"]),\n ];\n}\n\n/**\n * The two read-only tools, scoped to the context's book:\n * `read_brand_book` (book + sections + palettes + open proposals as compact\n * text) and `list_assets` (live, non-tombstoned asset rows, optionally\n * filtered by kind).\n */\nexport function readTools(ctx: BrandToolCtx): ToolDef[] {\n const readBrandBook: ToolDef = {\n name: \"read_brand_book\",\n description:\n \"Read the current brand book: status, members, active palette, compiled tokens, sections, palettes, and open proposals.\",\n inputSchema: { type: \"object\", properties: {} },\n handler: ctx.guard(async () => {\n const authorizedBook = await ctx.loadBook();\n const res = await ctx.db.query({\n [BRAND_NS.section]: {\n $: { where: { bookId: ctx.bookId }, order: { updatedAt: \"asc\" } },\n book: {},\n },\n [BRAND_NS.palette]: {\n $: { where: { bookId: ctx.bookId }, order: { createdAt: \"asc\" } },\n book: {},\n },\n [BRAND_NS.proposal]: {\n $: {\n where: { bookId: ctx.bookId, status: \"open\" },\n order: { createdAt: \"asc\" },\n },\n book: {},\n },\n });\n const linked = <T extends { bookId: string; book?: Array<{ id: string }> }>(\n rows: unknown[],\n ): T[] => (rows as T[]).filter((row) =>\n row.bookId === authorizedBook.id &&\n Array.isArray(row.book) &&\n row.book.length === 1 &&\n row.book[0]?.id === authorizedBook.id);\n const sections = linked<BrandSection & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.section] ?? [],\n );\n const palettes = linked<BrandPalette & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.palette] ?? [],\n );\n const proposals = linked<BrandProposal & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.proposal] ?? [],\n );\n const ids = [\n ...authorizedBook.memberIds,\n ...sections.map((section) => section.updatedBy),\n ...proposals.map((proposal) => proposal.createdBy),\n ];\n const directory = new Map(\n (await ctx.resolvePrincipals(ids)).map((principal) => [principal.id, principal]),\n );\n return {\n content: [\n ...bookLines(authorizedBook, directory),\n ...childLines(sections, palettes, proposals, directory),\n ].join(\"\\n\"),\n };\n }),\n };\n\n const listAssets: ToolDef = {\n name: \"list_assets\",\n description:\n \"List the book's uploaded assets (id, kind, content type, size, title, analysis state). Tombstoned assets are excluded.\",\n inputSchema: {\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...ASSET_KINDS], description: \"Only assets of this kind.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n await ctx.loadBook();\n const where: Record<string, unknown> = { bookId: ctx.bookId, status: \"live\" };\n if (input.kind !== undefined) {\n if (typeof input.kind !== \"string\" || !(ASSET_KINDS as readonly string[]).includes(input.kind)) {\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n }\n where.kind = input.kind;\n }\n const res = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where, order: { createdAt: \"asc\" } },\n book: {},\n },\n });\n const rows = ((res[BRAND_NS.asset] ?? []) as Array<\n BrandAsset & { book?: Array<{ id: string }> }\n >).filter((asset) =>\n asset.bookId === ctx.bookId &&\n Array.isArray(asset.book) &&\n asset.book.length === 1 &&\n asset.book[0]?.id === ctx.bookId);\n if (rows.length === 0) {\n return { content: input.kind ? `(no ${String(input.kind)} assets uploaded yet)` : \"(no assets uploaded yet)\" };\n }\n const lines = rows.map(\n (a) =>\n `${a.id} — ${a.kind}, ${a.contentType}, ${a.size} bytes` +\n `${a.title ? `, \"${a.title}\"` : \"\"}${a.analysis ? \" (analyzed)\" : \" (not analyzed)\"}`,\n );\n return { content: lines.join(\"\\n\") };\n }),\n };\n\n return [readBrandBook, listAssets];\n}\n","// The @odla-ai/ai Skill assembly for a brand book: one shared tool context\n// (injected db + identity + defaults), the workflow instructions, and the\n// tools from the five tool modules. @odla-ai/ai is an optional peer imported\n// for TYPES ONLY (chat's pattern) — the package works without it installed.\n//\n// Error contract with the agent loop: runAgent converts a handler throw into\n// a SANITIZED error tool_result (`Tool \"x\" failed.`) because arbitrary\n// handler messages may carry credentials. Brand's own validation errors are\n// crafted, secret-free, and actionable, so `guard` catches BrandInputError /\n// BrandNotFoundError and returns the message as an error output the model can\n// act on; anything unexpected still propagates into the loop's sanitizer.\nimport type { Skill, ToolHandler } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"../constants\";\nimport { resolveDeps, type BrandFetchedBytes } from \"../deps\";\nimport { BrandForbiddenError, BrandInputError, BrandNotFoundError } from \"../errors\";\nimport type {\n AssetAnalysis,\n BrandAsset,\n BrandBook,\n BrandDb,\n BrandProposal,\n} from \"../types\";\nimport type { ProposalKind } from \"../constants\";\nimport { parseDesignBundle } from \"../design/bundle\";\nimport { assetTools } from \"./asset-tools\";\nimport { designTools } from \"./design-tools\";\nimport { bookTools } from \"./book-tools\";\nimport { paletteTools } from \"./palette-tools\";\nimport { readTools } from \"./read-tools\";\nimport type {\n BrandCapability,\n BrandCapabilityAuthority,\n BrandPrincipalProjection,\n} from \"./agent-types\";\n\nexport type {\n BrandCapability,\n BrandCapabilityAuthority,\n BrandPrincipalProjection,\n} from \"./agent-types\";\n\n/** The bot identity the skill writes as (`selfId` = the agent id carried in\n * the book's `memberIds` roster and every audience snapshot). */\nexport interface BrandSkillSelf {\n selfId: string;\n kind: \"bot\";\n displayName?: string;\n}\n\n/** Server-enforced semantic bridge. Raw agent credentials must be denied all\n * Brand namespace writes and raw file operations. */\nexport interface BrandAgentBridge {\n createProposal(input: {\n jobId: string;\n bookId: string;\n mutationId: string;\n kind: ProposalKind;\n payload: Record<string, unknown>;\n rationale: string;\n sourceAssetId?: string;\n }): Promise<BrandProposal>;\n recordAssetAnalysis(input: {\n jobId: string;\n mutationId: string;\n bookId: string;\n assetId: string;\n analysis: AssetAnalysis;\n expectedAnalysisRevision: number;\n }): Promise<BrandAsset>;\n readAssetContent(input: {\n jobId: string;\n bookId: string;\n assetId: string;\n }): Promise<BrandFetchedBytes>;\n}\n\n/** Options for {@link brandSkill}. */\nexport interface BrandSkillOpts {\n /** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */\n db: BrandDb;\n /** The one brand book this skill instance is scoped to. */\n bookId: string;\n /** The bot identity acting through these tools. */\n self: BrandSkillSelf;\n /** Host attestation for the rules-scoped credential behind `db`. */\n agentDbBinding: { principalId: string; credentialRef: string };\n /** Active verified agent job; the bridge derives message/turn provenance. */\n agentJobId: string;\n agentBridge: BrandAgentBridge;\n /** Host verification against the live principal grant. Missing/denied hooks\n * fail closed; roster membership is visibility, not authority. */\n authorizeCapability: (input: {\n agentId: string;\n bookId: string;\n capability: BrandCapability;\n }) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;\n /** Bounded host directory projection for conversational display only. */\n resolvePrincipals: (input: {\n requesterAgentId: string;\n bookId: string;\n principalIds: string[];\n }) => Promise<BrandPrincipalProjection[]>;\n /** False when the model cannot take image/document blocks inside a\n * tool_result — view_asset then steers to the pre-turn attachment path. */\n visionInToolResults?: boolean;\n /** Clock override (tests). */\n now?: () => number;\n /** Id factory override (tests). */\n newId?: () => string;\n}\n\n/** The resolved context every brand tool module builds its tools from. */\nexport interface BrandToolCtx {\n db: BrandDb;\n bookId: string;\n self: BrandSkillSelf;\n /** Whether image/document blocks may be returned inside tool results. */\n visionInToolResults: boolean;\n now: () => number;\n newId: () => string;\n agentJobId: string;\n createProposal(input: {\n mutationId: string;\n kind: ProposalKind;\n payload: Record<string, unknown>;\n rationale: string;\n sourceAssetId?: string;\n }): Promise<BrandProposal>;\n recordAssetAnalysis(input: {\n mutationId: string;\n assetId: string;\n analysis: AssetAnalysis;\n expectedAnalysisRevision: number;\n }): Promise<BrandAsset>;\n readAssetContent(assetId: string): Promise<BrandFetchedBytes>;\n /** The decoded template document of a `design` asset. Memoized per skill\n * instance: a bundle is megabytes, and `read_design_source` is designed to\n * be called repeatedly while an agent ports markup. */\n readDesignTemplate(assetId: string): Promise<string>;\n resolvePrincipals(ids: string[]): Promise<BrandPrincipalProjection[]>;\n authority(capability: BrandCapability): Promise<BrandCapabilityAuthority>;\n /** Load the scoped book row; throws BrandNotFoundError when missing. */\n loadBook(): Promise<BrandBook>;\n /** Wrap a handler so Brand validation errors come back as actionable\n * error text instead of the loop's sanitized generic failure. */\n guard(handler: ToolHandler): ToolHandler;\n}\n\n/** Workflow guidance appended to the persona's system prompt as the skill's\n * instruction section. */\nexport const BRAND_INSTRUCTIONS =\n \"You help build and maintain ONE brand book. Workflow, in order:\\n\" +\n \"1. Understand the brand first: read_brand_book and list_assets before proposing anything.\\n\" +\n \"2. Look at the real material: view_asset on logos and inspiration, then record what you \" +\n \"saw with record_asset_analysis (description, dominant colors as hex, tags).\\n\" +\n \"3. Explore with the math tools: analyze_color and evaluate_contrast. Never invent a hex \" +\n \"without a rationale — ground every color in an asset's dominant color, a harmony \" +\n \"companion, or a contrast fix, and say which.\\n\" +\n \"4. When a Claude Design has been uploaded, read_design is the fastest way to learn the \" +\n \"brand: it reports the design tokens, typefaces, props, and page outline. read_design_source \" +\n \"reads exact markup when you need it. If the design already carries the brand colors, \" +\n \"propose_palette_from_design reads its --ui-* declarations back into a palette proposal.\\n\" +\n \"5. propose_palette parks a proposal for review. It does NOT change the brand.\\n\" +\n \"6. You cannot approve or resolve a proposal. Direct the human to the brand approval \" +\n \"surface, which records a guarded receipt for their decision.\\n\" +\n \"7. update_section parks a proposal; it never overwrites an approved facet. Bind \" +\n \"sourceAssetId when a real Brand asset grounds typography, voice, logo, or imagery. Human \" +\n \"acceptance applies the exact reviewed change and automatically recompiles dependent tokens.\\n\" +\n \"8. Re-read the book after a decision and explain any compiler warnings conversationally.\";\n\n/**\n * Build the brand Skill: read/asset/design/palette/book tools scoped to one book,\n * acting as one bot identity, plus {@link BRAND_INSTRUCTIONS}. Attach it to\n * a Persona (or use `createBrandPersona`).\n */\nexport function brandSkill(opts: BrandSkillOpts): Skill {\n if (\n opts.agentDbBinding.principalId !== opts.self.selfId ||\n !opts.agentDbBinding.credentialRef\n ) throw new BrandForbiddenError(\"brand db is not bound to the acting agent\");\n const deps = resolveDeps({ db: opts.db, now: opts.now, newId: opts.newId });\n const designTemplates = new Map<string, Promise<string>>();\n const authority = (capability: BrandCapability): Promise<BrandCapabilityAuthority> =>\n Promise.resolve(opts.authorizeCapability({\n agentId: opts.self.selfId,\n bookId: opts.bookId,\n capability,\n }) ?? null).then((result) => {\n if (!result || result.capability !== capability || !result.authorityRef)\n throw new BrandForbiddenError(`agent lacks ${capability} for brand book ${opts.bookId}`);\n return result;\n });\n const ctx: BrandToolCtx = {\n db: deps.db,\n bookId: opts.bookId,\n self: opts.self,\n visionInToolResults: opts.visionInToolResults !== false,\n now: deps.now,\n newId: deps.newId,\n agentJobId: opts.agentJobId,\n createProposal: (input) => opts.agentBridge.createProposal({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n ...input,\n }),\n recordAssetAnalysis: (input) => opts.agentBridge.recordAssetAnalysis({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n ...input,\n }),\n readAssetContent: (assetId) => opts.agentBridge.readAssetContent({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n assetId,\n }),\n readDesignTemplate: (assetId) => {\n const cached = designTemplates.get(assetId);\n if (cached) return cached;\n const pending = opts.agentBridge\n .readAssetContent({ jobId: opts.agentJobId, bookId: opts.bookId, assetId })\n .then((fetched) =>\n parseDesignBundle(new TextDecoder().decode(fetched.bytes)).template,\n );\n // A failed read must not be memoized as a permanent failure.\n pending.catch(() => designTemplates.delete(assetId));\n designTemplates.set(assetId, pending);\n return pending;\n },\n resolvePrincipals: (principalIds) => {\n const ids = [...new Set(principalIds)].slice(0, 100);\n return opts.resolvePrincipals({\n requesterAgentId: opts.self.selfId,\n bookId: opts.bookId,\n principalIds: ids,\n });\n },\n authority,\n loadBook: async () => {\n await authority(\"brand.read\");\n const res = await deps.db.query({ [BRAND_NS.book]: { $: { where: { id: opts.bookId } } } });\n const row = (res[BRAND_NS.book] ?? [])[0] as BrandBook | undefined;\n if (!row || !row.memberIds.includes(opts.self.selfId))\n throw new BrandNotFoundError(`brand book ${opts.bookId}`);\n return row;\n },\n guard: (handler) => async (input, toolCtx) => {\n try {\n return await handler(input, toolCtx);\n } catch (error) {\n if (\n error instanceof BrandInputError ||\n error instanceof BrandNotFoundError ||\n error instanceof BrandForbiddenError\n ) {\n return { content: error.message, isError: true };\n }\n throw error;\n }\n },\n };\n return {\n name: \"brand\",\n instructions: BRAND_INSTRUCTIONS,\n tools: [\n ...readTools(ctx),\n ...assetTools(ctx),\n ...designTools(ctx),\n ...paletteTools(ctx),\n ...bookTools(ctx),\n ],\n };\n}\n","// The brand-director Persona: the brand skill pre-attached, a default system\n// prompt encoding the explore → propose → human approves → compile loop, and\n// the capability probe hosts use to decide whether asset bytes can ride\n// inside tool results or must be attached pre-turn. @odla-ai/ai types only.\nimport type { Persona, Skill } from \"@odla-ai/ai\";\nimport { brandSkill, type BrandSkillOpts } from \"./skill\";\n\n/** The default brand-director system prompt (override via `system`). */\nexport const DEFAULT_BRAND_SYSTEM =\n \"You are a meticulous brand director for one brand book. You study the real material \" +\n \"before forming opinions, you justify every color with math (harmony, ΔEOK, WCAG \" +\n \"contrast) or provenance (an asset's dominant colors), and you present options rather \" +\n \"than dictating. Proposals and drafts are yours to make; decisions are the human's — \" +\n \"you have no proposal-resolution or section-approval tool. When \" +\n \"tokens compile with warnings, explain each adjustment in plain language.\";\n\n/** Options for {@link createBrandPersona}. */\nexport interface CreateBrandPersonaOpts {\n /** Canonical model id the persona runs on. */\n model: string;\n /** System prompt override (default {@link DEFAULT_BRAND_SYSTEM}). */\n system?: string;\n /** Provider web-search server tool (default true — brand research). */\n webSearch?: boolean;\n /** Max model turns per run (default 10 — the workflow is multi-step). */\n maxSteps?: number;\n /** Extra skills appended after the brand skill (e.g. a chat skill). */\n skills?: Skill[];\n /** Options for the attached {@link brandSkill}. */\n brand: BrandSkillOpts;\n}\n\n/** Build the brand-director Persona: {@link brandSkill} first, extra skills\n * after, defaults per the option JSDoc above. */\nexport function createBrandPersona(opts: CreateBrandPersonaOpts): Persona {\n return {\n name: \"brand-director\",\n model: opts.model,\n system: opts.system ?? DEFAULT_BRAND_SYSTEM,\n webSearch: opts.webSearch ?? true,\n maxSteps: opts.maxSteps ?? 10,\n skills: [brandSkill(opts.brand), ...(opts.skills ?? [])],\n };\n}\n\n/** The capability flags {@link supportsBrandVision} inspects. */\nexport interface BrandVisionCapabilities {\n toolResultBlocks?: boolean;\n imageIn?: boolean;\n documentIn?: boolean;\n}\n\n/** The (structural) slice of an @odla-ai/ai ModelSpec the probe reads. */\nexport interface BrandVisionSpec {\n capabilities?: BrandVisionCapabilities;\n}\n\n/**\n * Whether a model can view assets THROUGH view_asset — i.e. take image and\n * document blocks inside tool results. Pure capabilities-metadata check\n * (`toolResultBlocks && imageIn && documentIn`), never provider names; when\n * false, hosts attach asset bytes as pre-turn input blocks instead and pass\n * `visionInToolResults: false` to the skill.\n */\nexport function supportsBrandVision(spec: BrandVisionSpec | null | undefined): boolean {\n const caps = spec?.capabilities;\n return !!(caps?.toolResultBlocks && caps.imageIn && caps.documentIn);\n}\n","import { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport { BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport type { BrandRouteCtx } from \"./http\";\n\nexport async function linkedAsset(\n ctx: BrandRouteCtx,\n book: BrandBook,\n assetId: string,\n allowDeleting = false,\n): Promise<BrandAsset> {\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: assetId, bookId: book.id } },\n book: {},\n },\n });\n const row = rowAsWritten(BRAND_NS.asset, (result[BRAND_NS.asset] ?? [])[0]) as\n | (BrandAsset & { book?: BrandBook[] })\n | undefined;\n const links = row?.book;\n if (\n !row ||\n row.bookId !== book.id ||\n !Array.isArray(links) ||\n links.length !== 1 ||\n links[0]?.id !== book.id ||\n (row.status !== \"live\" && !(allowDeleting && row.status === \"deleting\"))\n ) throw new BrandNotFoundError(`asset ${assetId}`);\n return row;\n}\n","// HTTP plumbing for the brand route factory (crm's http.ts contract): option\n// shapes, JSON helpers, the error → status mapping (BrandInputError → 400,\n// BrandNotFoundError → 404, anything else an OPAQUE 500), body-field\n// extractors, and the shared book loaders.\n//\n// Access parity note: routes run on the host's ADMIN db credential, which\n// bypasses odla-db rules — so the loaders re-enforce what the CEL rules would:\n// a book you are not in `memberIds` of answers 404, the same as one that does\n// not exist (a non-member cannot probe for existence).\nimport { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandGoneError,\n BrandInputError,\n BrandNotFoundError,\n BrandReviewStateChangedError,\n} from \"../errors\";\nimport type {\n BrandActor,\n BrandBook,\n BrandDb,\n BrandHumanAuthorityConsumption,\n BrandSourceAssetSnapshot,\n} from \"../types\";\n\nexport type BrandRouteCapability = \"brand.edit\" | \"app.manage\";\nexport type BrandRouteEffect = \"internal\" | \"destructive\";\nexport interface BrandRouteAuthority {\n authorityRef: string;\n actorPrincipalId: string;\n capability: BrandRouteCapability;\n effect: BrandRouteEffect;\n}\n\n/** Everything {@link import(\"./index\").createBrandRoutes} needs from the host worker. */\nexport interface BrandRouteOpts {\n /** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */\n db: BrandDb;\n /** Registry app that owns the book rows and central authority records. */\n appId: string;\n /** Host-owned auth: resolve the request to an actor or null (→ 401). The\n * tokens routes skip this only when `publicTokens` is true. */\n authorize: (req: Request) => Promise<BrandActor | null> | BrandActor | null;\n /** Optional host-owned authority seam for read-only Discussion reference\n * lookup. Verify exact Brand product, brand.read capability, canonical\n * audience, principal, current app lifetime/environment, and agent grant\n * provenance here; when omitted, the ordinary request authorizer is used. */\n authorizeDiscussionReferences?: (\n req: Request,\n ) => Promise<BrandActor | null> | BrandActor | null;\n /** Live host verification for worker-mediated effects. The callback must\n * verify the direct human credential, current app owner/co-owner status,\n * exact capability/effect/resource, and return null on any uncertainty. */\n authorizeCapability: (input: {\n req: Request;\n actor: BrandActor;\n appId: string;\n bookId?: string;\n capability: BrandRouteCapability;\n effect: BrandRouteEffect;\n }) => Promise<BrandRouteAuthority | null> | BrandRouteAuthority | null;\n /** Consume or idempotently replay one registry `human_exact` authority use,\n * then reload and authenticate its immutable central receipt. Missing,\n * synthetic, cached, or unverifiable authority must return null. */\n consumeHumanExact: (input: {\n req: Request;\n actor: BrandActor;\n appId: string;\n capability: \"brand.proposal.resolve\";\n projectCapability: \"brand.approve\";\n effect: \"internal\";\n resource: { bookId: string; proposalId: string };\n actionDigest: string;\n consumptionIdempotencyKey: string;\n }) => Promise<BrandHumanAuthorityConsumption | null> | BrandHumanAuthorityConsumption | null;\n /** Re-read the private object and authenticate the exact snapshot captured\n * by the agent bridge. This must verify path, ETag, size, and SHA-256 bytes;\n * returning false prevents authority consumption and the local effect. */\n verifySourceAssetSnapshot: (input: {\n req: Request;\n appId: string;\n bookId: string;\n assetId: string;\n path: string;\n snapshot: BrandSourceAssetSnapshot;\n }) => Promise<boolean> | boolean;\n /** Mount point. Default \"/api/brand\". */\n basePath?: string;\n /** Native UI mount used by returned Discussion deep links. Default \"/\". */\n discussionBasePath?: string;\n /**\n * Product-owned fetch used only for a short-lived URL minted from a linked\n * private Brand asset. Callers never provide this URL or receive it back.\n */\n fetchPrivateAsset?: typeof fetch;\n /** `frame-ancestors` for the design preview response — who may embed a\n * design. Default `[\"'self'\"]`. Widen only to origins you control: the\n * preview renders untrusted design HTML. */\n previewFrameAncestors?: string[];\n /** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */\n maxUploadBytes?: number;\n /** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —\n * compiled tokens only; every other route always authorizes. Default false. */\n publicTokens?: boolean;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n /** Injectable id factory (tests). Default `crypto.randomUUID`. */\n newId?: () => string;\n}\n\n/** Per-request context handed to the authorized route handlers. */\nexport interface BrandRouteCtx {\n db: BrandDb;\n appId: string;\n actor: BrandActor;\n authorizeCapability: BrandRouteOpts[\"authorizeCapability\"];\n consumeHumanExact: BrandRouteOpts[\"consumeHumanExact\"];\n verifySourceAssetSnapshot: BrandRouteOpts[\"verifySourceAssetSnapshot\"];\n now: () => number;\n newId: () => string;\n maxUploadBytes: number;\n discussionBasePath: string;\n fetchPrivateAsset: typeof fetch;\n previewFrameAncestors: string[];\n}\n\n/** Revalidate one direct-human route effect immediately before its write. */\nexport async function requireRouteAuthority(\n ctx: BrandRouteCtx,\n req: Request,\n capability: BrandRouteCapability,\n effect: BrandRouteEffect,\n bookId?: string,\n): Promise<BrandRouteAuthority> {\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"this brand effect requires a directly authenticated human\");\n const result = await ctx.authorizeCapability({\n req,\n actor: ctx.actor,\n appId: ctx.appId,\n ...(bookId ? { bookId } : {}),\n capability,\n effect,\n });\n if (\n !result ||\n result.actorPrincipalId !== ctx.actor.id ||\n result.capability !== capability ||\n result.effect !== effect ||\n typeof result.authorityRef !== \"string\" ||\n result.authorityRef.length < 1 ||\n result.authorityRef.length > 200\n ) throw new BrandForbiddenError(`human lacks ${capability} ${effect} authority`);\n return result;\n}\n\n/** JSON response helper (`content-type: application/json`). */\nexport const json = (body: unknown, status = 200, headers: Record<string, string> = {}): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json\", ...headers },\n });\n\n/** Map a thrown error to its response: 400 input, 403 principal kind, 404\n * missing/membership parity, 409 stale review, otherwise opaque 500. */\nexport const errorResponse = (error: unknown): Response => {\n if (error instanceof BrandInputError)\n return json({ error: error.message, ...(error.fields ? { fields: error.fields } : {}) }, 400);\n if (error instanceof BrandForbiddenError) return json({ error: error.message }, 403);\n if (error instanceof BrandNotFoundError) return json({ error: error.message }, 404);\n if (error instanceof BrandGoneError) return json({ error: error.message }, 410);\n if (error instanceof BrandReviewStateChangedError)\n return json({ error: error.message, code: error.code }, 409);\n if (error instanceof BrandConflictError) return json({ error: error.message }, 409);\n return json({ error: \"internal error\" }, 500);\n};\n\n/** The uniform 405 for a known path hit with the wrong method. */\nexport const methodNotAllowed = (): Response => json({ error: \"method not allowed\" }, 405);\n\n/** Parse a JSON object body; {@link BrandInputError} (→ 400) on anything else. */\nexport async function readJson(req: Request): Promise<Record<string, unknown>> {\n let body: unknown;\n try {\n body = await req.json();\n } catch {\n throw new BrandInputError(\"invalid JSON body\");\n }\n if (typeof body !== \"object\" || body === null || Array.isArray(body))\n throw new BrandInputError(\"body must be a JSON object\");\n return body as Record<string, unknown>;\n}\n\n/** Required non-empty string body field. */\nexport function str(body: Record<string, unknown>, key: string): string {\n const value = body[key];\n if (typeof value !== \"string\" || value === \"\")\n throw new BrandInputError(`\"${key}\" must be a non-empty string`);\n return value;\n}\n\n/** Optional string body field (absent/null → undefined). */\nexport function optStr(body: Record<string, unknown>, key: string): string | undefined {\n const value = body[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") throw new BrandInputError(`\"${key}\" must be a string`);\n return value;\n}\n\n/** Optional string-array body field (absent/null → undefined). */\nexport function optStrArray(body: Record<string, unknown>, key: string): string[] | undefined {\n const value = body[key];\n if (value === undefined || value === null) return undefined;\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\"))\n throw new BrandInputError(`\"${key}\" must be an array of strings`);\n return value as string[];\n}\n\n/** Whether `actorId` is on the book's auth roster. */\nexport function isMember(book: BrandBook, actorId: string): boolean {\n return Array.isArray(book.memberIds) && book.memberIds.includes(actorId);\n}\n\n/** Load a book by id; {@link BrandNotFoundError} (→ 404) when missing. */\nexport async function loadBook(db: BrandDb, bookId: string): Promise<BrandBook> {\n const res = await db.query({ [BRAND_NS.book]: { $: { where: { id: bookId } } } });\n const row = (res[BRAND_NS.book] ?? [])[0] as BrandBook | undefined;\n if (!row) throw new BrandNotFoundError(`brand book ${bookId}`);\n // BrandBook.createdAt is declared `number` and that is the published\n // contract; the store's ISO read shape is an implementation detail that must\n // not reach a consumer.\n return rowAsWritten(BRAND_NS.book, row);\n}\n\n/** {@link loadBook}, plus the rules-parity membership gate: a non-member gets\n * the same 404 a missing book gets (see the header note). */\nexport async function loadMemberBook(db: BrandDb, bookId: string, actorId: string): Promise<BrandBook> {\n const book = await loadBook(db, bookId);\n if (!isMember(book, actorId)) throw new BrandNotFoundError(`brand book ${bookId}`);\n return book;\n}\n","import { ASSET_KINDS, BRAND_NS, DESIGN_ASSET_KIND, type AssetKind } from \"../constants\";\nimport { digestDesignHtml } from \"../design/digest\";\nimport { BrandConflictError, BrandInputError } from \"../errors\";\nimport { createAssetOps } from \"../ops/assets\";\nimport { assertAssetContentType, capString, safeFileName } from \"../validate\";\nimport { linkedAsset } from \"./asset-query\";\nimport {\n json,\n loadMemberBook,\n requireRouteAuthority,\n type BrandRouteCtx,\n} from \"./http\";\n\nasync function readForm(req: Request): Promise<FormData> {\n try {\n return await req.formData();\n } catch {\n throw new BrandInputError(\n 'expected multipart/form-data with a \"file\" field',\n );\n }\n}\n\nasync function contentDigest(file: File): Promise<string> {\n const hash = await crypto.subtle.digest(\"SHA-256\", await file.arrayBuffer());\n return `sha256:${[...new Uint8Array(hash)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n\nexport async function uploadAsset(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const form = await readForm(req);\n const file = form.get(\"file\");\n if (!(file instanceof File))\n throw new BrandInputError('\"file\" must be an uploaded file field');\n // Kind is resolved BEFORE the content-type check: the allowlist is\n // per-kind (design accepts text/html and nothing else; every other kind\n // accepts images/PDF and never HTML).\n const kindRaw = form.get(\"kind\");\n const kind = typeof kindRaw === \"string\" && kindRaw ? kindRaw : \"other\";\n if (!(ASSET_KINDS as readonly string[]).includes(kind))\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n let contentType: string;\n try {\n contentType = assertAssetContentType(file.type, kind);\n } catch (error) {\n if (error instanceof BrandInputError)\n return json({ error: error.message }, 415);\n throw error;\n }\n if (file.size > ctx.maxUploadBytes)\n return json({ error: `file exceeds ${ctx.maxUploadBytes} bytes` }, 413);\n // Parse before touching storage, so an unreadable bundle is a clean 400\n // and never strands an object (the ordering invariant this file keeps for\n // every other check too).\n const design =\n kind === DESIGN_ASSET_KIND ? digestDesignHtml(await file.text()) : undefined;\n const titleRaw = form.get(\"title\");\n const title = typeof titleRaw === \"string\" && titleRaw\n ? capString(titleRaw, \"title\", 160)\n : undefined;\n const fileName = safeFileName(file.name);\n const id = ctx.newId();\n const path = `brand/${book.id}/assets/${id}/${fileName}`;\n const authority = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"internal\", book.id,\n );\n const record = await ctx.db.storage.upload(\n path,\n file,\n contentType,\n { private: true },\n );\n if (record.path !== path) {\n await ctx.db.storage.delete(record.path);\n throw new BrandConflictError(\n \"private storage returned an unexpected asset path\",\n );\n }\n try {\n const current = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"internal\", book.id,\n );\n if (current.authorityRef !== authority.authorityRef)\n throw new BrandConflictError(\"brand edit authority changed during upload\");\n await ctx.db.transact(createAssetOps({\n id,\n bookId: book.id,\n kind: kind as AssetKind,\n path: record.path,\n storageObjectId: record.id,\n contentDigest: await contentDigest(file),\n contentType,\n size: record.size,\n uploadedBy: ctx.actor.id,\n uploadedAuthorityRef: authority.authorityRef,\n audience: book.memberIds,\n title,\n ...(design ? { design } : {}),\n now: ctx.now(),\n }), {\n mutationId: `brand:asset-upload:v1:${id}`,\n guards: [\n { ns: BRAND_NS.asset, id, exists: false },\n {\n ns: BRAND_NS.book,\n id: book.id,\n exists: true,\n equals: {\n version: book.version,\n activationRevision: book.activationRevision,\n memberIds: book.memberIds,\n },\n },\n ],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n } catch (error) {\n await ctx.db.storage.delete(record.path);\n throw error;\n }\n return json(await linkedAsset(ctx, book, id), 201);\n}\n","// Private Brand asset upload, listing, short-lived download signing, and\n// deletion saga. Rows are linked to books and privileged reads validate both\n// the scalar bookId and the actual schema link.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandConflictError } from \"../errors\";\nimport {\n beginAssetDeleteOps,\n finishAssetDeleteOps,\n} from \"../ops/assets\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport { linkedAsset } from \"./asset-query\";\nimport { uploadAsset } from \"./asset-upload\";\nimport {\n json,\n loadMemberBook,\n methodNotAllowed,\n requireRouteAuthority,\n type BrandRouteCtx,\n} from \"./http\";\n\n/** List or upload assets. Only live rows are returned; every upload is\n * private and its expiring signed URL is never persisted. */\nexport async function handleAssetsRoot(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n if (req.method === \"POST\") return uploadAsset(ctx, req, bookId);\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { bookId: book.id, status: \"live\" }, order: { createdAt: \"asc\" } },\n book: {},\n },\n });\n const assets = (result[BRAND_NS.asset] ?? []).filter((value) => {\n const row = value as BrandAsset & { book?: BrandBook[] };\n return row.bookId === book.id &&\n Array.isArray(row.book) &&\n row.book.length === 1 &&\n row.book[0]?.id === book.id;\n });\n return json({ assets });\n}\n\n/** Mint a five-minute private URL after current membership + exact link\n * validation. The response itself is non-cacheable. */\nexport async function handleAssetContent(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n const expiresInSeconds = 300;\n const url = await ctx.db.storage.sign(asset.path, expiresInSeconds);\n return json(\n { assetId, url, expiresInSeconds },\n 200,\n { \"cache-control\": \"private, no-store\", \"x-content-type-options\": \"nosniff\" },\n );\n}\n\n/** Guarded deleting → storage tombstone → deleted saga. A retry resumes a\n * deleting row; list/sign paths reject it from the first committed step. */\nexport async function handleAssetItem(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"DELETE\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n let asset = await linkedAsset(ctx, book, assetId, true);\n const authority = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"destructive\", book.id,\n );\n const mutationBase = `brand:asset-delete:v1:${book.id}:${asset.id}`;\n if (asset.status === \"live\") {\n const deletedAt = ctx.now();\n try {\n await ctx.db.transact(beginAssetDeleteOps(\n asset.id,\n deletedAt,\n ctx.actor.id,\n authority.authorityRef,\n ), {\n mutationId: `${mutationBase}:begin`,\n guards: [\n {\n ns: BRAND_NS.asset,\n id: asset.id,\n exists: true,\n equals: {\n bookId: book.id,\n path: asset.path,\n storageObjectId: asset.storageObjectId,\n contentDigest: asset.contentDigest,\n status: \"live\",\n },\n },\n {\n ns: BRAND_NS.book,\n id: book.id,\n exists: true,\n equals: { version: book.version, memberIds: book.memberIds },\n },\n ],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as { code?: unknown }).code === \"transact_guard_failed\"\n ) throw new BrandConflictError(\"asset changed before deletion\");\n throw error;\n }\n asset = { ...asset, status: \"deleting\", deletedAt };\n }\n await ctx.db.storage.delete(asset.path);\n await ctx.db.transact(finishAssetDeleteOps(asset.id), {\n mutationId: `${mutationBase}:finish`,\n guards: [{\n ns: BRAND_NS.asset,\n id: asset.id,\n exists: true,\n equals: {\n bookId: book.id,\n path: asset.path,\n storageObjectId: asset.storageObjectId,\n contentDigest: asset.contentDigest,\n status: \"deleting\",\n deletedBy: asset.deletedBy ?? ctx.actor.id,\n deletedAuthorityRef: asset.deletedAuthorityRef ?? authority.authorityRef,\n },\n }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n return json({ id: asset.id, status: \"deleted\", deletedAt: asset.deletedAt });\n}\n","// /books handlers: create, member-filtered list, and detail.\n//\n// List filtering note: odla-db's query where-clauses have no \"roster array\n// CONTAINS value\" operator (`$in` tests a scalar column against a candidate\n// list, the inverse), so membership on the json `memberIds` roster is not\n// expressible as a where. The handler fetches the namespace and filters in\n// code — exactly the visibility the `brand_book.view` CEL rule\n// (`auth.id in data.memberIds`) enforces for rules-scoped credentials; the\n// admin-key route path just re-applies it server-side.\nimport { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport { BrandConflictError, BrandForbiddenError, BrandInputError } from \"../errors\";\nimport { createBookOps } from \"../ops/books\";\nimport type { BrandBook } from \"../types\";\nimport { capString } from \"../validate\";\nimport {\n isMember,\n json,\n loadBook,\n loadMemberBook,\n methodNotAllowed,\n optStr,\n optStrArray,\n readJson,\n requireRouteAuthority,\n str,\n type BrandRouteCtx,\n} from \"./http\";\n\n/**\n * `GET /books` — every book whose `memberIds` roster contains the actor,\n * oldest first, as `{ books }`. `POST /books` — create a draft book owned by\n * the actor (`slug`, `name`, optional `memberIds` roster and `channelId`);\n * answers 201 with the created row. Other methods: 405.\n */\nexport async function handleBooksRoot(ctx: BrandRouteCtx, req: Request): Promise<Response> {\n if (req.method === \"GET\") {\n const res = await ctx.db.query({ [BRAND_NS.book]: { $: { order: { createdAt: \"asc\" } } } });\n const books = ((res[BRAND_NS.book] ?? []) as unknown as BrandBook[])\n .map((b) => rowAsWritten(BRAND_NS.book, b))\n .filter((b) =>\n isMember(b, ctx.actor.id),\n );\n return json({ books });\n }\n if (req.method === \"POST\") {\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a human can create a brand book\");\n const body = await readJson(req);\n const id = ctx.newId();\n const authority = await requireRouteAuthority(\n ctx,\n req,\n \"brand.edit\",\n \"internal\",\n );\n const ops = createBookOps({\n id,\n slug: str(body, \"slug\"),\n name: str(body, \"name\"),\n ownerId: ctx.actor.id,\n createdAuthorityRef: authority.authorityRef,\n memberIds: optStrArray(body, \"memberIds\") ?? [],\n channelId: optStr(body, \"channelId\"),\n now: ctx.now(),\n });\n await ctx.db.transact(ops, {\n mutationId: id,\n guards: [{ ns: BRAND_NS.book, id, exists: false }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n return json(await loadBook(ctx.db, id), 201);\n }\n return methodNotAllowed();\n}\n\nconst sameStrings = (left: string[], right: string[]): boolean =>\n left.length === right.length && left.every((value, index) => value === right[index]);\nconst guardFailure = (error: unknown): boolean =>\n typeof error === \"object\" && error !== null &&\n (error as { code?: unknown }).code === \"transact_guard_failed\";\n\n/** `PATCH /books/:id/members` — owner-only atomic roster update. Child CEL\n * reads follow schema links to this current roster, so no fan-out is needed. */\nexport async function handleBookMembers(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n if (req.method !== \"PATCH\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a human app owner can change members\");\n const body = await readJson(req);\n const rawMembers = optStrArray(body, \"memberIds\");\n const rawExpected = optStrArray(body, \"expectedMemberIds\");\n if (!rawMembers || !rawExpected)\n throw new BrandInputError('\"memberIds\" and \"expectedMemberIds\" are required string arrays');\n const memberIds = Array.from(new Set([\n book.ownerId,\n ...rawMembers.map((id, index) => capString(id, `memberIds[${index}]`, 160)),\n ]));\n if (memberIds.length > 100)\n throw new BrandInputError(\"a brand book supports at most 100 members\");\n const expectedMemberIds = rawExpected.map((id, index) =>\n capString(id, `expectedMemberIds[${index}]`, 160));\n if (!sameStrings(book.memberIds, expectedMemberIds) && !sameStrings(book.memberIds, memberIds))\n throw new BrandConflictError(\"brand book membership changed since review\");\n\n const mutationId = capString(str(body, \"mutationId\"), \"mutationId\", 200);\n const mutationKey = `brand:book-members:v1:${bookId}:${mutationId}`;\n const authority = await requireRouteAuthority(\n ctx,\n req,\n \"app.manage\",\n \"internal\",\n bookId,\n );\n try {\n const tx = await ctx.db.transact(\n [{\n t: \"update\",\n ns: BRAND_NS.book,\n id: bookId,\n attrs: {\n memberIds,\n version: book.version + 1,\n updatedAt: ctx.now(),\n rosterAuthorityRef: authority.authorityRef,\n },\n }],\n {\n mutationId: mutationKey,\n guards: [{\n ns: BRAND_NS.book,\n id: bookId,\n exists: true,\n equals: { memberIds: expectedMemberIds, version: book.version },\n }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n },\n );\n return json({ bookId, memberIds, duplicate: tx.duplicate === true });\n } catch (error) {\n if (guardFailure(error))\n throw new BrandConflictError(\"brand book membership changed since review\");\n throw error;\n }\n}\n\n/** `GET /books/:id` — the book row, members only (404 otherwise, matching the\n * view rule — see http.ts). Other methods: 405. */\nexport async function handleBookItem(ctx: BrandRouteCtx, req: Request, bookId: string): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n return json(await loadMemberBook(ctx.db, bookId, ctx.actor.id));\n}\n","// Serving a design so a person can look at it.\n//\n// A Claude Design bundle is a self-contained document that MUST run its own\n// JavaScript to render — the loader inflates its assets into blob: URLs and\n// swaps the document root. So there is no safe way to show one by extracting\n// markup; it has to execute. The question is only where.\n//\n// It executes in a CSP `sandbox` with no `allow-same-origin`, which puts the\n// document in a unique OPAQUE origin: scripts run, but they cannot read the\n// host app's cookies, storage, or DOM, and cannot act as the signed-in user.\n// This is the same posture an artifact host takes, and the bundle loader is\n// explicitly written to work in opaque origins (it handles the file://\n// case), so nothing is lost by denying same-origin.\n//\n// Two related choices:\n// - The bytes are PROXIED, not redirected to the signed storage URL. A\n// redirect would run the design on the storage origin, under whatever\n// headers that origin sets, next to every other app's stored objects.\n// Proxying is what makes the sandbox header ours to set.\n// - Only `design`-kind assets are served this way, and `design` is the\n// only kind whose content type may be text/html. An image can never\n// reach this route, and HTML can never reach a non-design kind.\nimport { DESIGN_ASSET_KIND } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport { linkedAsset } from \"./asset-query\";\nimport { json, loadMemberBook, methodNotAllowed, type BrandRouteCtx } from \"./http\";\n\n/** How long the internal signed read URL lives. Seconds, not minutes: it is\n * fetched immediately and never handed to a client. */\nconst SIGNED_READ_TTL_SECONDS = 60;\n\n/**\n * Headers that make an untrusted HTML document safe to render.\n *\n * `sandbox allow-scripts` (WITHOUT `allow-same-origin`) is the load-bearing\n * one — it grants an opaque origin. `allow-scripts` alone is what the bundle\n * needs; forms, popups, top-navigation, and modals stay denied, so a\n * prototype's form cannot post anywhere and a link cannot navigate the\n * embedder away.\n */\nexport function designPreviewHeaders(frameAncestors: string[]): Record<string, string> {\n return {\n \"content-type\": \"text/html; charset=utf-8\",\n \"content-security-policy\": [\n \"sandbox allow-scripts\",\n `frame-ancestors ${frameAncestors.join(\" \")}`,\n ].join(\"; \"),\n \"x-content-type-options\": \"nosniff\",\n \"referrer-policy\": \"no-referrer\",\n \"cache-control\": \"private, no-store\",\n };\n}\n\n/**\n * `GET /books/:id/assets/:assetId/preview` — the design bundle itself,\n * proxied under the sandbox headers above. Members only; a non-design asset\n * answers 404 (the same answer a missing one gets — the route does not\n * confirm that some other kind of asset exists at that id).\n */\nexport async function handleDesignPreview(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n if (asset.kind !== DESIGN_ASSET_KIND) throw new BrandNotFoundError(`design ${assetId}`);\n const signed = await ctx.db.storage.sign(asset.path, SIGNED_READ_TTL_SECONDS);\n // The signed URL is internal: fetched through the product-owned seam, never\n // handed to the client and never redirected to (see the header note).\n // Through a local: a property call would hand `ctx` to fetch as its receiver.\n const fetchPrivateAsset = ctx.fetchPrivateAsset;\n const fetched = await fetchPrivateAsset(signed, {\n headers: { accept: \"text/html\" },\n redirect: \"manual\",\n signal: req.signal,\n });\n if (!fetched.ok || fetched.type === \"opaqueredirect\")\n throw new BrandNotFoundError(`design ${assetId}`);\n return new Response(new Uint8Array(await fetched.arrayBuffer()), {\n status: 200,\n headers: designPreviewHeaders(ctx.previewFrameAncestors),\n });\n}\n\n/**\n * `GET /books/:id/assets/:assetId/design` — the stored {@link\n * import(\"../design/types\").DesignDigest} as JSON: tokens, fonts, colours,\n * props, and heading outline, without the megabytes. This is what a UI\n * header and a building agent read.\n */\nexport async function handleDesignDigest(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n if (asset.kind !== DESIGN_ASSET_KIND || !asset.design)\n throw new BrandNotFoundError(`design ${assetId}`);\n return json(\n { assetId: asset.id, title: asset.title, digest: asset.design },\n 200,\n { \"cache-control\": \"private, no-store\" },\n );\n}\n","import { PROPOSAL_KINDS } from \"../constants\";\nimport { BrandConflictError, BrandInputError } from \"../errors\";\nimport { isBoundedBrandJson } from \"../review\";\nimport type { BrandProposal, BrandProposalReviewSnapshot } from \"../types\";\nimport { capString } from \"../validate\";\nimport { optStr, str } from \"./http\";\n\nconst SNAPSHOT_KEYS = [\n \"audience\",\n \"bookId\",\n \"createdAt\",\n \"createdAuthorityRef\",\n \"createdBy\",\n \"id\",\n \"kind\",\n \"payload\",\n \"provenance\",\n \"rationale\",\n \"reviewDigest\",\n \"status\",\n] as const;\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport interface ProposalResolutionRequest {\n mutationId: string;\n resolution: \"accepted\" | \"rejected\";\n reviewed: BrandProposalReviewSnapshot;\n resolutionNote?: string;\n}\n\nexport function parseProposalResolutionRequest(\n body: Record<string, unknown>,\n bookId: string,\n proposalId: string,\n): ProposalResolutionRequest {\n const allowed = new Set([\n \"mutationId\",\n \"resolution\",\n \"reviewedProposal\",\n \"note\",\n ]);\n if (Object.keys(body).some((key) => !allowed.has(key)))\n throw new BrandInputError(\"proposal resolution body has unknown fields\");\n const mutationId = capString(str(body, \"mutationId\"), \"mutationId\", 200);\n const rawResolution = str(body, \"resolution\");\n if (rawResolution !== \"accepted\" && rawResolution !== \"rejected\")\n throw new BrandInputError('\"resolution\" must be \"accepted\" or \"rejected\"');\n const rawNote = optStr(body, \"note\");\n const resolutionNote = rawNote?.trim()\n ? capString(rawNote, \"note\", 1_000)\n : undefined;\n return {\n mutationId,\n resolution: rawResolution,\n reviewed: parseReviewedProposal(body.reviewedProposal, bookId, proposalId),\n ...(resolutionNote ? { resolutionNote } : {}),\n };\n}\n\n/** Freeze the exact OPEN proposal fields a reviewer sees. */\nexport function proposalReviewSnapshot(proposal: BrandProposal): BrandProposalReviewSnapshot {\n if (proposal.status !== \"open\")\n throw new BrandConflictError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n return {\n id: proposal.id,\n bookId: proposal.bookId,\n kind: proposal.kind,\n status: \"open\",\n payload: proposal.payload,\n rationale: proposal.rationale,\n provenance: proposal.provenance,\n reviewDigest: proposal.reviewDigest,\n audience: proposal.audience,\n createdBy: proposal.createdBy,\n createdAuthorityRef: proposal.createdAuthorityRef,\n createdAt: proposal.createdAt,\n };\n}\n\n/** Strict, bounded request parser: no extra hydration/resolution fields. */\nexport function parseReviewedProposal(\n value: unknown,\n bookId: string,\n proposalId: string,\n): BrandProposalReviewSnapshot {\n // The server bounds the entire guards array. Reserve ample room for guard\n // wrappers and the independent book/palette/receipt guards.\n if (!isBoundedBrandJson(value, { maxDepth: 12, maxNodes: 1_500, maxBytes: 32 * 1024 }))\n throw new BrandInputError('\"reviewedProposal\" is too deeply nested, complex, or large');\n if (!record(value)) throw new BrandInputError('\"reviewedProposal\" must be an object');\n const keys = Object.keys(value).sort();\n if (\n keys.length !== SNAPSHOT_KEYS.length ||\n !SNAPSHOT_KEYS.every((key, index) => key === keys[index])\n ) throw new BrandInputError('\"reviewedProposal\" has an invalid shape');\n if (value.id !== proposalId || value.bookId !== bookId || value.status !== \"open\")\n throw new BrandInputError('\"reviewedProposal\" must identify this open proposal');\n if (\n typeof value.kind !== \"string\" ||\n !(PROPOSAL_KINDS as readonly string[]).includes(value.kind) ||\n !record(value.payload) ||\n typeof value.rationale !== \"string\" ||\n !Array.isArray(value.audience) ||\n value.audience.length < 1 ||\n value.audience.length > 100 ||\n value.audience.some((id) => typeof id !== \"string\" || id.length < 1 || id.length > 200) ||\n new Set(value.audience).size !== value.audience.length ||\n typeof value.createdBy !== \"string\" || value.createdBy.length < 1 || value.createdBy.length > 200 ||\n typeof value.createdAuthorityRef !== \"string\" ||\n value.createdAuthorityRef.length < 1 || value.createdAuthorityRef.length > 200 ||\n !Number.isSafeInteger(value.createdAt) || (value.createdAt as number) < 0 ||\n typeof value.reviewDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.reviewDigest)\n ) throw new BrandInputError('\"reviewedProposal\" has invalid fields');\n if (\n !record(value.provenance) ||\n Object.keys(value.provenance).sort().join(\",\") !==\n \"messageId,sourceAsset,sourceAssetId,taintLabels,turnId\" ||\n (value.provenance.sourceAssetId !== null &&\n (typeof value.provenance.sourceAssetId !== \"string\" ||\n value.provenance.sourceAssetId.length < 1 ||\n value.provenance.sourceAssetId.length > 200)) ||\n (value.provenance.sourceAsset !== null &&\n (!record(value.provenance.sourceAsset) ||\n Object.keys(value.provenance.sourceAsset).sort().join(\",\") !==\n \"analysisDigest,analysisRevision,assetId,contentDigest,contentType,objectEtag,objectSize,pathDigest\" ||\n typeof value.provenance.sourceAsset.assetId !== \"string\" ||\n value.provenance.sourceAsset.assetId.length < 1 ||\n value.provenance.sourceAsset.assetId.length > 200 ||\n typeof value.provenance.sourceAsset.objectEtag !== \"string\" ||\n value.provenance.sourceAsset.objectEtag.length < 1 ||\n value.provenance.sourceAsset.objectEtag.length > 200 ||\n !Number.isSafeInteger(value.provenance.sourceAsset.objectSize) ||\n (value.provenance.sourceAsset.objectSize as number) < 1 ||\n typeof value.provenance.sourceAsset.pathDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.pathDigest) ||\n (value.provenance.sourceAsset.contentType !== null &&\n (typeof value.provenance.sourceAsset.contentType !== \"string\" ||\n value.provenance.sourceAsset.contentType.length < 1 ||\n value.provenance.sourceAsset.contentType.length > 160)) ||\n typeof value.provenance.sourceAsset.contentDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.contentDigest) ||\n (value.provenance.sourceAsset.analysisRevision !== null &&\n (!Number.isSafeInteger(value.provenance.sourceAsset.analysisRevision) ||\n (value.provenance.sourceAsset.analysisRevision as number) < 0)) ||\n (value.provenance.sourceAsset.analysisDigest !== null &&\n (typeof value.provenance.sourceAsset.analysisDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(\n value.provenance.sourceAsset.analysisDigest,\n ))) ||\n value.provenance.sourceAsset.assetId !==\n value.provenance.sourceAssetId)) ||\n ((value.provenance.sourceAssetId === null) !==\n (value.provenance.sourceAsset === null)) ||\n (value.provenance.messageId !== null &&\n (typeof value.provenance.messageId !== \"string\" ||\n value.provenance.messageId.length < 1 ||\n value.provenance.messageId.length > 200)) ||\n (value.provenance.turnId !== null &&\n (typeof value.provenance.turnId !== \"string\" ||\n value.provenance.turnId.length < 1 ||\n value.provenance.turnId.length > 200)) ||\n !Array.isArray(value.provenance.taintLabels) ||\n value.provenance.taintLabels.length > 16 ||\n value.provenance.taintLabels.some((label) =>\n typeof label !== \"string\" || label.length < 1 || label.length > 120) ||\n new Set(value.provenance.taintLabels).size !== value.provenance.taintLabels.length\n ) throw new BrandInputError('\"reviewedProposal.provenance\" is invalid');\n return value as unknown as BrandProposalReviewSnapshot;\n}\n\nexport const proposalGuardEquals = (\n snapshot: BrandProposalReviewSnapshot,\n): Record<string, unknown> => ({ ...snapshot });\n","import { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { acceptProposalOps, rejectProposalOps } from \"../ops/palettes\";\nimport { upsertSectionOps } from \"../ops/sections\";\nimport { brandJsonDigest } from \"../review\";\nimport { compileBrandTokens } from \"../tokens/compile\";\nimport type {\n BrandBook,\n BrandOp,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTokensSnapshot,\n Swatch,\n TypographySection,\n} from \"../types\";\nimport { assertSwatches } from \"../validate\";\n\nexport interface ProposalEffectInput {\n proposal: BrandProposal;\n book: BrandBook;\n resolution: \"accepted\" | \"rejected\";\n receiptId: string;\n actionDigest: string;\n paletteId?: string;\n priorPalette?: BrandPalette;\n approvedTypography?: BrandSection;\n actorId: string;\n now: number;\n resolutionNote?: string;\n}\n\nasync function tokenSnapshot(\n swatches: Swatch[],\n typography: TypographySection | undefined,\n input: ProposalEffectInput,\n paletteId: string,\n paletteReceiptId: string,\n paletteActionDigest: string,\n typographyReceiptId?: string,\n typographyActionDigest?: string,\n): Promise<BrandTokensSnapshot> {\n const compiled = compileBrandTokens({ swatches, ...(typography ? { typography } : {}) });\n const sources = {\n paletteId,\n paletteReceiptId,\n paletteActionDigest,\n typographyReceiptId: typographyReceiptId ?? null,\n typographyActionDigest: typographyActionDigest ?? null,\n };\n return {\n light: compiled.light,\n dark: compiled.dark,\n warnings: compiled.warnings,\n compiledAt: input.now,\n paletteId,\n paletteReceiptId,\n paletteActionDigest,\n ...(typographyReceiptId ? { typographyReceiptId } : {}),\n ...(typographyActionDigest ? { typographyActionDigest } : {}),\n sourceDigest: await brandJsonDigest(sources),\n };\n}\n\nfunction stampProposal(ops: BrandOp[], input: ProposalEffectInput): void {\n const op = ops.find(\n (candidate) =>\n candidate.t === \"update\" &&\n candidate.ns === BRAND_NS.proposal &&\n candidate.id === input.proposal.id,\n );\n if (!op || op.t !== \"update\") throw new Error(\"proposal resolution op missing\");\n Object.assign(op.attrs, {\n approvedBy: input.actorId,\n appliedBy: input.actorId,\n resolutionReceiptId: input.receiptId,\n resolutionActionDigest: input.actionDigest,\n });\n}\n\n/** Build all live effects for one guarded decision. */\nexport async function proposalDecisionOps(input: ProposalEffectInput): Promise<BrandOp[]> {\n const common = {\n proposal: input.proposal,\n resolvedBy: input.actorId,\n now: input.now,\n resolutionNote: input.resolutionNote,\n };\n if (input.resolution === \"rejected\") {\n const ops = rejectProposalOps(common);\n stampProposal(ops, input);\n return ops;\n }\n\n let ops: BrandOp[];\n if (input.proposal.kind === \"palette\") {\n if (!input.paletteId) throw new Error(\"accepted palette id missing\");\n ops = acceptProposalOps({\n ...common,\n paletteId: input.paletteId,\n approvalReceiptId: input.receiptId,\n approvalActionDigest: input.actionDigest,\n });\n const swatches = assertSwatches(input.proposal.payload.swatches);\n const tokens = await tokenSnapshot(\n swatches,\n input.approvedTypography?.content as TypographySection | undefined,\n input,\n input.paletteId,\n input.receiptId,\n input.actionDigest,\n input.approvedTypography?.approvalReceiptId,\n input.approvedTypography?.approvalActionDigest,\n );\n const bookOp = ops.find(\n (op) => op.t === \"update\" && op.ns === BRAND_NS.book && op.id === input.book.id,\n );\n if (!bookOp || bookOp.t !== \"update\") throw new Error(\"book activation op missing\");\n Object.assign(bookOp.attrs, {\n version: input.book.version + 1,\n activationRevision: input.book.activationRevision + 1,\n tokens,\n });\n if (input.priorPalette && input.priorPalette.id !== input.paletteId) {\n ops.unshift({\n t: \"update\",\n ns: BRAND_NS.palette,\n id: input.priorPalette.id,\n attrs: { status: \"archived\", updatedAt: input.now },\n });\n }\n } else {\n const content = input.proposal.payload.content;\n if (typeof content !== \"object\" || content === null || Array.isArray(content))\n throw new BrandInputError(\"proposal payload.content must be an object\");\n ops = [\n ...upsertSectionOps({\n bookId: input.book.id,\n kind: input.proposal.kind,\n content: content as Record<string, unknown>,\n status: \"approved\",\n audience: input.book.memberIds,\n updatedBy: input.actorId,\n approvalReceiptId: input.receiptId,\n approvalActionDigest: input.actionDigest,\n now: input.now,\n }),\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: input.book.id,\n attrs: {\n activationRevision: input.book.activationRevision + 1,\n version: input.book.version + 1,\n updatedAt: input.now,\n },\n },\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.proposal.id,\n attrs: {\n status: \"accepted\",\n resolvedBy: input.actorId,\n resolvedAt: input.now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n if (input.proposal.kind === \"typography\" && input.priorPalette) {\n const bookOp = ops.find(\n (op) => op.t === \"update\" && op.ns === BRAND_NS.book && op.id === input.book.id,\n );\n if (bookOp?.t === \"update\") {\n if (!input.priorPalette.approvalReceiptId || !input.priorPalette.approvalActionDigest)\n throw new BrandInputError(\"active palette is missing approval provenance\");\n bookOp.attrs.tokens = await tokenSnapshot(\n input.priorPalette.swatches,\n content as TypographySection,\n input,\n input.priorPalette.id,\n input.priorPalette.approvalReceiptId,\n input.priorPalette.approvalActionDigest,\n input.receiptId,\n input.actionDigest,\n );\n }\n }\n }\n stampProposal(ops, input);\n return ops;\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandForbiddenError } from \"../errors\";\nimport {\n brandJsonDigest,\n canonicalBrandJson,\n isBrandHumanAuthorityConsumption,\n receiptAsWritten,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandHumanAuthorityConsumption,\n BrandProposalReviewSnapshot,\n} from \"../types\";\nimport type { BrandRouteCtx } from \"./http\";\n\n/** Fixed-width local/central idempotency domain. Caller-controlled ids are\n * hashed so every legal request stays below registry and database key limits. */\nexport async function proposalResolutionMutationKey(\n bookId: string,\n proposalId: string,\n mutationId: string,\n): Promise<string> {\n const digest = await brandJsonDigest({\n version: 3,\n bookId,\n proposalId,\n mutationId,\n });\n return `brand:proposal-resolution:v3:${digest.slice(\"sha256:\".length)}`;\n}\n\nexport async function proposalReceiptByMutation(\n ctx: BrandRouteCtx,\n mutationKey: string,\n): Promise<BrandApprovalReceipt | undefined> {\n const result = await ctx.db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { mutationKey } },\n book: {},\n },\n });\n const row = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== row.bookId\n ) return undefined;\n const { book: _book, ...receipt } = row;\n // Back to the shape it was written in before anyone verifies it: `createdAt`\n // is a `date`, so the store hands back ISO text the digest never covered.\n return receiptAsWritten(receipt) as BrandApprovalReceipt;\n}\n\nexport async function consumeProposalAuthority(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n proposalId: string,\n actionDigest: string,\n mutationKey: string,\n): Promise<BrandHumanAuthorityConsumption> {\n const authority = await ctx.consumeHumanExact({\n req,\n actor: ctx.actor,\n appId: ctx.appId,\n capability: \"brand.proposal.resolve\",\n projectCapability: \"brand.approve\",\n effect: \"internal\",\n resource: { bookId, proposalId },\n actionDigest,\n consumptionIdempotencyKey: mutationKey,\n });\n const resourceDigest = await brandJsonDigest({ bookId, proposalId });\n if (\n !isBrandHumanAuthorityConsumption(authority) ||\n authority.actorPrincipalId !== ctx.actor.id ||\n authority.appId !== ctx.appId ||\n authority.actionDigest !== actionDigest ||\n authority.resourceDigest !== resourceDigest ||\n authority.consumptionIdempotencyKey !== mutationKey\n ) throw new BrandForbiddenError(\n \"a verified human-exact brand approval is required\",\n );\n return authority;\n}\n\nexport function sameProposalResolutionRequest(\n receipt: BrandApprovalReceipt,\n reviewed: BrandProposalReviewSnapshot,\n resolution: \"accepted\" | \"rejected\",\n note: string | undefined,\n paletteId: string | undefined,\n): boolean {\n return receipt.resolution === resolution &&\n (receipt.resolutionNote ?? null) === (note ?? null) &&\n (receipt.paletteId ?? null) === (paletteId ?? null) &&\n canonicalBrandJson(receipt.reviewedProposal) ===\n canonicalBrandJson(reviewed);\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandConflictError } from \"../errors\";\nimport {\n canonicalBrandJson,\n verifyBrandApprovalReceipt,\n receiptAsWritten,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandBook,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n assertHex,\n assertSectionContent,\n assertSwatches,\n capString,\n} from \"../validate\";\nimport type { BrandRouteCtx } from \"./http\";\n\nasync function receipt(\n ctx: BrandRouteCtx,\n id: string,\n actionDigest: string,\n expected: {\n bookId: string;\n kind: BrandProposal[\"kind\"];\n paletteId?: string;\n proposalId?: string;\n content?: Record<string, unknown>;\n },\n): Promise<BrandApprovalReceipt> {\n const result = await ctx.db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { id } },\n book: {},\n },\n });\n const row = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n row.actionDigest !== actionDigest ||\n row.resolution !== \"accepted\" ||\n row.bookId !== expected.bookId ||\n row.reviewedProposal.bookId !== expected.bookId ||\n row.reviewedProposal.kind !== expected.kind ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== expected.bookId ||\n (expected.paletteId !== undefined && row.paletteId !== expected.paletteId) ||\n (expected.proposalId !== undefined && row.proposalId !== expected.proposalId) ||\n (expected.content !== undefined &&\n canonicalBrandJson(row.reviewedProposal.payload.content) !==\n canonicalBrandJson(expected.content))\n ) throw new BrandConflictError(`approval receipt ${id} is invalid`);\n const { book: _book, ...stored } = row;\n const unhydrated = receiptAsWritten(stored);\n if (!(await verifyBrandApprovalReceipt(unhydrated)))\n throw new BrandConflictError(`approval receipt ${id} is invalid`);\n return unhydrated as BrandApprovalReceipt;\n}\n\nexport async function activePalette(\n ctx: BrandRouteCtx,\n book: BrandBook,\n): Promise<{ palette?: BrandPalette; receipt?: BrandApprovalReceipt }> {\n if (!book.activePaletteId) return {};\n const result = await ctx.db.query({\n [BRAND_NS.palette]: {\n $: { where: { id: book.activePaletteId } },\n book: {},\n },\n });\n const palette = (result[BRAND_NS.palette] ?? [])[0] as\n | (BrandPalette & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !palette ||\n palette.bookId !== book.id ||\n palette.status !== \"active\" ||\n !palette.proposalId ||\n !palette.approvalReceiptId ||\n !palette.approvalActionDigest ||\n !Array.isArray(palette.book) ||\n palette.book.length !== 1 ||\n palette.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"active palette is missing valid approval provenance\",\n );\n const approval = await receipt(\n ctx,\n palette.approvalReceiptId,\n palette.approvalActionDigest,\n {\n bookId: book.id,\n kind: \"palette\",\n paletteId: palette.id,\n proposalId: palette.proposalId,\n },\n );\n let expectedName: string;\n let expectedSwatches: ReturnType<typeof assertSwatches>;\n let expectedSeed: string | undefined;\n try {\n expectedName = capString(\n approval.reviewedProposal.payload.name,\n \"reviewedProposal.payload.name\",\n 120,\n );\n expectedSwatches = assertSwatches(\n approval.reviewedProposal.payload.swatches,\n );\n expectedSeed = approval.reviewedProposal.payload.seedHex === undefined\n ? undefined\n : assertHex(\n approval.reviewedProposal.payload.seedHex,\n \"reviewedProposal.payload.seedHex\",\n );\n } catch {\n throw new BrandConflictError(\"active palette approval payload is invalid\");\n }\n const expectedSource = approval.reviewedProposal.provenance.sourceAsset\n ? \"extracted\"\n : expectedSeed\n ? \"derived\"\n : \"manual\";\n if (\n palette.proposalId !== approval.proposalId ||\n palette.name !== expectedName ||\n canonicalBrandJson(palette.swatches) !== canonicalBrandJson(expectedSwatches) ||\n (palette.seedHex ?? null) !== (expectedSeed ?? null) ||\n palette.source !== expectedSource ||\n palette.rationale !== approval.reviewedProposal.rationale ||\n canonicalBrandJson(palette.audience) !==\n canonicalBrandJson(approval.reviewedProposal.audience) ||\n palette.createdAt !== approval.createdAt ||\n palette.updatedAt !== approval.createdAt\n ) throw new BrandConflictError(\n \"active palette does not match its approved proposal\",\n );\n return { palette, receipt: approval };\n}\n\nexport async function approvedTypography(\n ctx: BrandRouteCtx,\n book: BrandBook,\n): Promise<{ section?: BrandSection; receipt?: BrandApprovalReceipt }> {\n const key = `${book.id}:typography`;\n const result = await ctx.db.query({\n [BRAND_NS.section]: {\n $: { where: { key } },\n book: {},\n },\n });\n const section = (result[BRAND_NS.section] ?? [])[0] as\n | (BrandSection & { book?: Array<{ id: string }> })\n | undefined;\n if (!section || section.status !== \"approved\") return {};\n if (\n section.bookId !== book.id ||\n section.kind !== \"typography\" ||\n !section.approvalReceiptId ||\n !section.approvalActionDigest ||\n !Array.isArray(section.book) ||\n section.book.length !== 1 ||\n section.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"approved typography is missing valid approval provenance\",\n );\n assertSectionContent(\"typography\", section.content);\n return {\n section,\n receipt: await receipt(\n ctx,\n section.approvalReceiptId,\n section.approvalActionDigest,\n { bookId: book.id, kind: \"typography\", content: section.content },\n ),\n };\n}\n\nexport const receiptGuard = (\n value: BrandApprovalReceipt,\n): BrandTransactGuard => ({\n ns: BRAND_NS.approvalReceipt,\n id: value.id,\n exists: true,\n equals: {\n actionDigest: value.actionDigest,\n receiptDigest: value.receiptDigest,\n resolution: \"accepted\",\n },\n});\n","import { BRAND_NS } from \"../constants\";\nimport { BrandConflictError, BrandNotFoundError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type {\n BrandAsset,\n BrandBook,\n BrandDecisionBinding,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n assertSectionContent,\n assertSwatches,\n capString,\n} from \"../validate\";\nimport type { BrandRouteCtx } from \"./http\";\nimport {\n activePalette,\n approvedTypography,\n receiptGuard,\n} from \"./proposal-dependencies\";\n\nexport interface ProposalDecisionState {\n priorPalette?: BrandPalette;\n approvedTypography?: BrandSection;\n binding: BrandDecisionBinding;\n effectDescriptor: Record<string, unknown>;\n dependencyGuards: BrandTransactGuard[];\n}\n\n/** Resolve, validate, and digest every live dependency before authority is\n * consumed. The caller must include every returned guard in the local CAS. */\nexport async function proposalDecisionState(\n ctx: BrandRouteCtx,\n req: Request,\n book: BrandBook,\n proposal: BrandProposal,\n resolution: \"accepted\" | \"rejected\",\n receiptId: string,\n paletteId?: string,\n): Promise<ProposalDecisionState> {\n const needsPalette = resolution === \"accepted\" &&\n (proposal.kind === \"palette\" || proposal.kind === \"typography\");\n const paletteDep = needsPalette ? await activePalette(ctx, book) : {};\n const typeDep = resolution === \"accepted\" && proposal.kind === \"palette\"\n ? await approvedTypography(ctx, book)\n : {};\n const dependencyGuards: BrandTransactGuard[] = [];\n const source = proposal.provenance.sourceAsset;\n let sourceAsset: (BrandAsset & { book?: Array<{ id: string }> }) | undefined;\n if (source && resolution === \"accepted\") {\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: source.assetId, bookId: book.id } },\n book: {},\n },\n });\n sourceAsset = (result[BRAND_NS.asset] ?? [])[0] as\n | (BrandAsset & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !sourceAsset ||\n sourceAsset.id !== source.assetId ||\n sourceAsset.bookId !== book.id ||\n sourceAsset.status !== \"live\" ||\n sourceAsset.deletedAt !== undefined ||\n sourceAsset.contentDigest !== source.contentDigest ||\n sourceAsset.size !== source.objectSize ||\n sourceAsset.contentType !== source.contentType ||\n (await brandJsonDigest({ appId: ctx.appId, path: sourceAsset.path })) !==\n source.pathDigest ||\n sourceAsset.analysisRevision !== source.analysisRevision ||\n (sourceAsset.analysisDigest ?? null) !== source.analysisDigest ||\n !Array.isArray(sourceAsset.book) ||\n sourceAsset.book.length !== 1 ||\n sourceAsset.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"source asset changed since the proposal was reviewed\",\n );\n if (!(await ctx.verifySourceAssetSnapshot({\n req,\n appId: ctx.appId,\n bookId: book.id,\n assetId: source.assetId,\n path: sourceAsset.path,\n snapshot: source,\n }))) throw new BrandConflictError(\n \"source asset bytes changed since the proposal was reviewed\",\n );\n dependencyGuards.push({\n ns: BRAND_NS.asset,\n id: sourceAsset.id,\n exists: true,\n equals: {\n bookId: book.id,\n status: \"live\",\n path: sourceAsset.path,\n storageObjectId: sourceAsset.storageObjectId,\n contentDigest: source.contentDigest,\n contentType: source.contentType,\n size: source.objectSize,\n analysisRevision: source.analysisRevision,\n ...(source.analysisDigest ? { analysisDigest: source.analysisDigest } : {}),\n },\n });\n }\n if (paletteDep.palette && paletteDep.receipt) {\n dependencyGuards.push({\n ns: BRAND_NS.palette,\n id: paletteDep.palette.id,\n exists: true,\n equals: {\n bookId: book.id,\n status: \"active\",\n name: paletteDep.palette.name,\n swatches: paletteDep.palette.swatches,\n seedHex: paletteDep.palette.seedHex ?? null,\n source: paletteDep.palette.source,\n rationale: paletteDep.palette.rationale,\n proposalId: paletteDep.palette.proposalId,\n approvalReceiptId: paletteDep.palette.approvalReceiptId,\n approvalActionDigest: paletteDep.palette.approvalActionDigest,\n audience: paletteDep.palette.audience,\n createdAt: paletteDep.palette.createdAt,\n updatedAt: paletteDep.palette.updatedAt,\n },\n }, receiptGuard(paletteDep.receipt));\n }\n if (typeDep.section && typeDep.receipt) {\n dependencyGuards.push({\n ns: BRAND_NS.section,\n id: typeDep.section.id,\n exists: true,\n equals: {\n key: typeDep.section.key,\n bookId: book.id,\n kind: \"typography\",\n status: \"approved\",\n content: typeDep.section.content,\n approvalReceiptId: typeDep.section.approvalReceiptId,\n approvalActionDigest: typeDep.section.approvalActionDigest,\n updatedAt: typeDep.section.updatedAt,\n },\n }, receiptGuard(typeDep.receipt));\n }\n\n let approvedContent: Record<string, unknown> | null = null;\n let paletteResult: Record<string, unknown> | null = null;\n if (resolution === \"accepted\" && proposal.kind === \"palette\") {\n if (!paletteId) throw new BrandNotFoundError(\"resulting palette id\");\n paletteResult = {\n id: paletteId,\n name: capString(proposal.payload.name, \"payload.name\", 120),\n swatches: assertSwatches(proposal.payload.swatches),\n seedHex: proposal.payload.seedHex ?? null,\n receiptId,\n archivePaletteId: paletteDep.palette?.id ?? null,\n };\n } else if (resolution === \"accepted\") {\n approvedContent = assertSectionContent(\n proposal.kind,\n proposal.payload.content,\n );\n }\n const tokenSources = resolution === \"accepted\" && (\n proposal.kind === \"palette\" || proposal.kind === \"typography\"\n ) ? {\n paletteReceiptId: proposal.kind === \"palette\"\n ? receiptId\n : paletteDep.palette?.approvalReceiptId ?? null,\n paletteActionDigest: proposal.kind === \"palette\"\n ? \"this-action\"\n : paletteDep.palette?.approvalActionDigest ?? null,\n typographyReceiptId: proposal.kind === \"typography\"\n ? receiptId\n : typeDep.section?.approvalReceiptId ?? null,\n typographyActionDigest: proposal.kind === \"typography\"\n ? \"this-action\"\n : typeDep.section?.approvalActionDigest ?? null,\n } : null;\n const effectDescriptor = {\n proposalId: proposal.id,\n resolution,\n nextBookVersion: resolution === \"accepted\" ? book.version + 1 : null,\n nextActivationRevision:\n resolution === \"accepted\" ? book.activationRevision + 1 : null,\n resultingActivePaletteId: proposal.kind === \"palette\" && resolution === \"accepted\"\n ? paletteId ?? null\n : book.activePaletteId ?? null,\n palette: paletteResult,\n approvedSection: approvedContent\n ? { kind: proposal.kind, content: approvedContent, receiptId }\n : null,\n tokenSources,\n };\n const binding: BrandDecisionBinding = {\n version: 1,\n bookVersion: book.version,\n activationRevision: book.activationRevision,\n activePaletteId: book.activePaletteId ?? null,\n memberIdsDigest: await brandJsonDigest(book.memberIds),\n activePaletteDigest: paletteDep.palette\n ? await brandJsonDigest({\n id: paletteDep.palette.id,\n swatches: paletteDep.palette.swatches,\n approvalReceiptId: paletteDep.palette.approvalReceiptId,\n approvalActionDigest: paletteDep.palette.approvalActionDigest,\n })\n : null,\n typographyDigest: typeDep.section\n ? await brandJsonDigest({\n key: typeDep.section.key,\n content: typeDep.section.content,\n approvalReceiptId: typeDep.section.approvalReceiptId,\n approvalActionDigest: typeDep.section.approvalActionDigest,\n })\n : null,\n sourceAssetDigest: source\n ? await brandJsonDigest(source)\n : null,\n effectDigest: await brandJsonDigest(effectDescriptor),\n };\n return {\n ...(paletteDep.palette ? { priorPalette: paletteDep.palette } : {}),\n ...(typeDep.section ? { approvedTypography: typeDep.section } : {}),\n binding,\n effectDescriptor,\n dependencyGuards,\n };\n}\n","// Decisions consume one credential-bound central `human_exact` authority use.\n// Local receipts are immutable projections; their hash proves consistency,\n// while authenticity comes only from the host's central receipt verifier.\nimport { BRAND_NS } from \"../constants\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandNotFoundError,\n BrandReviewStateChangedError,\n} from \"../errors\";\nimport {\n brandAuthorityRef,\n brandJsonDigest,\n canonicalBrandJson,\n proposalAsWritten,\n verifyBrandApprovalReceipt,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandProposal,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n json,\n loadMemberBook,\n methodNotAllowed,\n readJson,\n type BrandRouteCtx,\n} from \"./http\";\nimport {\n parseProposalResolutionRequest,\n proposalGuardEquals,\n proposalReviewSnapshot,\n} from \"./proposal-input\";\nimport { proposalDecisionOps } from \"./proposal-effects\";\nimport {\n consumeProposalAuthority,\n proposalReceiptByMutation,\n proposalResolutionMutationKey,\n sameProposalResolutionRequest,\n} from \"./proposal-resolution-receipts\";\nimport { proposalDecisionState } from \"./proposal-state\";\n\nexport { proposalResolutionMutationKey } from \"./proposal-resolution-receipts\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst sameStrings = (left: string[], right: string[]): boolean =>\n left.length === right.length && left.every((value, index) => value === right[index]);\nconst guardFailure = (error: unknown): boolean =>\n record(error) && error.code === \"transact_guard_failed\";\n\n/** `POST /books/:bookId/proposals/:proposalId/resolve` — direct human member\n * plus current app owner/co-owner central approval. */\nexport async function handleProposalResolution(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n proposalId: string,\n): Promise<Response> {\n if (req.method !== \"POST\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a directly authenticated human can resolve a proposal\");\n\n const body = await readJson(req);\n const {\n mutationId,\n resolution,\n reviewed,\n resolutionNote,\n } = parseProposalResolutionRequest(body, bookId, proposalId);\n const mutationKey = await proposalResolutionMutationKey(\n bookId,\n proposalId,\n mutationId,\n );\n const stable = (await brandJsonDigest({ mutationKey })).slice(7);\n const receiptId = `brand-receipt-${stable.slice(0, 32)}`;\n const paletteId = resolution === \"accepted\" && reviewed.kind === \"palette\"\n ? `brand-palette-${stable.slice(32)}`\n : undefined;\n\n // Completed retries re-authenticate and replay the exact central receipt;\n // they never need the now-resolved proposal row.\n const existing = await proposalReceiptByMutation(ctx, mutationKey);\n if (existing) {\n if (\n !(await verifyBrandApprovalReceipt(existing)) ||\n !sameProposalResolutionRequest(\n existing, reviewed, resolution, resolutionNote, paletteId,\n )\n ) throw new BrandConflictError(\"mutationId was used for another decision\");\n const replayed = await consumeProposalAuthority(\n ctx, req, bookId, proposalId, existing.actionDigest, mutationKey,\n );\n if (\n canonicalBrandJson(replayed) !==\n canonicalBrandJson(existing.authorityConsumption)\n ) throw new BrandConflictError(\"central approval receipt changed\");\n return json({ receipt: existing, duplicate: true });\n }\n\n const result = await ctx.db.query({\n [BRAND_NS.proposal]: {\n $: { where: { id: proposalId, bookId } },\n book: {},\n },\n });\n // Back to the shape it was written in: `reviewDigest` covers `createdAt`,\n // which the store hands back as ISO text it never digested.\n const proposal = proposalAsWritten((result[BRAND_NS.proposal] ?? [])[0]) as\n | (BrandProposal & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !proposal ||\n proposal.bookId !== book.id ||\n !Array.isArray(proposal.book) ||\n proposal.book.length !== 1 ||\n proposal.book[0]?.id !== book.id\n ) throw new BrandNotFoundError(`proposal ${proposalId}`);\n const current = proposalReviewSnapshot(proposal);\n const { reviewDigest, ...unsignedReview } = current;\n if (\n (await brandJsonDigest(unsignedReview)) !== reviewDigest ||\n canonicalBrandJson(current) !== canonicalBrandJson(reviewed)\n ) throw new BrandConflictError(\"proposal changed since review\");\n // Acceptance applies live effects and therefore requires a fresh review\n // against the current roster. Rejection applies no Brand materialization:\n // a current human owner who remains a book member may close the exact\n // immutable stale proposal instead of leaving it permanently unresolvable.\n if (resolution === \"accepted\" && !sameStrings(current.audience, book.memberIds))\n throw new BrandConflictError(\"book membership changed; review the proposal again\");\n\n const state = await proposalDecisionState(\n ctx, req, book, proposal, resolution, receiptId, paletteId,\n );\n const actionDigest = await brandJsonDigest({\n version: 1,\n reviewedProposal: current,\n resolution,\n resolutionNote: resolutionNote ?? null,\n paletteId: paletteId ?? null,\n decisionBinding: state.binding,\n });\n const authority = await consumeProposalAuthority(\n ctx, req, bookId, proposalId, actionDigest, mutationKey,\n );\n const receiptBase = {\n version: 1 as const,\n id: receiptId,\n mutationKey,\n bookId,\n proposalId,\n resolution,\n ...(paletteId ? { paletteId } : {}),\n ...(resolutionNote ? { resolutionNote } : {}),\n reviewedProposal: current,\n actionDigest,\n decisionBinding: state.binding,\n approvedBy: ctx.actor.id,\n approvedByKind: \"human\" as const,\n appliedBy: ctx.actor.id,\n appliedByKind: \"human\" as const,\n authorityRef: brandAuthorityRef(authority),\n authorityCapability: \"brand.approve\" as const,\n authorityConsumption: authority,\n createdAt: authority.consumedAt,\n };\n const receipt: BrandApprovalReceipt = {\n ...receiptBase,\n receiptDigest: await brandJsonDigest(receiptBase),\n };\n const ops = await proposalDecisionOps({\n proposal: { ...proposal, audience: [...book.memberIds] },\n book,\n resolution,\n receiptId,\n actionDigest,\n ...(paletteId ? { paletteId } : {}),\n ...(state.priorPalette ? { priorPalette: state.priorPalette } : {}),\n ...(state.approvedTypography\n ? { approvedTypography: state.approvedTypography }\n : {}),\n actorId: ctx.actor.id,\n now: authority.consumedAt,\n resolutionNote,\n });\n ops.push({\n t: \"update\",\n ns: BRAND_NS.approvalReceipt,\n id: receipt.id,\n attrs: receipt,\n }, {\n t: \"link\",\n ns: BRAND_NS.approvalReceipt,\n id: receipt.id,\n label: \"book\",\n target: bookId,\n });\n const guards: BrandTransactGuard[] = [\n {\n ns: BRAND_NS.proposal,\n id: proposalId,\n exists: true,\n equals: proposalGuardEquals(current),\n },\n { ns: BRAND_NS.approvalReceipt, id: receiptId, exists: false },\n {\n ns: BRAND_NS.book,\n id: bookId,\n exists: true,\n equals: {\n version: book.version,\n activationRevision: book.activationRevision,\n memberIds: book.memberIds,\n },\n },\n ...state.dependencyGuards,\n ];\n if (paletteId) {\n guards.push({ ns: BRAND_NS.palette, id: paletteId, exists: false });\n }\n try {\n const tx = await ctx.db.transact(ops, {\n mutationId: mutationKey,\n guards,\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n if (tx.duplicate) {\n const replay = await proposalReceiptByMutation(ctx, mutationKey);\n if (\n !replay ||\n !(await verifyBrandApprovalReceipt(replay)) ||\n !sameProposalResolutionRequest(\n replay, reviewed, resolution, resolutionNote, paletteId,\n ) ||\n canonicalBrandJson(replay.authorityConsumption) !==\n canonicalBrandJson(authority)\n )\n throw new BrandConflictError(\"proposal decision replay is invalid\");\n return json({ receipt: replay, duplicate: true });\n }\n return json({ receipt, duplicate: false });\n } catch (error) {\n if (guardFailure(error)) throw new BrandReviewStateChangedError();\n throw error;\n }\n}\n","// Tokens are served only from an approval-bound cache. GET never compiles\n// drafts or repairs stale state; any missing/mismatched dependency fails\n// closed until a new human-approved activation recompiles the cache.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport { brandJsonDigest, receiptAsWritten, verifyBrandApprovalReceipt } from \"../review\";\nimport { renderTokensCss } from \"../tokens/css\";\nimport type { BrandTokens } from \"../tokens/types\";\nimport type {\n BrandActor,\n BrandApprovalReceipt,\n BrandBook,\n BrandPalette,\n BrandSection,\n BrandTokensSnapshot,\n} from \"../types\";\nimport { json, loadBook, loadMemberBook, methodNotAllowed } from \"./http\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst missing = (bookId: string): never => {\n throw new BrandNotFoundError(`compiled tokens for brand book ${bookId}`);\n};\n\nasync function acceptedReceipt(\n db: Parameters<typeof loadBook>[0],\n bookId: string,\n receiptId: string,\n actionDigest: string,\n): Promise<BrandApprovalReceipt> {\n const result = await db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { id: receiptId, bookId } },\n book: {},\n },\n });\n const receipt = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !receipt ||\n receipt.resolution !== \"accepted\" ||\n receipt.actionDigest !== actionDigest ||\n !Array.isArray(receipt.book) ||\n receipt.book.length !== 1 ||\n receipt.book[0]?.id !== bookId\n ) return missing(bookId);\n const { book: _book, ...stored } = receipt;\n const unhydrated = receiptAsWritten(stored);\n if (!(await verifyBrandApprovalReceipt(unhydrated))) return missing(bookId);\n return unhydrated as BrandApprovalReceipt;\n}\n\nasync function approvedCache(\n db: Parameters<typeof loadBook>[0],\n book: BrandBook,\n): Promise<BrandTokensSnapshot> {\n const cache = book.tokens;\n if (\n !cache ||\n !record(cache.light) ||\n !record(cache.dark) ||\n !book.activePaletteId ||\n cache.paletteId !== book.activePaletteId ||\n !cache.paletteReceiptId ||\n !cache.paletteActionDigest ||\n !cache.sourceDigest\n ) return missing(book.id);\n const paletteResult = await db.query({\n [BRAND_NS.palette]: {\n $: { where: { id: cache.paletteId, bookId: book.id } },\n book: {},\n },\n });\n const palette = (paletteResult[BRAND_NS.palette] ?? [])[0] as\n | (BrandPalette & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !palette ||\n palette.status !== \"active\" ||\n palette.approvalReceiptId !== cache.paletteReceiptId ||\n palette.approvalActionDigest !== cache.paletteActionDigest ||\n !Array.isArray(palette.book) ||\n palette.book.length !== 1 ||\n palette.book[0]?.id !== book.id\n ) return missing(book.id);\n await acceptedReceipt(\n db, book.id, cache.paletteReceiptId, cache.paletteActionDigest,\n );\n\n const hasTypeId = cache.typographyReceiptId !== undefined;\n const hasTypeDigest = cache.typographyActionDigest !== undefined;\n if (hasTypeId !== hasTypeDigest) return missing(book.id);\n const sectionResult = await db.query({\n [BRAND_NS.section]: {\n $: { where: { key: `${book.id}:typography` } },\n book: {},\n },\n });\n const typography = (sectionResult[BRAND_NS.section] ?? [])[0] as\n | (BrandSection & { book?: Array<{ id: string }> })\n | undefined;\n if (hasTypeId) {\n if (\n !typography ||\n typography.bookId !== book.id ||\n typography.kind !== \"typography\" ||\n typography.status !== \"approved\" ||\n typography.approvalReceiptId !== cache.typographyReceiptId ||\n typography.approvalActionDigest !== cache.typographyActionDigest ||\n !Array.isArray(typography.book) ||\n typography.book.length !== 1 ||\n typography.book[0]?.id !== book.id\n ) return missing(book.id);\n await acceptedReceipt(\n db,\n book.id,\n cache.typographyReceiptId!,\n cache.typographyActionDigest!,\n );\n } else if (\n typography?.status === \"approved\" &&\n (typography.approvalReceiptId || typography.approvalActionDigest)\n ) {\n // An approved dependency exists but the cache omits it.\n return missing(book.id);\n }\n const sourceDigest = await brandJsonDigest({\n paletteId: cache.paletteId,\n paletteReceiptId: cache.paletteReceiptId,\n paletteActionDigest: cache.paletteActionDigest,\n typographyReceiptId: cache.typographyReceiptId ?? null,\n typographyActionDigest: cache.typographyActionDigest ?? null,\n });\n if (sourceDigest !== cache.sourceDigest) return missing(book.id);\n return cache;\n}\n\n/** Serve approved cached CSS/JSON, optionally public. ETags are derived from\n * immutable dependency provenance, never wall-clock timestamps. */\nexport async function handleTokens(\n db: Parameters<typeof loadBook>[0],\n req: Request,\n bookId: string,\n which: \"tokens.css\" | \"tokens.json\",\n actor: BrandActor | null,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = actor === null\n ? await loadBook(db, bookId)\n : await loadMemberBook(db, bookId, actor.id);\n const cache = await approvedCache(db, book);\n const light = cache.light as BrandTokens;\n const dark = cache.dark as BrandTokens;\n if (which === \"tokens.json\") return json({ light, dark });\n const etag = `\"brand-tokens-${book.activationRevision}-${cache.sourceDigest.slice(7)}\"`;\n if (\n req.headers.get(\"if-none-match\")\n ?.split(\",\")\n .map((value) => value.trim())\n .includes(etag)\n ) return new Response(null, { status: 304, headers: { etag } });\n return new Response(renderTokensCss(light, { dark }), {\n status: 200,\n headers: {\n \"content-type\": \"text/css; charset=utf-8\",\n \"cache-control\": \"public, max-age=0, must-revalidate\",\n etag,\n },\n });\n}\n","import { BrandInputError, BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport { linkedAsset } from \"./asset-query\";\nimport {\n json,\n loadMemberBook,\n type BrandRouteCtx,\n} from \"./http\";\n\n/** Same aggregate 4.5 MiB inline-media lane used by Brand and Discussion. */\nexport const MAX_DISCUSSION_ASSET_BYTES = 4_718_592;\nconst SIGN_TTL_SECONDS = 30;\nconst TYPES = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/pdf\",\n]);\n\nconst bare = (value: string | null): string =>\n (value?.split(\";\", 1)[0] ?? \"\").trim().toLowerCase();\n\nconst starts = (bytes: Uint8Array, expected: readonly number[]): boolean =>\n expected.every((value, index) => bytes[index] === value);\n\nfunction magicMatches(contentType: string, bytes: Uint8Array): boolean {\n if (contentType === \"image/png\") {\n return starts(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n }\n if (contentType === \"image/jpeg\") {\n return starts(bytes, [0xff, 0xd8, 0xff]);\n }\n const prefix = new TextDecoder().decode(bytes.subarray(0, 16));\n if (contentType === \"image/gif\") {\n return prefix.startsWith(\"GIF87a\") || prefix.startsWith(\"GIF89a\");\n }\n if (contentType === \"image/webp\") {\n return prefix.startsWith(\"RIFF\") && prefix.slice(8, 12) === \"WEBP\";\n }\n return contentType === \"application/pdf\" && prefix.startsWith(\"%PDF-\");\n}\n\nasync function boundedBytes(\n response: Response,\n max: number,\n): Promise<Uint8Array | null> {\n const length = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(length) && length > max) return null;\n if (!response.body) return new Uint8Array();\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const next = await reader.read();\n if (next.done) break;\n total += next.value.byteLength;\n if (total > max) {\n await reader.cancel();\n return null;\n }\n chunks.push(next.value);\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return out;\n}\n\nasync function digest(bytes: Uint8Array): Promise<string> {\n const value = await crypto.subtle.digest(\"SHA-256\", bytes.slice().buffer);\n return `sha256:${[...new Uint8Array(value)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n\nfunction exactAsset(\n beforeBook: BrandBook,\n before: BrandAsset,\n afterBook: BrandBook,\n after: BrandAsset,\n): boolean {\n return afterBook.id === beforeBook.id &&\n after.id === before.id &&\n after.bookId === before.bookId &&\n after.status === \"live\" &&\n after.path === before.path &&\n after.storageObjectId === before.storageObjectId &&\n after.contentDigest === before.contentDigest &&\n after.contentType === before.contentType &&\n after.size === before.size;\n}\n\nfunction safeSignedUrl(value: string): URL | null {\n try {\n const url = new URL(value);\n return value.length <= 4_096 &&\n url.protocol === \"https:\" &&\n !url.username &&\n !url.password\n ? url\n : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read one exact private Brand asset through a product-owned signed fetch.\n * The URL is derived from the linked row, used once, and never returned.\n */\nexport async function handleBrandDiscussionAsset(\n ctx: BrandRouteCtx,\n req: Request,\n target: { bookId: string; resourceId: string },\n): Promise<Response> {\n const beforeBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);\n const before = await linkedAsset(ctx, beforeBook, target.resourceId);\n const contentType = bare(before.contentType);\n if (!TYPES.has(contentType)) {\n return json({ error: \"asset content type is not viewable\" }, 415);\n }\n if (before.size < 1 || before.size > MAX_DISCUSSION_ASSET_BYTES) {\n return json({ error: \"asset exceeds the discussion media limit\" }, 413);\n }\n const signed = safeSignedUrl(\n await ctx.db.storage.sign(before.path, SIGN_TTL_SECONDS),\n );\n if (!signed) throw new BrandInputError(\"private asset signing failed\");\n // Through a local: a property call would hand `ctx` to fetch as its receiver.\n const fetchPrivateAsset = ctx.fetchPrivateAsset;\n const response = await fetchPrivateAsset(signed, {\n headers: { accept: contentType },\n redirect: \"manual\",\n signal: req.signal,\n });\n if (!response.ok || response.type === \"opaqueredirect\") {\n throw new BrandNotFoundError(`asset ${before.id}`);\n }\n const served = bare(response.headers.get(\"content-type\"));\n if (\n served === \"image/svg+xml\" ||\n (served && served !== \"application/octet-stream\" && served !== contentType)\n ) {\n return json({ error: \"asset content type is inconsistent\" }, 415);\n }\n const bytes = await boundedBytes(response, MAX_DISCUSSION_ASSET_BYTES);\n if (\n !bytes ||\n bytes.byteLength !== before.size ||\n !magicMatches(contentType, bytes) ||\n await digest(bytes) !== before.contentDigest\n ) {\n return json({ error: \"asset bytes failed validation\" }, 422);\n }\n const afterBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);\n const after = await linkedAsset(ctx, afterBook, target.resourceId);\n if (!exactAsset(beforeBook, before, afterBook, after)) {\n return json({ error: \"asset changed during inspection\" }, 409);\n }\n return json({\n asset: {\n reference: { kind: \"brand:asset\", id: `${before.bookId}/${before.id}` },\n contentType,\n byteLength: bytes.byteLength,\n data: base64(bytes),\n taint: \"untrusted_project_material\",\n },\n }, 200, {\n \"cache-control\": \"private, no-store\",\n \"x-content-type-options\": \"nosniff\",\n });\n}\n\nfunction base64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let index = 0; index < bytes.length; index += 0x2000) {\n binary += String.fromCharCode(...bytes.subarray(index, index + 0x2000));\n }\n return btoa(binary);\n}\n","import { BRAND_NS } from \"../constants\";\nimport {\n brandDiscussionReferenceHref,\n brandDiscussionReferenceId,\n parseBrandDiscussionReference,\n type BrandDiscussionReference,\n type BrandDiscussionReferenceKind,\n type BrandDiscussionSwatch,\n type BrandDiscussionReferenceTarget,\n} from \"../discussion-reference\";\nimport type {\n BrandApprovalReceipt,\n BrandAsset,\n BrandBook,\n BrandPalette,\n BrandProposal,\n} from \"../types\";\nimport { assertSwatches } from \"../validate\";\nimport { handleBrandDiscussionAsset } from \"./discussion-asset\";\nimport { isMember, json, loadMemberBook, methodNotAllowed, type BrandRouteCtx } from \"./http\";\n\ntype Child = BrandAsset | BrandPalette | BrandProposal | BrandApprovalReceipt;\n\nconst capLimit = (raw: string | null): number => {\n const parsed = Number(raw ?? 20);\n return Number.isInteger(parsed) ? Math.max(1, Math.min(parsed, 20)) : 20;\n};\n\nconst targetFromQuery = (url: URL): BrandDiscussionReferenceTarget | null => {\n const kind = url.searchParams.get(\"kind\");\n const id = url.searchParams.get(\"id\");\n if (!kind && !id) return null;\n if (!kind || !id) return null;\n const value = new URL(\"https://brand.invalid\");\n value.searchParams.set(\"odla-ref\", `${kind}/${id}`);\n return parseBrandDiscussionReference(value);\n};\n\nconst childNamespace = (\n kind: BrandDiscussionReferenceKind,\n): string | null => ({\n \"brand:asset\": BRAND_NS.asset,\n \"brand:palette\": BRAND_NS.palette,\n \"brand:proposal\": BRAND_NS.proposal,\n \"brand:receipt\": BRAND_NS.approvalReceipt,\n} as Partial<Record<BrandDiscussionReferenceKind, string>>)[kind] ?? null;\n\nconst childTarget = (\n kind: Exclude<BrandDiscussionReferenceKind, \"brand:book\">,\n row: Child,\n): BrandDiscussionReferenceTarget => ({\n kind,\n bookId: row.bookId,\n resourceId: row.id,\n});\n\nconst projection = (\n req: Request,\n ctx: BrandRouteCtx,\n book: BrandBook,\n target: BrandDiscussionReferenceTarget,\n row: BrandBook | Child,\n): BrandDiscussionReference => {\n let label = book.name;\n let hint = `${book.status} brand book`;\n let summary = `${book.name} brand book`;\n let status: string = book.status;\n let destination = \"Brand Studio · Brand book\";\n let swatches: BrandDiscussionSwatch[] | undefined;\n if (target.kind === \"brand:asset\") {\n const asset = row as BrandAsset;\n label = asset.title?.trim() || `${asset.kind} asset`;\n hint = `${book.name} · ${asset.status}`;\n summary = `${asset.kind} source asset in ${book.name}`;\n status = asset.status;\n destination = \"Brand Studio · Conversation\";\n } else if (target.kind === \"brand:palette\") {\n const palette = row as BrandPalette;\n swatches = assertSwatches(palette.swatches).map((swatch) => ({\n role: swatch.role,\n hex: swatch.hex,\n ...(swatch.name ? { name: swatch.name } : {}),\n }));\n label = palette.name;\n hint = `${book.name} · ${palette.status} palette`;\n summary = `${palette.swatches.length}-color palette in ${book.name}`;\n status = palette.status;\n destination = \"Brand Studio · Review changes\";\n } else if (target.kind === \"brand:proposal\") {\n const proposal = row as BrandProposal;\n label = `${proposal.kind} proposal`;\n hint = `${book.name} · ${proposal.status}`;\n summary = proposal.rationale;\n status = proposal.status;\n destination = \"Brand Studio · Review changes\";\n } else if (target.kind === \"brand:receipt\") {\n const receipt = row as BrandApprovalReceipt;\n label = `${receipt.resolution} ${receipt.reviewedProposal.kind} change`;\n hint = `${book.name} · approval receipt`;\n summary = `${receipt.resolution} ${receipt.reviewedProposal.kind} decision`;\n status = receipt.resolution;\n destination = \"Brand Studio · Review changes\";\n }\n return {\n kind: target.kind,\n id: brandDiscussionReferenceId(target),\n label,\n hint,\n summary,\n status,\n destination,\n href: brandDiscussionReferenceHref(\n new URL(req.url),\n target,\n ctx.discussionBasePath,\n ),\n ...(swatches ? { swatches } : {}),\n };\n};\n\nasync function exact(\n ctx: BrandRouteCtx,\n req: Request,\n target: BrandDiscussionReferenceTarget,\n): Promise<BrandDiscussionReference[]> {\n const book = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id)\n .catch(() => null);\n if (!book) return [];\n if (target.kind === \"brand:book\") {\n return [projection(req, ctx, book, target, book)];\n }\n const namespace = childNamespace(target.kind);\n if (!namespace || !target.resourceId) return [];\n const result = await ctx.db.query({\n [namespace]: {\n $: { where: { id: target.resourceId }, limit: 1 },\n },\n });\n const row = (result[namespace] ?? [])[0] as Child | undefined;\n if (\n !row ||\n row.bookId !== book.id ||\n (target.kind === \"brand:asset\" && (row as BrandAsset).status !== \"live\")\n ) return [];\n return [projection(req, ctx, book, target, row)];\n}\n\nconst matches = (\n item: BrandDiscussionReference,\n needle: string,\n): boolean => !needle ||\n `${item.label}\\n${item.hint}\\n${item.id}`.toLowerCase().includes(needle);\n\nasync function search(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n): Promise<BrandDiscussionReference[]> {\n const result = await ctx.db.query({\n [BRAND_NS.book]: { $: { order: { updatedAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.asset]: { $: { order: { createdAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.palette]: { $: { order: { updatedAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.proposal]: { $: { order: { createdAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.approvalReceipt]: {\n $: { order: { createdAt: \"desc\" }, limit: 100 },\n },\n });\n const books = ((result[BRAND_NS.book] ?? []) as unknown as BrandBook[])\n .filter((book) => isMember(book, ctx.actor.id));\n const bookById = new Map(books.map((book) => [book.id, book]));\n const items = books.map((book) =>\n projection(req, ctx, book, { kind: \"brand:book\", bookId: book.id }, book)\n );\n const append = (\n kind: Exclude<BrandDiscussionReferenceKind, \"brand:book\">,\n rows: unknown[],\n ) => {\n for (const row of rows as Child[]) {\n const book = bookById.get(row.bookId);\n if (\n !book ||\n (kind === \"brand:asset\" && (row as BrandAsset).status !== \"live\")\n ) continue;\n items.push(projection(req, ctx, book, childTarget(kind, row), row));\n }\n };\n append(\"brand:asset\", result[BRAND_NS.asset] ?? []);\n append(\"brand:palette\", result[BRAND_NS.palette] ?? []);\n append(\"brand:proposal\", result[BRAND_NS.proposal] ?? []);\n append(\"brand:receipt\", result[BRAND_NS.approvalReceipt] ?? []);\n const needle = (url.searchParams.get(\"q\") ?? \"\").trim().toLowerCase()\n .slice(0, 120);\n return items.filter((item) => matches(item, needle))\n .slice(0, capLimit(url.searchParams.get(\"limit\")));\n}\n\n/**\n * Authenticated product-owned Brand reference search and exact resolution.\n * Membership and row existence are checked here, never inferred by Registry.\n */\nexport async function handleBrandDiscussionReferences(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const inspect = url.searchParams.get(\"inspect\");\n const kind = url.searchParams.get(\"kind\");\n const id = url.searchParams.get(\"id\");\n if ((kind && !id) || (!kind && id)) return json({ error: \"kind and id must be paired\" }, 400);\n const target = targetFromQuery(url);\n if ((kind || id) && !target) return json({ items: [] });\n if (inspect === \"asset-content\") {\n const allowed = new Set([\"inspect\", \"kind\", \"id\"]);\n if (\n [...url.searchParams.keys()].some((key) => !allowed.has(key)) ||\n target?.kind !== \"brand:asset\" ||\n !target.resourceId\n ) return json({ error: \"exact brand asset kind and id required\" }, 400);\n return handleBrandDiscussionAsset(ctx, req, {\n bookId: target.bookId,\n resourceId: target.resourceId,\n });\n }\n if (inspect !== null && inspect !== \"1\") {\n return json({ error: \"invalid inspection mode\" }, 400);\n }\n return json({\n items: target ? await exact(ctx, req, target) : await search(ctx, req, url),\n });\n}\n","// The mountable route factory (crm's createCrmRoutes contract): the host\n// worker composes it —\n// const brandRoutes = createBrandRoutes({ db, authorize, … });\n// return (await brandRoutes(request)) ?? next(request);\n// — keeping full ownership of auth (`authorize`) and the admin db key.\nimport { handleAssetContent, handleAssetItem, handleAssetsRoot } from \"./assets\";\nimport { handleBookItem, handleBookMembers, handleBooksRoot } from \"./books\";\nimport { handleDesignDigest, handleDesignPreview } from \"./design-preview\";\nimport { errorResponse, json, type BrandRouteCtx, type BrandRouteOpts } from \"./http\";\nimport { handleProposalResolution } from \"./proposals\";\nimport { handleTokens } from \"./tokens\";\nimport { handleBrandDiscussionReferences } from \"./discussion-references\";\n\nexport type { BrandRouteCtx, BrandRouteOpts } from \"./http\";\nexport { proposalReviewSnapshot } from \"./proposal-input\";\n\ntype TokensFile = \"tokens.css\" | \"tokens.json\";\n\n/** `/books/:id/tokens.css|json` recognizer — the only publicTokens-eligible paths. */\nconst tokensFile = (seg: string[]): TokensFile | null =>\n seg.length === 3 && seg[0] === \"books\" && (seg[2] === \"tokens.css\" || seg[2] === \"tokens.json\")\n ? (seg[2] as TokensFile)\n : null;\n\nasync function route(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n seg: string[],\n): Promise<Response | null> {\n const [head, id, sub, subId, action] = seg;\n if (head === \"discussion-references\" && seg.length === 1)\n return handleBrandDiscussionReferences(ctx, req, url);\n if (head !== \"books\") return null;\n if (seg.length === 1) return handleBooksRoot(ctx, req);\n if (seg.length === 2) return handleBookItem(ctx, req, id!);\n if (seg.length === 3 && sub === \"members\") return handleBookMembers(ctx, req, id!);\n if (sub === \"assets\") {\n if (seg.length === 3) return handleAssetsRoot(ctx, req, id!);\n if (seg.length === 4) return handleAssetItem(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"content\")\n return handleAssetContent(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"preview\")\n return handleDesignPreview(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"design\")\n return handleDesignDigest(ctx, req, id!, subId!);\n return null;\n }\n if (sub === \"proposals\" && seg.length === 5 && action === \"resolve\")\n return handleProposalResolution(ctx, req, id!, subId!);\n const file = tokensFile(seg);\n if (file) return handleTokens(ctx.db, req, id!, file, ctx.actor);\n return null;\n}\n\n/**\n * Build the brand fetch handler. Returns `null` for requests outside\n * `basePath` (default `/api/brand`) so the host worker falls through to its\n * own routes; inside it, every route requires `authorize` to resolve an\n * actor (401 otherwise) EXCEPT the two tokens routes when `publicTokens` is\n * true — compiled tokens are the one intentionally publishable surface.\n * Domain errors map to 400/404 JSON; anything unexpected is an opaque 500.\n */\nexport function createBrandRoutes(options: BrandRouteOpts): (req: Request) => Promise<Response | null> {\n const basePath = options.basePath ?? \"/api/brand\";\n const publicTokens = options.publicTokens === true;\n const base = {\n db: options.db,\n appId: options.appId,\n authorizeCapability: options.authorizeCapability,\n consumeHumanExact: options.consumeHumanExact,\n verifySourceAssetSnapshot: options.verifySourceAssetSnapshot,\n now: options.now ?? Date.now,\n newId: options.newId ?? (() => crypto.randomUUID()),\n maxUploadBytes: options.maxUploadBytes ?? 8 * 1024 * 1024,\n discussionBasePath: options.discussionBasePath ?? \"/\",\n // Bound: this is stored on the context and invoked from route handlers,\n // where a property call would set the receiver to that context and\n // Cloudflare's fetch refuses a foreign receiver (\"Illegal invocation\").\n fetchPrivateAsset: options.fetchPrivateAsset ??\n globalThis.fetch.bind(globalThis),\n previewFrameAncestors: options.previewFrameAncestors ?? [\"'self'\"],\n };\n return async (req: Request): Promise<Response | null> => {\n const url = new URL(req.url);\n if (url.pathname !== basePath && !url.pathname.startsWith(`${basePath}/`)) return null;\n const seg = url.pathname.slice(basePath.length).split(\"/\").filter(Boolean);\n try {\n const file = tokensFile(seg);\n if (publicTokens && file) return await handleTokens(base.db, req, seg[1]!, file, null);\n const actor = await (\n seg[0] === \"discussion-references\"\n ? options.authorizeDiscussionReferences ?? options.authorize\n : options.authorize\n )(req);\n if (!actor) return json({ error: \"unauthorized\" }, 401);\n return (await route({ ...base, actor }, req, url, seg)) ??\n json({ error: \"not found\" }, 404);\n } catch (error) {\n return errorResponse(error);\n }\n };\n}\n","import { BRAND_NS } from \"./constants\";\nimport type { BrandAsset, BrandBook, BrandDb } from \"./types\";\n\nconst MAX_MESSAGE_ASSETS = 12;\n\nfunction candidateAssetIds(row: Record<string, unknown>): string[] {\n const standard = Array.isArray(row.attachments)\n ? row.attachments.flatMap((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return [];\n const id = (value as Record<string, unknown>).id;\n return typeof id === \"string\" && id.length > 0 && id.length <= 200\n ? [id]\n : [];\n })\n : [];\n // Compatibility for rows written before standard Chat attachments were\n // included in the initial message transaction.\n const legacy = Array.isArray(row.assetIds)\n ? row.assetIds.filter((value): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= 200)\n : [];\n return [...new Set([...standard, ...legacy])].slice(0, MAX_MESSAGE_ASSETS);\n}\n\n/** Reload message attachment ids against the exact live linked Brand book. */\nexport async function attachedBrandAssetIds(\n db: BrandDb,\n book: BrandBook,\n row: Record<string, unknown>,\n): Promise<string[]> {\n const candidates = candidateAssetIds(row);\n const assets = await Promise.all(candidates.map(async (id) => {\n const result = await db.query({\n [BRAND_NS.asset]: {\n $: { where: { id, bookId: book.id, status: \"live\" }, limit: 2 },\n book: { $: { limit: 2 } },\n },\n });\n const rows = result[BRAND_NS.asset] ?? [];\n if (rows.length !== 1) return null;\n const asset = rows[0] as BrandAsset & { book?: Array<{ id: string }> };\n return asset.id === id &&\n asset.bookId === book.id &&\n asset.status === \"live\" &&\n asset.deletedAt === undefined &&\n Array.isArray(asset.book) &&\n asset.book.length === 1 &&\n asset.book[0]?.id === book.id\n ? id\n : null;\n }));\n return assets.filter((id): id is string => id !== null);\n}\n","// Commit-trigger config brand installs into odla-db (POST to\n// `/app/:id/admin/triggers`), mirroring @odla-ai/chat's botTrigger: the\n// @odla/server commit hook fires on matching human-authored chat-message\n// writes and dispatches to the host's agent worker with `skill: \"brand\"`.\n// Two deployment modes, both this one builder:\n// - global mention-gated: one bot, `mention: \"@brand\"`, no `channels`;\n// - per-book channel-scoped: `channels: [book.channelId]`, no mention.\n\n/** The odla-db namespace chat messages live in.\n * PROVENANCE: @odla-ai/chat `CHAT_NS.message` (packages/chat/src/constants.ts)\n * — duplicated as a local const because this package is zero-dep and the wire\n * value is a stable contract, not an implementation detail. */\nexport const CHAT_MESSAGE_NS = \"chat_message\";\n\n/** Matches @odla/server's `Trigger` (the exact JSON POSTed to\n * `/app/:id/admin/triggers`) — the same wire shape as chat's `ChatTrigger`. */\nexport interface BrandTrigger {\n id: string;\n watch: { ns: string; on: \"create\" | \"update\" };\n when?: string;\n runAs: { agentId: string; persona: string };\n skill: string;\n maxDepth?: number;\n channels?: string[];\n validate?: string;\n}\n\n/** Options for {@link brandBotTrigger}. */\nexport interface BrandBotTriggerOpts {\n /** Trigger id (unique per app). */\n id: string;\n /** The bot's agent id — must be in each target book's `memberIds` roster. */\n agentId: string;\n /** Persona name the dispatching worker runs. */\n persona: string;\n /** Fire only on messages mentioning this handle, e.g. \"@brand\". */\n mention?: string;\n /** Extra CEL over the new message row, ANDed with the built-in guards. */\n when?: string;\n /** Restrict to specific channel ids (the per-book mode). */\n channels?: string[];\n /** Watched write kind (default \"create\"). */\n on?: \"create\" | \"update\";\n}\n\n/** Escape a value for embedding inside a CEL double-quoted string literal —\n * copied verbatim from @odla-ai/chat (packages/chat/src/triggers.ts):\n * `mention` is matched as literal text, so a stray quote or backslash must\n * not break out of the literal into CEL syntax. */\nconst celString = (value: string): string => value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n\n/**\n * Build a trigger that runs the brand agent on human chat messages\n * (optionally @-mentions, optionally channel-scoped): chat's `botTrigger`\n * shape with `skill: \"brand\"` and `maxDepth: 1` so a bot reply can never\n * re-trigger a bot.\n */\nexport function brandBotTrigger(opts: BrandBotTriggerOpts): BrandTrigger {\n const clauses = ['data.authorKind == \"human\"'];\n if (opts.mention) clauses.push(`data.body.contains(\"${celString(opts.mention)}\")`);\n // `when` is documented as caller-authored CEL, so it is intentionally not escaped.\n if (opts.when) clauses.push(`(${opts.when})`);\n return {\n id: opts.id,\n watch: { ns: CHAT_MESSAGE_NS, on: opts.on ?? \"create\" },\n when: clauses.join(\" && \"),\n runAs: { agentId: opts.agentId, persona: opts.persona },\n skill: \"brand\",\n maxDepth: 1,\n ...(opts.channels ? { channels: opts.channels } : {}),\n };\n}\n","// Host dispatch for one Brand chat turn. The service DB resolves the book;\n// tools receive a separate rules-scoped DB bound to the exact runAs agent.\nimport type { ImageBlock, OracleContentBlock } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"./constants\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandNotFoundError,\n} from \"./errors\";\nimport { attachedBrandAssetIds } from \"./dispatch-assets\";\nimport { createBrandPersona, supportsBrandVision } from \"./skill/persona\";\nimport type { BrandSkillSelf } from \"./skill/skill\";\nimport { CHAT_MESSAGE_NS } from \"./triggers\";\nimport type { BrandBook, BrandDb } from \"./types\";\nimport type { BrandDispatchBody, BrandDispatchDeps } from \"./dispatch-types\";\nimport type { BrandPrincipalProjection } from \"./skill/agent-types\";\n\nexport type { BrandDispatchBody, BrandDispatchDeps } from \"./dispatch-types\";\nexport { attachedBrandAssetIds } from \"./dispatch-assets\";\n\n/** Strict-enough structural parse for the signed host dispatch envelope. */\nexport function parseBrandDispatch(raw: unknown): BrandDispatchBody | null {\n if (!raw || typeof raw !== \"object\") return null;\n const body = raw as Record<string, unknown>;\n const trigger = body.trigger as {\n id?: unknown;\n skill?: unknown;\n maxDepth?: unknown;\n runAs?: { agentId?: unknown; persona?: unknown };\n } | undefined;\n const event = body.event as {\n ns?: unknown;\n id?: unknown;\n row?: unknown;\n } | undefined;\n if (\n body.v !== 2 ||\n typeof body.appId !== \"string\" ||\n !body.appId ||\n typeof body.appIncarnation !== \"string\" ||\n !/^[0-9a-f]{32}$/.test(body.appIncarnation) ||\n typeof body.jobId !== \"string\" ||\n !body.jobId ||\n !trigger ||\n typeof trigger.runAs?.agentId !== \"string\" ||\n !trigger.runAs.agentId ||\n typeof trigger.runAs.persona !== \"string\" ||\n !event ||\n typeof event.id !== \"string\" ||\n !event.row ||\n typeof event.row !== \"object\" ||\n Array.isArray(event.row)\n ) return null;\n return {\n v: 2,\n appId: body.appId,\n appIncarnation: body.appIncarnation,\n jobId: body.jobId,\n trigger: {\n id: typeof trigger.id === \"string\" ? trigger.id : \"\",\n skill: typeof trigger.skill === \"string\" ? trigger.skill : \"\",\n runAs: {\n agentId: trigger.runAs.agentId,\n persona: trigger.runAs.persona,\n },\n ...(typeof trigger.maxDepth === \"number\"\n ? { maxDepth: trigger.maxDepth }\n : {}),\n },\n event: {\n ns: typeof event.ns === \"string\" ? event.ns : CHAT_MESSAGE_NS,\n id: event.id,\n row: event.row as Record<string, unknown>,\n },\n };\n}\n\n/** Channel ids are unique by schema, but ambiguity still fails closed if a\n * legacy/corrupt store returns more than one row. */\nexport async function bookForChannel(\n db: BrandDb,\n channelId: string,\n): Promise<BrandBook | null> {\n if (!channelId) return null;\n const result = await db.query({\n [BRAND_NS.book]: { $: { where: { channelId } } },\n });\n const books = (result[BRAND_NS.book] ?? []) as BrandBook[];\n if (books.length > 1)\n throw new BrandConflictError(`multiple brand books claim channel ${channelId}`);\n return books[0] ?? null;\n}\n\n/** Assemble the conversational request. Attachments remain supported as a\n * pure helper, but secure dispatch does not pass signed/private URLs here. */\nexport function brandInputFor(\n body: BrandDispatchBody,\n attachments?: ImageBlock[],\n author?: BrandPrincipalProjection,\n attachedAssetIds: readonly string[] = [],\n): string | OracleContentBlock[] {\n const row = body.event.row;\n const actor = author\n ? `${author.displayName} (${author.kind}` +\n `${author.managerDisplayName\n ? `, managed by ${author.managerDisplayName}`\n : \"\"})`\n : row.authorKind === \"bot\"\n ? \"a managed agent\"\n : \"a participant\";\n const prompt =\n `A new message arrived in this brand book's channel from ` +\n `${actor}: ` +\n `\"${String(row.body ?? \"\")}\". Ground yourself first (read_brand_book, ` +\n \"list_assets), then move the work forward. Study real material, justify \" +\n \"colors, and park exact proposals. A human approves in the Brand surface; \" +\n \"acceptance applies the reviewed facet and recompiles dependent tokens. \" +\n (attachedAssetIds.length > 0\n ? `This message atomically attached Brand asset id${attachedAssetIds.length === 1 ? \"\" : \"s\"} ` +\n `${attachedAssetIds.join(\", \")}; use view_asset on those exact ids before drawing conclusions. `\n : \"\") +\n \"Keep any chat reply concise.\";\n return attachments?.length\n ? [...attachments, { type: \"text\", text: prompt }]\n : prompt;\n}\n\n/** Preflight exact app/skill/channel/roster/live brand.read before the model\n * is invoked. Every tool revalidates its own read/edit capability as well. */\nexport async function dispatchBrandTurn(\n deps: BrandDispatchDeps,\n body: BrandDispatchBody,\n): Promise<{ finalText: string; durableOutcome: boolean }> {\n if (\n body.appId !== deps.appId ||\n body.trigger.skill !== \"brand\" ||\n body.event.ns !== CHAT_MESSAGE_NS\n ) throw new BrandForbiddenError(\"foreign or non-brand dispatch\");\n const channelId = String(body.event.row.channelId ?? \"\");\n const book = await bookForChannel(deps.db, channelId);\n if (!book)\n throw new BrandNotFoundError(\n `brand book for channel ${channelId || \"(missing channelId)\"}`,\n );\n const agentId = body.trigger.runAs.agentId;\n if (!book.memberIds.includes(agentId))\n throw new BrandNotFoundError(`brand book for channel ${channelId}`);\n const read = await deps.authorizeCapability({\n agentId,\n bookId: book.id,\n capability: \"brand.read\",\n });\n if (!read || read.capability !== \"brand.read\" || !read.authorityRef)\n throw new BrandForbiddenError(\"agent lacks live brand.read\");\n const authorId =\n typeof body.event.row.authorId === \"string\"\n ? body.event.row.authorId\n : \"\";\n const authors = authorId\n ? await deps.resolvePrincipals({\n requesterAgentId: agentId,\n bookId: book.id,\n principalIds: [authorId],\n })\n : [];\n const author = authors.find((candidate) => candidate.id === authorId);\n const attachedAssetIds = await attachedBrandAssetIds(\n deps.db,\n book,\n body.event.row,\n );\n const runtime = await deps.agentRuntimeFor({\n appId: body.appId,\n agentId,\n bookId: book.id,\n triggerId: body.trigger.id,\n eventId: body.event.id,\n jobId: body.jobId,\n });\n if (\n !runtime.credentialRef ||\n !runtime.jobId ||\n runtime.jobId !== body.jobId\n )\n throw new BrandForbiddenError(\"agent data credential is not bound\");\n let durableOutcome = false;\n const bridge = {\n ...runtime.bridge,\n createProposal: async (\n input: Parameters<typeof runtime.bridge.createProposal>[0],\n ) => {\n const proposal = await runtime.bridge.createProposal(input);\n durableOutcome = true;\n return proposal;\n },\n recordAssetAnalysis: async (\n input: Parameters<typeof runtime.bridge.recordAssetAnalysis>[0],\n ) => {\n const asset = await runtime.bridge.recordAssetAnalysis(input);\n durableOutcome = true;\n return asset;\n },\n };\n\n const visionInToolResults = supportsBrandVision(\n deps.catalog?.[deps.model],\n );\n const self: BrandSkillSelf = {\n selfId: agentId,\n kind: \"bot\",\n displayName: body.trigger.runAs.persona,\n };\n const persona = createBrandPersona({\n model: deps.model,\n brand: {\n db: runtime.db,\n bookId: book.id,\n self,\n agentDbBinding: {\n principalId: agentId,\n credentialRef: runtime.credentialRef,\n },\n agentJobId: runtime.jobId,\n agentBridge: bridge,\n authorizeCapability: deps.authorizeCapability,\n resolvePrincipals: deps.resolvePrincipals,\n visionInToolResults,\n ...(deps.newId ? { newId: deps.newId } : {}),\n },\n skills: deps.chatSkillFor\n ? [deps.chatSkillFor(channelId, self)]\n : [],\n });\n const run = await deps.runAgent(deps.inference, persona, {\n // Models without tool-result vision receive no raw/signed fallback URL.\n input: brandInputFor(body, undefined, author, attachedAssetIds),\n });\n return { finalText: run.finalText, durableOutcome };\n}\n","// The integration descriptor: documentation-as-data for the brand capability,\n// following the crm/chat pattern — what installing @odla-ai/brand into an app\n// means (schema, deny-all rules, per-bot triggers, worker mount), described\n// but not performed. The base shapes are inlined so the zero-dependency\n// package does not depend on the CLI; the CLI consumes descriptors\n// structurally from odla.config.mjs.\nimport { BRAND_SCHEMA, type SerializedSchema } from \"./schema\";\nimport { brandRules, type BrandRules } from \"./rules\";\nimport type { BrandTrigger } from \"./triggers\";\nimport {\n BRAND_AGENT_PROFILE,\n type BrandAgentProfile,\n} from \"./agent-profile\";\n\n/** One owner-facing setting the integration exposes (crm's shape). */\nexport interface IntegrationSetting {\n key: string;\n description: string;\n public: boolean;\n pattern?: string;\n perEnv: boolean;\n source: string;\n}\n\n/** One vault secret the integration needs (brand core needs none). */\nexport interface IntegrationSecret {\n key: string;\n description: string;\n pattern?: string;\n vault: boolean;\n}\n\n/** Human / CLI / doctor provisioning steps, documentation-as-data. */\nexport interface IntegrationProvision {\n human: string[];\n cli: string[];\n doctor: string[];\n}\n\n/** Unauthenticated route check run by `odla-ai smoke`. */\nexport interface BrandIntegrationProbe {\n path: string;\n expectedStatus: number;\n}\n\n/** The brand descriptor shape: the shared base plus the schema + rules\n * provisioning installs and the (app-supplied) bot triggers. */\nexport interface BrandIntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n settings: IntegrationSetting[];\n secrets: IntegrationSecret[];\n /** The schema to POST at /app/:id/schema. */\n schema: SerializedSchema;\n /** The default-deny rules to install at /app/:id/admin/rules (merged with existing). */\n rules: BrandRules;\n /** Commit triggers to register at /app/:id/admin/triggers (per-bot; app-supplied). */\n triggers: BrandTrigger[];\n /** Least-privilege agent capabilities and semantic-operation boundary. */\n agentProfile: BrandAgentProfile;\n probes?: BrandIntegrationProbe[];\n provision: IntegrationProvision;\n}\n\n/**\n * The static documentation descriptor for @odla-ai/brand. Data only: it\n * describes what installing the brand capability means — push\n * {@link BRAND_SCHEMA}, install the default-deny `brandRules()`, register\n * `brandBotTrigger`s (app-supplied, in either the global mention-gated or the\n * per-book channel-scoped mode), mount `createBrandRoutes` in the app worker\n * — and performs none of it. Use {@link createBrandIntegration} in\n * `odla.config.mjs` to add the live route probe the CLI can execute.\n */\nexport const brandIntegration: BrandIntegrationDescriptor = {\n id: \"brand\",\n title: \"Brand books (assets, palettes, proposals, design tokens)\",\n npm: \"@odla-ai/brand\",\n settings: [\n {\n key: \"basePath\",\n description: 'Route mount point the app worker serves brand under. Default \"/api/brand\".',\n public: true,\n perEnv: false,\n source: \"createBrandRoutes({ basePath }) in the app worker\",\n },\n {\n key: \"publicTokens\",\n description:\n \"Serve GET /books/:id/tokens.css and tokens.json without authorization (compiled tokens \" +\n \"only — books and assets always authorize). Default false.\",\n public: true,\n perEnv: false,\n source: \"createBrandRoutes({ publicTokens }) in the app worker\",\n },\n ],\n secrets: [],\n schema: BRAND_SCHEMA,\n rules: brandRules(),\n triggers: [],\n agentProfile: BRAND_AGENT_PROFILE,\n provision: {\n human: [\n \"Configure direct Clerk human approval through authorizeCapability + consumeHumanExact; delegated, machine, and agent principals must not resolve proposals.\",\n \"Choose the trigger mode: one global mention-gated bot (brandBotTrigger({ mention: \\\"@brand\\\" }), no channels) or per-book channel-scoped bots (channels: [book.channelId], no mention).\",\n \"Pick a model where supportsBrandVision(catalog[model]) is true for in-conversation asset viewing; secure dispatch never falls back to signed or persistent asset URLs.\",\n \"Decide whether compiled tokens are public (publicTokens serves tokens.css/tokens.json unauthenticated).\",\n ],\n cli: [\n \"POST BRAND_SCHEMA to /app/:id/schema.\",\n \"Install brandRules() at /app/:id/admin/rules (merged with the app's existing rules).\",\n \"Register a brandBotTrigger(...) per bot at /app/:id/admin/triggers — global mention-gated, or channel-scoped per book.\",\n \"Seed the bot's agent id into each brand_book.memberIds roster (audienceFanoutOps covers existing child rows).\",\n \"Issue the bot brand.read + brand.edit and expose only BRAND_AGENT_PROFILE semantic operations; deny raw brand_* writes and raw file operations.\",\n \"Provision private file signing and verifySourceAssetSnapshot; never expose an admin credential or persistent asset URL to the agent.\",\n ],\n doctor: [\n \"All six brand_* namespaces have rules installed; raw browser/agent writes are denied and child reads use current linked-book membership.\",\n \"The agent runtime matches BRAND_AGENT_PROFILE: brand.read/edit only, semantic operations only, no raw brand_* or file access.\",\n \"Proposal decisions consume a direct-human exact brand.approve authority use and persist one guarded brand_approval_receipt.\",\n \"Private source assets are signed briefly and verifySourceAssetSnapshot revalidates path, ETag, size, content type, and digest before approval.\",\n \"brand_book.id/slug, brand_section.key, and the other mirrored id attrs are unique.\",\n \"Each registered trigger's agent id is present in its target books' memberIds rosters.\",\n \"Books with channelId set point at real chat channels when @odla-ai/chat is installed.\",\n ],\n },\n};\n\n/** Options for {@link createBrandIntegration}. */\nexport interface CreateBrandIntegrationOptions {\n /** Worker mount path; defaults to `/api/brand`. */\n basePath?: string;\n /** Document (and probe-plan for) unauthenticated tokens routes. */\n publicTokens?: boolean;\n /** The global bot's mention handle — folded into the CLI trigger step. */\n mention?: string;\n}\n\n/**\n * Build the project-specific, CLI-consumable brand integration descriptor:\n * {@link brandIntegration} plus a live smoke probe (an anonymous GET of\n * `<basePath>/books` must answer 401 — routes mounted, authorize enforced,\n * exactly crm's probe idiom) and, when `mention`/`publicTokens` are given,\n * concrete CLI steps carrying the app's actual values. Mounting\n * `createBrandRoutes` remains app-owned source work.\n */\nexport function createBrandIntegration(\n options: CreateBrandIntegrationOptions = {},\n): BrandIntegrationDescriptor {\n const basePath = options.basePath ?? \"/api/brand\";\n if (!/^\\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(basePath) || basePath.endsWith(\"/\")) {\n throw new Error(\"createBrandIntegration: basePath must be an absolute path without a trailing slash\");\n }\n const cli = [...brandIntegration.provision.cli];\n if (options.mention !== undefined)\n cli.push(`Gate the global bot on mentions: brandBotTrigger({ mention: ${JSON.stringify(options.mention)}, ... }).`);\n if (options.publicTokens === true)\n cli.push(`Mount createBrandRoutes({ publicTokens: true }) so ${basePath}/books/:id/tokens.css serves unauthenticated.`);\n return {\n ...brandIntegration,\n provision: { ...brandIntegration.provision, cli },\n probes: [{ path: `${basePath}/books`, expectedStatus: 401 }],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,OAAO;AACT;AAGO,IAAM,gBAAgB,CAAC,SAAS,UAAU,UAAU;AAKpD,IAAM,gBAAgB,CAAC,WAAW,cAAc,SAAS,QAAQ,SAAS;AAK1E,IAAM,mBAAmB,CAAC,SAAS,UAAU;AAK7C,IAAM,mBAAmB,CAAC,UAAU,UAAU;AAM9C,IAAM,kBAAkB,CAAC,aAAa,WAAW,QAAQ;AAKzD,IAAM,iBAAiB;AAMvB,IAAM,oBAAoB,CAAC,QAAQ,YAAY,YAAY,YAAY;AAQvE,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,oBAAoB;AAI1B,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACnEO,IAAM,sBAAyC;AAAA,EACpD,SAAS;AAAA,EACT,qBAAqB,CAAC,cAAc,YAAY;AAAA,EAChD,oBAAoB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,UAAU;AAAA,IACR,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,YAAY;AAAA,IACZ,aAAa;AAAA,EACf;AACF;;;AClCO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EACT,YAAY,SAAiB,QAAiC;AAC5D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,MAAc;AACxB,UAAM,GAAG,IAAI,YAAY;AACzB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YAAY,UAAU,sDAAsD;AAC1E,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAY,UAAU,aAAa;AACjC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAOO,IAAM,+BAAN,cAA2C,mBAAmB;AAAA,EAC1D,OAAO;AAAA,EAEhB,YACE,UAAU,yEACV;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACRA,IAAM,IAAI,CAAC,MAAgB,IAAS,CAAC,OAAuB;AAAA,EAC1D;AAAA,EACA,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,GAAG;AACL;AACA,IAAM,OAAO,CAAC,SAAmC,EAAE,MAAM,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AACxF,IAAM,MAAM,CAAC,MAAgB,WAAW,UAA0B,EAAE,MAAM,EAAE,SAAS,MAAM,SAAS,CAAC;AACrG,IAAM,MAAM,CAAC,SAAmC,EAAE,MAAM,EAAE,UAAU,KAAK,CAAC;AASnE,IAAM,eAAiC;AAAA,EAC5C,UAAU;AAAA,IACR,CAAC,SAAS,IAAI,GAAG;AAAA,MACf,OAAO;AAAA,QACL,IAAI,KAAK,QAAQ;AAAA,QACjB,SAAS,EAAE,QAAQ;AAAA,QACnB,MAAM,KAAK,QAAQ;AAAA,QACnB,MAAM,IAAI,QAAQ;AAAA,QAClB,QAAQ,IAAI,QAAQ;AAAA;AAAA,QACpB,SAAS,IAAI,QAAQ;AAAA,QACrB,qBAAqB,IAAI,QAAQ;AAAA,QACjC,oBAAoB,IAAI,QAAQ;AAAA,QAChC,WAAW,EAAE,MAAM;AAAA;AAAA,QACnB,WAAW,EAAE,UAAU,EAAE,QAAQ,MAAM,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,QACtE,iBAAiB,IAAI,QAAQ;AAAA,QAC7B,oBAAoB,EAAE,QAAQ;AAAA,QAC9B,QAAQ,IAAI,MAAM;AAAA;AAAA,QAClB,SAAS,IAAI,QAAQ;AAAA,QACrB,WAAW,IAAI,MAAM;AAAA,QACrB,WAAW,IAAI,MAAM;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,OAAO;AAAA,QACL,KAAK,KAAK,QAAQ;AAAA;AAAA,QAClB,QAAQ,IAAI,QAAQ;AAAA,QACpB,MAAM,IAAI,QAAQ;AAAA;AAAA,QAClB,QAAQ,IAAI,QAAQ;AAAA;AAAA,QACpB,SAAS,EAAE,MAAM;AAAA,QACjB,UAAU,EAAE,MAAM;AAAA,QAClB,WAAW,EAAE,QAAQ;AAAA,QACrB,WAAW,IAAI,MAAM;AAAA,QACrB,mBAAmB,IAAI,QAAQ;AAAA,QAC/B,sBAAsB,IAAI,QAAQ;AAAA,MACpC;AAAA,IACF;AAAA,IACA,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,OAAO;AAAA,QACL,IAAI,KAAK,QAAQ;AAAA,QACjB,QAAQ,IAAI,QAAQ;AAAA,QACpB,MAAM,EAAE,QAAQ;AAAA,QAChB,QAAQ,IAAI,QAAQ;AAAA;AAAA,QACpB,UAAU,EAAE,MAAM;AAAA;AAAA,QAClB,SAAS,IAAI,QAAQ;AAAA,QACrB,QAAQ,EAAE,QAAQ;AAAA;AAAA,QAClB,WAAW,IAAI,QAAQ;AAAA,QACvB,YAAY,IAAI,QAAQ;AAAA,QACxB,mBAAmB,EAAE,QAAQ;AAAA,QAC7B,sBAAsB,EAAE,QAAQ;AAAA,QAChC,UAAU,EAAE,MAAM;AAAA,QAClB,WAAW,IAAI,MAAM;AAAA,QACrB,WAAW,IAAI,MAAM;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,SAAS,QAAQ,GAAG;AAAA,MACnB,OAAO;AAAA,QACL,IAAI,KAAK,QAAQ;AAAA,QACjB,QAAQ,IAAI,QAAQ;AAAA,QACpB,MAAM,IAAI,QAAQ;AAAA;AAAA,QAClB,QAAQ,IAAI,QAAQ;AAAA;AAAA,QACpB,SAAS,EAAE,MAAM;AAAA,QACjB,WAAW,EAAE,QAAQ;AAAA,QACrB,YAAY,EAAE,MAAM;AAAA;AAAA,QACpB,cAAc,IAAI,QAAQ;AAAA,QAC1B,UAAU,EAAE,MAAM;AAAA,QAClB,WAAW,EAAE,QAAQ;AAAA,QACrB,qBAAqB,EAAE,QAAQ;AAAA,QAC/B,WAAW,IAAI,MAAM;AAAA,QACrB,YAAY,IAAI,QAAQ;AAAA,QACxB,YAAY,IAAI,MAAM;AAAA,QACtB,gBAAgB,IAAI,QAAQ;AAAA,QAC5B,YAAY,IAAI,QAAQ;AAAA,QACxB,WAAW,IAAI,QAAQ;AAAA,QACvB,qBAAqB,IAAI,QAAQ;AAAA,QACjC,wBAAwB,IAAI,QAAQ;AAAA,MACtC;AAAA,IACF;AAAA,IACA,CAAC,SAAS,eAAe,GAAG;AAAA,MAC1B,OAAO;AAAA,QACL,IAAI,KAAK,QAAQ;AAAA,QACjB,SAAS,EAAE,QAAQ;AAAA,QACnB,aAAa,KAAK,QAAQ;AAAA,QAC1B,QAAQ,IAAI,QAAQ;AAAA,QACpB,YAAY,IAAI,QAAQ;AAAA,QACxB,YAAY,IAAI,QAAQ;AAAA;AAAA,QACxB,WAAW,IAAI,QAAQ;AAAA,QACvB,gBAAgB,IAAI,QAAQ;AAAA,QAC5B,kBAAkB,EAAE,MAAM;AAAA,QAC1B,cAAc,IAAI,QAAQ;AAAA,QAC1B,iBAAiB,EAAE,MAAM;AAAA,QACzB,YAAY,IAAI,QAAQ;AAAA,QACxB,gBAAgB,EAAE,QAAQ;AAAA,QAC1B,WAAW,IAAI,QAAQ;AAAA,QACvB,eAAe,EAAE,QAAQ;AAAA,QACzB,cAAc,IAAI,QAAQ;AAAA,QAC1B,qBAAqB,EAAE,QAAQ;AAAA,QAC/B,sBAAsB,EAAE,MAAM;AAAA,QAC9B,WAAW,IAAI,MAAM;AAAA,QACrB,eAAe,IAAI,QAAQ;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,SAAS,KAAK,GAAG;AAAA,MAChB,OAAO;AAAA,QACL,IAAI,KAAK,QAAQ;AAAA,QACjB,QAAQ,IAAI,QAAQ;AAAA,QACpB,MAAM,IAAI,QAAQ;AAAA;AAAA,QAClB,MAAM,IAAI,QAAQ;AAAA,QAClB,iBAAiB,IAAI,QAAQ;AAAA,QAC7B,eAAe,IAAI,QAAQ;AAAA,QAC3B,aAAa,EAAE,QAAQ;AAAA,QACvB,MAAM,EAAE,QAAQ;AAAA,QAChB,QAAQ,IAAI,QAAQ;AAAA;AAAA,QACpB,OAAO,IAAI,QAAQ;AAAA,QACnB,UAAU,IAAI,MAAM;AAAA;AAAA,QACpB,YAAY,IAAI,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,QAKtB,QAAQ,IAAI,MAAM;AAAA,QAClB,kBAAkB,EAAE,QAAQ;AAAA,QAC5B,gBAAgB,IAAI,QAAQ;AAAA,QAC5B,YAAY,IAAI,QAAQ;AAAA,QACxB,sBAAsB,IAAI,QAAQ;AAAA,QAClC,UAAU,EAAE,MAAM;AAAA,QAClB,YAAY,EAAE,QAAQ;AAAA,QACtB,sBAAsB,EAAE,QAAQ;AAAA,QAChC,WAAW,IAAI,MAAM;AAAA,QACrB,WAAW,IAAI,MAAM;AAAA;AAAA,QACrB,WAAW,IAAI,QAAQ;AAAA,QACvB,qBAAqB,IAAI,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,kBAAkB;AAAA,MAChB,SAAS,EAAE,IAAI,SAAS,SAAS,KAAK,OAAO,OAAO,OAAO;AAAA,MAC3D,SAAS,EAAE,IAAI,SAAS,MAAM,KAAK,QAAQ,OAAO,WAAW;AAAA,IAC/D;AAAA,IACA,kBAAkB;AAAA,MAChB,SAAS,EAAE,IAAI,SAAS,SAAS,KAAK,OAAO,OAAO,OAAO;AAAA,MAC3D,SAAS,EAAE,IAAI,SAAS,MAAM,KAAK,QAAQ,OAAO,WAAW;AAAA,IAC/D;AAAA,IACA,mBAAmB;AAAA,MACjB,SAAS,EAAE,IAAI,SAAS,UAAU,KAAK,OAAO,OAAO,OAAO;AAAA,MAC5D,SAAS,EAAE,IAAI,SAAS,MAAM,KAAK,QAAQ,OAAO,YAAY;AAAA,IAChE;AAAA,IACA,0BAA0B;AAAA,MACxB,SAAS,EAAE,IAAI,SAAS,iBAAiB,KAAK,OAAO,OAAO,OAAO;AAAA,MACnE,SAAS,EAAE,IAAI,SAAS,MAAM,KAAK,QAAQ,OAAO,mBAAmB;AAAA,IACvE;AAAA,IACA,gBAAgB;AAAA,MACd,SAAS,EAAE,IAAI,SAAS,OAAO,KAAK,OAAO,OAAO,OAAO;AAAA,MACzD,SAAS,EAAE,IAAI,SAAS,MAAM,KAAK,QAAQ,OAAO,SAAS;AAAA,IAC7D;AAAA,EACF;AACF;;;ACpNA,IAAM,SAAS,CAAC,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAQrE,IAAM,cAAc,oBAAI,IAAyB;AACjD,WAAW,CAAC,IAAI,MAAM,KAAK,OAAO,QAAQ,aAAa,QAAQ;AAC7D,cAAY;AAAA,IACV;AAAA,IACA,IAAI;AAAA,MACF,OAAO,QAAQ,OAAO,KAAK,EACxB,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,KAAK,SAAS,MAAM,EACzC,IAAI,CAAC,CAAC,KAAK,MAAM,KAAK;AAAA,IAC3B;AAAA,EACF;AAuBK,SAAS,aAAgB,IAAY,KAAW;AACrD,QAAM,QAAQ,YAAY,IAAI,EAAE;AAChC,MAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,GAAG,EAAG,QAAO;AACzC,MAAI,UAAU;AACd,QAAM,MAA+B,EAAE,GAAG,IAAI;AAC9C,aAAW,SAAS,OAAO;AACzB,UAAM,QAAQ,IAAI,KAAK;AACvB,QAAI,OAAO,UAAU,SAAU;AAC/B,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,QAAI,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,EAAG;AACjD,QAAI,KAAK,IAAI;AACb,cAAU;AAAA,EACZ;AACA,SAAQ,UAAU,MAAM;AAC1B;AAGO,SAAS,iBAAoB,KAAW;AAC7C,SAAO,aAAa,SAAS,iBAAiB,GAAG;AACnD;AAGO,SAAS,kBAAqB,KAAW;AAC9C,SAAO,aAAa,SAAS,UAAU,GAAG;AAC5C;AAWO,SAAS,gBAAmD,QAAc;AAC/E,QAAM,MAA+B,EAAE,GAAG,OAAO;AACjD,aAAW,CAAC,IAAI,IAAI,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC5C,QAAI,MAAM,QAAQ,IAAI,EAAG,KAAI,EAAE,IAAI,KAAK,IAAI,CAAC,QAAQ,aAAa,IAAI,GAAG,CAAC;AAAA,EAC5E;AACA,SAAO;AACT;;;AC9DA,eAAe,kBAAkB,KAAyC;AACxE,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,QAAQ,GAAG,EAAE;AAC3E,SAAO;AAAA,IACL,OAAO,IAAI,WAAW,MAAM,IAAI,YAAY,CAAC;AAAA,IAC7C,aAAa,IAAI,QAAQ,IAAI,cAAc,KAAK;AAAA,EAClD;AACF;AAeA,SAAS,iBAAiB,IAAsB;AAC9C,SAAO;AAAA,IACL,OAAO,OAAO,MAAM,gBAAgB,MAAM,GAAG,MAAM,CAAC,CAAC;AAAA,IACrD,UAAU,CAAC,KAAK,SAAS,GAAG,SAAS,KAAK,IAAI;AAAA,IAC9C,SAAS,GAAG;AAAA,EACd;AACF;AAGO,SAAS,YAAY,MAAoC;AAC9D,SAAO;AAAA,IACL,IAAI,iBAAiB,KAAK,EAAE;AAAA,IAC5B,KAAK,KAAK,OAAO,KAAK;AAAA,IACtB,OAAO,KAAK,UAAU,MAAM,OAAO,WAAW;AAAA,IAC9C,YAAY,KAAK,cAAc;AAAA,EACjC;AACF;;;AC7CA,IAAM,sBACJ;AASK,IAAM,cAA0B;AAAA,EACrC,CAAC,SAAS,IAAI,GAAG;AAAA,IACf,MAAM;AAAA;AAAA;AAAA,IAGN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,CAAC,SAAS,OAAO,GAAG;AAAA,IAClB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,CAAC,SAAS,OAAO,GAAG;AAAA,IAClB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,CAAC,SAAS,QAAQ,GAAG;AAAA,IACnB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,CAAC,SAAS,eAAe,GAAG;AAAA,IAC1B,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,CAAC,SAAS,KAAK,GAAG;AAAA,IAChB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAQO,SAAS,aAAyB;AACvC,SAAO,OAAO,YAAY,OAAO,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACxF;;;AClEO,IAAM,eAAe;AAMrB,IAAM,sBAA2C,oBAAI,IAAI;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAKM,IAAM,uBAA4C,oBAAI,IAAI,CAAC,WAAW,CAAC;AAE9E,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,YAAY;AAElB,IAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAQlD,SAAS,UAAU,OAAgB,QAAQ,SAAiB;AACjE,MAAI,OAAO,UAAU;AACnB,UAAM,IAAI,gBAAgB,GAAG,KAAK,oCAAoC;AACxE,QAAM,MAAM,MAAM,KAAK,EAAE,YAAY;AACrC,MAAI,UAAU,KAAK,GAAG;AACpB,UAAM,IAAI,gBAAgB,GAAG,KAAK,8BAA8B,KAAK,gBAAgB;AACvF,MAAI,QAAQ,KAAK,GAAG,EAAG,QAAO,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACrF,MAAI,CAAC,WAAW,KAAK,GAAG;AACtB,UAAM,IAAI,gBAAgB,GAAG,KAAK,qCAAqC,KAAK,GAAG;AACjF,SAAO;AACT;AAGO,SAAS,UAAU,OAAgB,OAAe,KAAqB;AAC5E,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,gBAAgB,GAAG,KAAK,mBAAmB;AACpF,QAAM,IAAI,MAAM,KAAK;AACrB,MAAI,MAAM,GAAI,OAAM,IAAI,gBAAgB,GAAG,KAAK,oBAAoB;AACpE,MAAI,EAAE,SAAS;AACb,UAAM,IAAI,gBAAgB,GAAG,KAAK,oBAAoB,GAAG,oBAAoB,EAAE,MAAM,GAAG;AAC1F,SAAO;AACT;AAGO,SAAS,eACd,OACA,OACA,MACU;AACV,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,gBAAgB,GAAG,KAAK,8BAA8B;AAC3F,QAAM,MAAM,KAAK,YAAY;AAC7B,MAAI,MAAM,SAAS;AACjB,UAAM,IAAI,gBAAgB,GAAG,KAAK,uBAAuB,GAAG,QAAQ,QAAQ,IAAI,KAAK,GAAG,EAAE;AAC5F,MAAI,MAAM,SAAS,KAAK;AACtB,UAAM,IAAI,gBAAgB,GAAG,KAAK,sBAAsB,KAAK,QAAQ,QAAQ;AAC/E,SAAO,MAAM,IAAI,CAAC,GAAG,MAAM,UAAU,GAAG,GAAG,KAAK,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC;AACxE;AAOO,SAAS,eAAe,OAA0B;AACvD,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW;AAC5C,UAAM,IAAI,gBAAgB,oCAAoC;AAChE,MAAI,MAAM,SAAS;AACjB,UAAM,IAAI,gBAAgB,8BAA8B,YAAY,UAAU;AAChF,SAAO,MAAM,IAAI,CAAC,KAAK,MAAM;AAC3B,QAAI,CAAC,SAAS,GAAG,EAAG,OAAM,IAAI,gBAAgB,YAAY,CAAC,qBAAqB;AAChF,UAAM,OAAO,IAAI;AACjB,QAAI,OAAO,SAAS,YAAY,CAAE,aAAmC,SAAS,IAAI;AAChF,YAAM,IAAI;AAAA,QACR,YAAY,CAAC,0BAA0B,aAAa,KAAK,IAAI,CAAC;AAAA,MAChE;AACF,UAAM,MAAc,EAAE,MAA0B,KAAK,UAAU,IAAI,KAAK,YAAY,CAAC,OAAO,EAAE;AAC9F,QAAI,IAAI,SAAS,OAAW,KAAI,OAAO,UAAU,IAAI,MAAM,YAAY,CAAC,UAAU,EAAE;AACpF,QAAI,IAAI,cAAc;AACpB,UAAI,YAAY,UAAU,IAAI,WAAW,YAAY,CAAC,eAAe,GAAG;AAC1E,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,qBAAqB,GAA4C;AACxE,SAAO;AAAA,IACL,WAAW,UAAU,EAAE,WAAW,qBAAqB,GAAG;AAAA,IAC1D,MAAM,UAAU,EAAE,MAAM,gBAAgB,GAAG;AAAA,IAC3C,UAAU,eAAe,EAAE,QAAQ;AAAA,EACrC;AACF;AAEA,SAAS,wBAAwB,GAA+C;AAC9E,QAAM,MAAyB,CAAC;AAChC,MAAI,EAAE,gBAAgB,OAAW,KAAI,cAAc,UAAU,EAAE,aAAa,uBAAuB,GAAG;AACtG,MAAI,EAAE,aAAa,OAAW,KAAI,WAAW,UAAU,EAAE,UAAU,oBAAoB,GAAG;AAC1F,MAAI,EAAE,aAAa,OAAW,KAAI,WAAW,UAAU,EAAE,UAAU,oBAAoB,GAAG;AAC1F,MAAI,EAAE,UAAU,QAAW;AACzB,QAAI,OAAO,EAAE,UAAU,YAAY,CAAC,OAAO,SAAS,EAAE,KAAK,KAAK,EAAE,SAAS,KAAK,EAAE,QAAQ;AACxF,YAAM,IAAI,gBAAgB,4DAA4D;AACxF,QAAI,QAAQ,EAAE;AAAA,EAChB;AACA,MAAI,EAAE,UAAU,OAAW,KAAI,QAAQ,UAAU,EAAE,OAAO,iBAAiB,GAAI;AAC/E,SAAO;AACT;AAEA,SAAS,mBAAmB,GAA0C;AACpE,QAAM,MAAoB;AAAA,IACxB,MAAM,UAAU,EAAE,MAAM,gBAAgB,GAAG;AAAA,IAC3C,YAAY,eAAe,EAAE,YAAY,sBAAsB,EAAE,UAAU,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;AAAA,EAC3G;AACA,MAAI,EAAE,aAAa;AACjB,QAAI,WAAW,eAAe,EAAE,UAAU,oBAAoB,EAAE,UAAU,IAAI,QAAQ,IAAI,CAAC;AAC7F,SAAO;AACT;AAEA,SAAS,kBAAkB,GAAyC;AAClE,QAAM,MAAmB;AAAA,IACvB,OAAO,eAAe,EAAE,OAAO,iBAAiB,EAAE,UAAU,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;AAAA,IAC1F,OAAO,eAAe,EAAE,OAAO,iBAAiB,EAAE,UAAU,IAAI,QAAQ,IAAI,CAAC;AAAA,EAC/E;AACA,MAAI,EAAE,eAAe,OAAW,KAAI,aAAa,UAAU,EAAE,YAAY,sBAAsB,GAAG;AAClG,MAAI,EAAE,YAAY,OAAW,KAAI,UAAU,UAAU,EAAE,SAAS,mBAAmB,GAAG;AACtF,SAAO;AACT;AAEA,SAAS,qBAAqB,GAA4C;AACxE,SAAO;AAAA,IACL,OAAO,UAAU,EAAE,OAAO,iBAAiB,GAAG;AAAA,IAC9C,UAAU,eAAe,EAAE,UAAU,oBAAoB,EAAE,UAAU,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;AAAA,EACrG;AACF;AAOO,SAAS,qBAAqB,MAAc,SAA2C;AAC5F,MAAI,CAAC,SAAS,OAAO,EAAG,OAAM,IAAI,gBAAgB,2BAA2B;AAC7E,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,EAAE,GAAG,qBAAqB,OAAO,EAAE;AAAA,IAC5C,KAAK;AACH,aAAO,EAAE,GAAG,wBAAwB,OAAO,EAAE;AAAA,IAC/C,KAAK;AACH,aAAO,EAAE,GAAG,mBAAmB,OAAO,EAAE;AAAA,IAC1C,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,OAAO,EAAE;AAAA,IACzC,KAAK;AACH,aAAO,EAAE,GAAG,qBAAqB,OAAO,EAAE;AAAA,IAC5C;AACE,YAAM,IAAI,gBAAgB,wBAAwB,IAAI,sBAAsB,cAAc,KAAK,IAAI,CAAC,EAAE;AAAA,EAC1G;AACF;AAMO,SAAS,aAAa,MAAuB;AAClD,MAAI,OAAO,SAAS,SAAU,OAAM,IAAI,gBAAgB,4BAA4B;AAEpF,MAAI,8BAA8B,KAAK,IAAI;AACzC,UAAM,IAAI,gBAAgB,6DAA6D;AACzF,QAAM,UAAU,KACb,KAAK,EACL,QAAQ,QAAQ,EAAE;AACrB,MAAI,YAAY,MAAM,YAAY,OAAO,YAAY;AACnD,UAAM,IAAI,gBAAgB,sDAAsD;AAClF,SAAO,QAAQ,MAAM,GAAG,GAAG;AAC7B;AAaO,SAAS,uBAAuB,OAAgB,MAAuB;AAC5E,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,gBAAgB,8BAA8B;AACvF,QAAM,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,EAAG,KAAK,EAAE,YAAY;AACnD,QAAM,UAAU,SAAS,oBAAoB,uBAAuB;AACpE,MAAI,CAAC,QAAQ,IAAI,EAAE;AACjB,UAAM,IAAI;AAAA,MACR,4BAA4B,MAAM,SAAS,aAAa,QAAQ,OAAO,cAAc,CAAC,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IAC9G;AACF,SAAO;AACT;AAMO,SAAS,eAAe,OAA+B;AAC5D,MAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,gBAAgB,4BAA4B;AAC5E,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,OAAM,IAAI,gBAAgB,0CAA0C;AAChG,MAAI,OAAO,SAAS;AAClB,UAAM,IAAI,gBAAgB,sDAAsD;AAClF,SAAO;AAAA,IACL,aAAa,UAAU,MAAM,aAAa,wBAAwB,GAAI;AAAA,IACtE,gBAAgB,OAAO,IAAI,CAAC,GAAG,MAAM,UAAU,GAAG,2BAA2B,CAAC,GAAG,CAAC;AAAA,IAClF,MAAM,eAAe,MAAM,MAAM,iBAAiB,EAAE,UAAU,IAAI,QAAQ,GAAG,CAAC;AAAA,EAChF;AACF;;;AC9OA,IAAMA,UAAS,CAAC,UACd,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,MAAM,QAAQ,KAAK,MACnB,OAAO,eAAe,KAAK,MAAM,OAAO,aACvC,OAAO,eAAe,KAAK,MAAM;AAG9B,SAAS,mBACd,MACA,SAAsE,CAAC,GAC9D;AACT,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,WAAW,OAAO,YAAY,KAAK;AACzC,QAAM,QAAkD,CAAC;AAAA,IACvD,OAAO;AAAA,IACP,OAAO;AAAA,EACT,CAAC;AACD,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,QAAQ;AACZ,SAAO,MAAM,QAAQ;AACnB,UAAM,EAAE,OAAO,MAAM,IAAI,MAAM,IAAI;AACnC,QAAI,EAAE,QAAQ,YAAY,QAAQ,SAAU,QAAO;AACnD,QACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,UAAU,UACjB;AACF,QAAI,OAAO,UAAU,UAAU;AAC7B,UAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC;AAAA,IACF;AACA,QAAI,OAAO,UAAU,YAAY,KAAK,IAAI,KAAK,EAAG,QAAO;AACzD,SAAK,IAAI,KAAK;AACd,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,SAAS;AAClB,cAAM,KAAK,EAAE,OAAO,OAAO,OAAO,QAAQ,EAAE,CAAC;AAAA,IACjD,WAAWA,QAAO,KAAK,GAAG;AACxB,iBAAW,SAAS,OAAO,OAAO,KAAK;AACrC,cAAM,KAAK,EAAE,OAAO,OAAO,OAAO,QAAQ,EAAE,CAAC;AAAA,IACjD,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI;AACF,WAAO,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,IAAI,CAAC,EAAE,cAAc;AAAA,EACtE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,OAAwB;AACzC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC5E,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;AACnE,QAAM,MAAM;AACZ,SAAO,IAAI,OAAO,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,QACtC,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC;AAC9D;AAGO,SAAS,mBAAmB,OAAwB;AACzD,MAAI,CAAC,mBAAmB,OAAO;AAAA,IAC7B,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU,MAAM;AAAA,EAClB,CAAC,EAAG,OAAM,IAAI,UAAU,gDAAgD;AACxE,SAAO,UAAU,KAAK;AACxB;AAGA,eAAsB,gBAAgB,OAAiC;AACrE,QAAM,QAAQ,MAAM,OAAO,OAAO;AAAA,IAChC;AAAA,IACA,IAAI,YAAY,EAAE,OAAO,mBAAmB,KAAK,CAAC;AAAA,EACpD;AACA,SAAO,UAAU,CAAC,GAAG,IAAI,WAAW,KAAK,CAAC,EACvC,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE,CAAC;AACb;;;ACzDA,IAAM,SAAS;AACf,IAAMC,UAAS,CAAC,UACd,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,MAAM,QAAQ,KAAK,MACnB,OAAO,eAAe,KAAK,MAAM,OAAO,aAAa,OAAO,eAAe,KAAK,MAAM;AACzF,IAAM,YAAY,CAAC,OAAgC,UAA6B,WAA8B,CAAC,MAAM;AACnH,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC;AAClD,SAAO,SAAS,MAAM,CAAC,QAAQ,OAAO,OAAO,OAAO,GAAG,CAAC,KACtD,OAAO,KAAK,KAAK,EAAE,MAAM,CAAC,QAAQ,QAAQ,IAAI,GAAG,CAAC;AACtD;AACA,IAAM,gBAAgB,CAAC,OAAgB,MAAM,QAC3C,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,UAAU;AACnE,IAAM,WAAW,CAAC,UAChB,OAAO,cAAc,KAAK,KAAM,SAAoB;AAG/C,SAAS,kBACd,aACQ;AACR,SAAO,aAAa,YAAY,OAAO,KAAK,YAAY,YAAY;AACtE;AAEA,IAAM,oBAAoB;AAAA,EACxB;AAAA,EAAM;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAW;AAAA,EAAa;AAAA,EAC1D;AAAA,EAAgB;AAAA,EAAY;AAAA,EAAa;AAAA,EAAuB;AAClE;AAEA,SAAS,mBAAmB,OAAsD;AAChF,MAAI,CAACA,QAAO,KAAK,KAAK,CAAC,UAAU,OAAO,iBAAiB,EAAG,QAAO;AACnE,QAAM,aAAa,MAAM;AACzB,SAAO,cAAc,MAAM,EAAE,KAC3B,cAAc,MAAM,MAAM,KAC1B,OAAO,MAAM,SAAS,YACrB,eAAqC,SAAS,MAAM,IAAI,KACzD,MAAM,WAAW,UACjBA,QAAO,MAAM,OAAO,KACpB,cAAc,MAAM,WAAW,GAAK,KACpCA,QAAO,UAAU,KACjB,UAAU,YAAY;AAAA,IACpB;AAAA,IAAiB;AAAA,IAAe;AAAA,IAAa;AAAA,IAAU;AAAA,EACzD,CAAC,MACA,WAAW,kBAAkB,QAC5B,cAAc,WAAW,aAAa,OACvC,WAAW,gBAAgB,QACzBA,QAAO,WAAW,WAAW,KAC5B,UAAU,WAAW,aAAa;AAAA,IAChC;AAAA,IAAW;AAAA,IAAiB;AAAA,IAAc;AAAA,IAAc;AAAA,IACxD;AAAA,IAAe;AAAA,IAAoB;AAAA,EACrC,CAAC,KACD,cAAc,WAAW,YAAY,OAAO,KAC5C,OAAO,WAAW,YAAY,kBAAkB,YAChD,OAAO,KAAK,WAAW,YAAY,aAAa,KAChD,cAAc,WAAW,YAAY,UAAU,KAC/C,OAAO,cAAc,WAAW,YAAY,UAAU,KACrD,WAAW,YAAY,aAAwB,KAChD,OAAO,WAAW,YAAY,eAAe,YAC7C,OAAO,KAAK,WAAW,YAAY,UAAU,MAC5C,WAAW,YAAY,gBAAgB,QACtC,cAAc,WAAW,YAAY,aAAa,GAAG,OACtD,WAAW,YAAY,qBAAqB,QAC1C,OAAO,cAAc,WAAW,YAAY,gBAAgB,KAC1D,WAAW,YAAY,oBAA+B,OAC1D,WAAW,YAAY,mBAAmB,QACxC,OAAO,WAAW,YAAY,mBAAmB,YAChD,OAAO,KAAK,WAAW,YAAY,cAAc,QACvD,WAAW,kBAAkB,QAAQ,WAAW,gBAAgB,QAC/D,WAAW,kBAAkB,QAC5B,WAAW,gBAAgB,QAC3B,WAAW,YAAY,YAAY,WAAW,mBACjD,WAAW,cAAc,QAAQ,cAAc,WAAW,SAAS,OACnE,WAAW,WAAW,QAAQ,cAAc,WAAW,MAAM,MAC9D,MAAM,QAAQ,WAAW,WAAW,KACpC,WAAW,YAAY,UAAU,MACjC,WAAW,YAAY,MAAM,CAAC,UAAU,cAAc,OAAO,GAAG,CAAC,KACjE,IAAI,IAAI,WAAW,WAAW,EAAE,SAAS,WAAW,YAAY,UAChE,OAAO,MAAM,iBAAiB,YAAY,OAAO,KAAK,MAAM,YAAY,KACxE,MAAM,QAAQ,MAAM,QAAQ,KAC5B,MAAM,SAAS,SAAS,KAAK,MAAM,SAAS,UAAU,OACtD,MAAM,SAAS,MAAM,CAAC,OAAO,cAAc,EAAE,CAAC,KAC9C,IAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,MAAM,SAAS,UAChD,cAAc,MAAM,SAAS,KAC7B,cAAc,MAAM,mBAAmB,KACvC,SAAS,MAAM,SAAS;AAC5B;AAEA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EAAM;AAAA,EAAW;AAAA,EAAgB;AAAA,EAAa;AAAA,EAC9C;AAAA,EAAa;AAAA,EAAgB;AAAA,EAAkB;AAAA,EAAS;AAAA,EACxD;AAAA,EACA;AAAA,EAAqB;AAAA,EAAU;AAAA,EAAgB;AAAA,EAC/C;AAAA,EACA;AAAA,EAA6B;AAAA,EAAiB;AAChD;AAGO,SAAS,iCACd,OACyC;AACzC,MAAI,CAACA,QAAO,KAAK,KAAK,CAAC,UAAU,OAAO,oBAAoB,EAAG,QAAO;AACtE,SAAO,cAAc,MAAM,EAAE,KAC3B,cAAc,MAAM,OAAO,KAC3B,OAAO,cAAc,MAAM,YAAY,KAAM,MAAM,eAA0B,KAC7E,OAAO,cAAc,MAAM,SAAS,KAAM,MAAM,YAAuB,KACvE,cAAc,MAAM,gBAAgB,KACpC,MAAM,cAAc,WACpB,cAAc,MAAM,YAAY,KAChC,MAAM,mBAAmB,WACzB,cAAc,MAAM,KAAK,KACzB,OAAO,MAAM,mBAAmB,YAChC,iBAAiB,KAAK,MAAM,cAAc,KAC1C,MAAM,eAAe,4BACrB,MAAM,sBAAsB,mBAC5B,MAAM,WAAW,cACjB,OAAO,MAAM,iBAAiB,YAAY,OAAO,KAAK,MAAM,YAAY,KACxE,OAAO,MAAM,mBAAmB,YAAY,OAAO,KAAK,MAAM,cAAc,KAC5EA,QAAO,MAAM,kBAAkB,KAC/B,cAAc,MAAM,yBAAyB,KAC7C,OAAO,MAAM,kBAAkB,YAAY,OAAO,KAAK,MAAM,aAAa,KAC1E,SAAS,MAAM,UAAU;AAC7B;AAEA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EAAW;AAAA,EAAM;AAAA,EAAe;AAAA,EAAU;AAAA,EAAc;AAAA,EACxD;AAAA,EAAoB;AAAA,EAAgB;AAAA,EAAmB;AAAA,EAAc;AAAA,EACrE;AAAA,EAAa;AAAA,EAAiB;AAAA,EAAgB;AAAA,EAC9C;AAAA,EAAwB;AAAA,EAAa;AACvC;AAKA,eAAsB,2BAA2BC,UAAoC;AACnF,MAAI;AACF,QAAI,CAAC,mBAAmBA,UAAS,EAAE,UAAU,IAAI,UAAU,MAAO,UAAU,KAAK,KAAK,CAAC;AACrF,aAAO;AACT,QAAI,CAACD,QAAOC,QAAO,KAAK,CAAC,UAAUA,UAAS,kBAAkB,CAAC,aAAa,gBAAgB,CAAC;AAC3F,aAAO;AACT,UAAM,UAAUA,SAAQ;AACxB,QACEA,SAAQ,YAAY,KACpB,CAAC,cAAcA,SAAQ,EAAE,KACzB,CAAC,cAAcA,SAAQ,WAAW,KAClC,CAAC,cAAcA,SAAQ,MAAM,KAC7B,CAAC,cAAcA,SAAQ,UAAU,KAChCA,SAAQ,eAAe,cAAcA,SAAQ,eAAe,cAC7D,CAAC,mBAAmBA,SAAQ,gBAAgB,KAC5C,OAAOA,SAAQ,iBAAiB,YAAY,CAAC,OAAO,KAAKA,SAAQ,YAAY,KAC7E,CAACD,QAAO,OAAO,KACf,CAAC,UAAU,SAAS;AAAA,MAClB;AAAA,MAAW;AAAA,MAAe;AAAA,MAAsB;AAAA,MAChD;AAAA,MAAmB;AAAA,MAAuB;AAAA,MAC1C;AAAA,MAAqB;AAAA,IACvB,CAAC,KACD,QAAQ,YAAY,KACpB,CAAC,OAAO,cAAc,QAAQ,WAAW,KAAM,QAAQ,cAAyB,KAChF,CAAC,OAAO,cAAc,QAAQ,kBAAkB,KAC/C,QAAQ,qBAAgC,KACxC,QAAQ,oBAAoB,QAAQ,CAAC,cAAc,QAAQ,eAAe,KAC3E,OAAO,QAAQ,oBAAoB,YAAY,CAAC,OAAO,KAAK,QAAQ,eAAe,KAClF,QAAQ,wBAAwB,SAC9B,OAAO,QAAQ,wBAAwB,YACtC,CAAC,OAAO,KAAK,QAAQ,mBAAmB,MAC3C,QAAQ,qBAAqB,SAC3B,OAAO,QAAQ,qBAAqB,YACnC,CAAC,OAAO,KAAK,QAAQ,gBAAgB,MACxC,QAAQ,sBAAsB,SAC5B,OAAO,QAAQ,sBAAsB,YACpC,CAAC,OAAO,KAAK,QAAQ,iBAAiB,MAC1C,OAAO,QAAQ,iBAAiB,YAAY,CAAC,OAAO,KAAK,QAAQ,YAAY,KAC7E,CAAC,cAAcC,SAAQ,UAAU,KACjCA,SAAQ,mBAAmB,WAC3B,CAAC,cAAcA,SAAQ,SAAS,KAChCA,SAAQ,kBAAkB,WAC1B,CAAC,cAAcA,SAAQ,YAAY,KACnCA,SAAQ,wBAAwB,mBAChC,CAAC,iCAAiCA,SAAQ,oBAAoB,KAC9D,CAAC,SAASA,SAAQ,SAAS,KAC3B,OAAOA,SAAQ,kBAAkB,YAAY,CAAC,OAAO,KAAKA,SAAQ,aAAa,KAC9EA,SAAQ,cAAc,UAAa,CAAC,cAAcA,SAAQ,SAAS,KACnEA,SAAQ,mBAAmB,UAAa,CAAC,cAAcA,SAAQ,gBAAgB,GAAK,EACrF,QAAO;AAET,UAAM,WAAWA,SAAQ;AACzB,UAAM,YAAYA,SAAQ;AAC1B,QACE,SAAS,OAAOA,SAAQ,cACxB,SAAS,WAAWA,SAAQ,UAC5BA,SAAQ,eAAeA,SAAQ,aAC/B,UAAU,qBAAqBA,SAAQ,cACvC,UAAU,iBAAiBA,SAAQ,gBACnC,UAAU,8BAA8BA,SAAQ,eAChDA,SAAQ,iBAAiB,kBAAkB,SAAS,KACpD,UAAU,aAAaA,SAAQ,aAC9BA,SAAQ,eAAe,cAAcA,SAAQ,cAAc,UAC3DA,SAAQ,eAAe,cAAc,SAAS,SAAS,aAAa,CAACA,SAAQ,aAC7E,SAAS,SAAS,aAAaA,SAAQ,cAAc,OACtD,QAAO;AAET,UAAM,EAAE,cAAc,GAAG,eAAe,IAAI;AAC5C,QAAK,MAAM,gBAAgB,cAAc,MAAO,aAAc,QAAO;AACrE,UAAM,iBAAiB,MAAM,gBAAgB;AAAA,MAC3C,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,YAAYA,SAAQ;AAAA,MACpB,gBAAgBA,SAAQ,kBAAkB;AAAA,MAC1C,WAAWA,SAAQ,aAAa;AAAA,MAChC,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,mBAAmBA,SAAQ,aAAc,QAAO;AACpD,QAAK,MAAM,gBAAgB,EAAE,QAAQA,SAAQ,QAAQ,YAAYA,SAAQ,WAAW,CAAC,MACnF,UAAU,eAAgB,QAAO;AAEnC,UAAM,EAAE,eAAe,GAAG,UAAU,IAAIA;AACxC,WAAQ,MAAM,gBAAgB,SAAS,MAAO;AAAA,EAChD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC/OO,IAAM,mCAAmC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA6CA,IAAM,UAAU;AAGT,SAAS,2BACd,QACQ;AACR,SAAO,OAAO,aACV,GAAG,OAAO,MAAM,IAAI,OAAO,UAAU,KACrC,OAAO;AACb;AAGO,SAAS,+BACd,QACQ;AACR,SAAO,GAAG,OAAO,IAAI,IAAI,2BAA2B,MAAM,CAAC;AAC7D;AAGO,SAAS,8BACd,OACuC;AACvC,MAAI;AACJ,MAAI;AACF,UAAM,iBAAiB,MACnB,MAAM,aAAa,IAAI,UAAU,IACjC,IAAI,IAAI,OAAO,uBAAuB,EAAE,aAAa,IAAI,UAAU;AAAA,EACzE,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,CAAC,MAAM,QAAQ,YAAY,KAAK,IAAI,IAAI,MAAM,GAAG;AACvD,MACE,UAAU,UACV,CAAC,iCAAiC;AAAA,IAChC;AAAA,EACF,KACA,CAAC,UACD,CAAC,QAAQ,KAAK,MAAM,EACpB,QAAO;AACT,QAAM,YAAY;AAClB,MAAI,cAAc,cAAc;AAC9B,WAAO,eAAe,SAAY,EAAE,MAAM,WAAW,OAAO,IAAI;AAAA,EAClE;AACA,SAAO,cAAc,QAAQ,KAAK,UAAU,IACxC,EAAE,MAAM,WAAW,QAAQ,WAAW,IACtC;AACN;AAGO,SAAS,6BACd,SACA,QACA,WAAW,KACH;AACR,QAAM,OAAO,IAAI,IAAI,QAAQ,MAAM;AACnC,OAAK,WAAW,SAAS,WAAW,GAAG,IAAI,WAAW,IAAI,QAAQ;AAClE,OAAK,aAAa,IAAI,YAAY,+BAA+B,MAAM,CAAC;AACxE,SAAO,KAAK,SAAS;AACvB;;;ACvGA,IAAM,UAAU;AAqBT,SAAS,cAAc,OAAmC;AAC/D,QAAM,OAAO,UAAU,MAAM,MAAM,QAAQ,EAAE;AAC7C,MAAI,CAAC,QAAQ,KAAK,IAAI;AACpB,UAAM,IAAI,gBAAgB,2DAA2D;AACvF,QAAM,OAAO,UAAU,MAAM,MAAM,QAAQ,GAAG;AAC9C,QAAM,UAAU,UAAU,MAAM,SAAS,WAAW,GAAG;AACvD,QAAM,sBAAsB,UAAU,MAAM,qBAAqB,uBAAuB,GAAG;AAC3F,QAAM,YAAY,MAAM,KAAK,oBAAI,IAAI,CAAC,SAAS,GAAG,MAAM,UAAU,IAAI,CAAC,IAAI,UACzE,UAAU,IAAI,aAAa,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9C,MAAI,UAAU,SAAS;AACrB,UAAM,IAAI,gBAAgB,2CAA2C;AACvE,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,MAAM;AAAA,MACV,OAAO;AAAA,QACL,IAAI,MAAM;AAAA,QACV,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA,oBAAoB;AAAA,QACpB,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM;AAAA,QACjB,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACF;AAIA,IAAM,YAAY,oBAAI,IAAI,CAAC,QAAQ,UAAU,aAAa,SAAS,CAAC;AACpE,IAAM,YAAY,oBAAI,IAAI,CAAC,aAAa,SAAS,CAAC;AAElD,SAAS,kBAAkB,KAAa,OAAyB;AAC/D,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,UAAU,OAAO,QAAQ,GAAG;AAAA,IACrC,KAAK;AACH,UAAI,OAAO,UAAU,YAAY,CAAE,cAAoC,SAAS,KAAK;AACnF,cAAM,IAAI,gBAAgB,0BAA0B,cAAc,KAAK,IAAI,CAAC,EAAE;AAChF,aAAO;AAAA,IACT,KAAK;AACH,aAAO,UAAU,OAAO,aAAa,GAAG;AAAA,IAC1C,KAAK;AACH,aAAO,UAAU,OAAO,WAAW,GAAI;AAAA,IACzC;AACE,aAAO;AAAA,EACX;AACF;AAQO,SAAS,cACd,QACA,OACA,KACW;AACX,QAAM,QAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAC3B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,UAAU,OAAW;AACzB,QAAI,CAAC,UAAU,IAAI,GAAG,EAAG,OAAM,IAAI,gBAAgB,uBAAuB,GAAG,EAAE;AAC/E,QAAI,UAAU,MAAM;AAClB,UAAI,CAAC,UAAU,IAAI,GAAG,EAAG,OAAM,IAAI,gBAAgB,GAAG,GAAG,oCAAoC;AAC7F,cAAQ,KAAK,GAAG;AAChB;AAAA,IACF;AACA,UAAM,GAAG,IAAI,kBAAkB,KAAK,KAAK;AAAA,EAC3C;AACA,MAAI,OAAO,KAAK,KAAK,EAAE,WAAW,KAAK,QAAQ,WAAW,EAAG,QAAO,CAAC;AACrE,QAAM,MAAiB;AAAA,IACrB,EAAE,GAAG,UAAU,IAAI,SAAS,MAAM,IAAI,QAAQ,OAAO,EAAE,GAAG,OAAO,WAAW,IAAI,EAAE;AAAA,EACpF;AACA,MAAI,QAAQ,SAAS,EAAG,KAAI,KAAK,EAAE,GAAG,WAAW,IAAI,SAAS,MAAM,IAAI,QAAQ,OAAO,QAAQ,CAAC;AAChG,SAAO;AACT;AAiBO,SAAS,kBACd,MACA,cACA,UACA,KACW;AACX,QAAM,YAAY,MAAM,KAAK,oBAAI,IAAI,CAAC,KAAK,SAAS,GAAG,YAAY,CAAC,CAAC;AACrE,QAAM,MAAiB;AAAA,IACrB,EAAE,GAAG,UAAU,IAAI,SAAS,MAAM,IAAI,KAAK,IAAI,OAAO,EAAE,WAAW,WAAW,IAAI,EAAE;AAAA,EACtF;AACA,QAAM,MAAM,CAAC,IAAY,SAAiC;AACxD,eAAW,OAAO,QAAQ,CAAC,EAAG,KAAI,KAAK,EAAE,GAAG,UAAU,IAAI,IAAI,IAAI,IAAI,OAAO,EAAE,UAAU,UAAU,EAAE,CAAC;AAAA,EACxG;AACA,MAAI,SAAS,SAAS,SAAS,QAAQ;AACvC,MAAI,SAAS,SAAS,SAAS,QAAQ;AACvC,MAAI,SAAS,UAAU,SAAS,SAAS;AACzC,MAAI,SAAS,OAAO,SAAS,MAAM;AACnC,SAAO;AACT;;;AC3IO,SAAS,WAAW,QAAgB,MAA2B;AACpE,SAAO,GAAG,MAAM,IAAI,IAAI;AAC1B;AAsBO,SAAS,iBAAiB,OAAsC;AACrE,QAAM,SAAS,MAAM,UAAU;AAC/B,MAAI,CAAE,iBAAuC,SAAS,MAAM;AAC1D,UAAM,IAAI,gBAAgB,0BAA0B,iBAAiB,KAAK,IAAI,CAAC,EAAE;AACnF,QAAM,UAAU,qBAAqB,MAAM,MAAM,MAAM,OAAO;AAC9D,MACE,WAAW,eACV,CAAC,MAAM,qBAAqB,CAAC,MAAM,sBACpC,OAAM,IAAI,gBAAgB,uDAAuD;AACnF,QAAM,MAAM,WAAW,MAAM,QAAQ,MAAM,IAAI;AAC/C,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,EAAE,IAAI,SAAS,SAAS,MAAM,OAAO,OAAO,IAAI;AAAA,MACpD,OAAO;AAAA,QACL;AAAA,QACA,QAAQ,MAAM;AAAA,QACd,MAAM,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM;AAAA,QACjB,GAAI,MAAM,oBACN,EAAE,mBAAmB,UAAU,MAAM,mBAAmB,qBAAqB,GAAG,EAAE,IAClF,CAAC;AAAA,QACL,GAAI,MAAM,uBACN,EAAE,sBAAsB,UAAU,MAAM,sBAAsB,wBAAwB,EAAE,EAAE,IAC1F,CAAC;AAAA,MACP;AAAA,IACF;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,EAAE,IAAI,SAAS,SAAS,MAAM,OAAO,OAAO,IAAI;AAAA,MACpD,OAAO;AAAA,MACP,QAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AACF;AAoBA,eAAsB,kBAAkB,OAAgD;AACtF,MAAI,MAAM,YAAY,SAAS;AAC7B,UAAM,IAAI,gBAAgB,0CAA0C;AACtE,QAAM,WAAW;AAAA,IACf,IAAI,MAAM;AAAA,IACV,QAAQ,MAAM;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,QAAQ;AAAA,IACR,SAAS,EAAE,SAAS,qBAAqB,MAAM,MAAM,MAAM,OAAO,EAAE;AAAA,IACpE,WAAW,UAAU,MAAM,WAAW,aAAa,GAAI;AAAA,IACvD,YAAY;AAAA,MACV,eAAe,MAAM,aAAa,WAAW;AAAA,MAC7C,aAAa,MAAM,eAAe;AAAA,MAClC,WAAW,UAAU,MAAM,WAAW,aAAa,GAAG;AAAA,MACtD,QAAQ,UAAU,MAAM,QAAQ,UAAU,GAAG;AAAA,MAC7C,aAAa,CAAC,GAAG,IAAI,IAAI,MAAM,YAAY,IAAI,CAAC,OAAO,UACrD,UAAU,OAAO,eAAe,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK;AAAA,IAC3D;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,qBAAqB,MAAM;AAAA,IAC3B,WAAW,MAAM;AAAA,EACnB;AACA,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,MAAM;AAAA,MACV,OAAO,EAAE,GAAG,UAAU,cAAc,MAAM,gBAAgB,QAAQ,EAAE;AAAA,IACtE;AAAA,IACA,EAAE,GAAG,QAAQ,IAAI,SAAS,UAAU,IAAI,MAAM,IAAI,OAAO,QAAQ,QAAQ,MAAM,OAAO;AAAA,EACxF;AACF;;;ACpFA,eAAsB,kBAAkB,OAAgD;AACtF,QAAM,OAAO,UAAU,MAAM,MAAM,QAAQ,GAAG;AAC9C,QAAM,YAAY,UAAU,MAAM,WAAW,aAAa,GAAI;AAC9D,QAAM,WAAW,eAAe,MAAM,QAAQ;AAC9C,QAAM,UAAU,MAAM,YAAY,SAAY,SAAY,UAAU,MAAM,SAAS,SAAS;AAC5F,MAAI,MAAM,YAAY,SAAS;AAC7B,UAAM,IAAI,gBAAgB,0CAA0C;AACtE,QAAM,UAAmC;AAAA,IACvC;AAAA,IACA;AAAA,IACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B,GAAI,MAAM,mBAAmB,SAAY,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,EACvF;AACA,QAAM,WAAW;AAAA,IACf,IAAI,MAAM;AAAA,IACV,QAAQ,MAAM;AAAA,IACd,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,YAAY;AAAA,MACV,eAAe,MAAM,aAAa,WAAW;AAAA,MAC7C,aAAa,MAAM,eAAe;AAAA,MAClC,WAAW,UAAU,MAAM,WAAW,aAAa,GAAG;AAAA,MACtD,QAAQ,UAAU,MAAM,QAAQ,UAAU,GAAG;AAAA,MAC7C,aAAa,CAAC,GAAG,IAAI,IAAI,MAAM,YAAY,IAAI,CAAC,OAAO,UACrD,UAAU,OAAO,eAAe,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK;AAAA,IAC3D;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,qBAAqB,MAAM;AAAA,IAC3B,WAAW,MAAM;AAAA,EACnB;AACA,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,MAAM;AAAA,MACV,OAAO,EAAE,GAAG,UAAU,cAAc,MAAM,gBAAgB,QAAQ,EAAE;AAAA,IACtE;AAAA,IACA,EAAE,GAAG,QAAQ,IAAI,SAAS,UAAU,IAAI,MAAM,IAAI,OAAO,QAAQ,QAAQ,MAAM,OAAO;AAAA,EACxF;AACF;AAwBO,SAAS,kBAAkB,OAAuC;AACvE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,MAAI,SAAS,SAAS;AACpB,UAAM,IAAI,gBAAgB,YAAY,SAAS,EAAE,SAAS,SAAS,IAAI,0BAA0B;AACnG,MAAI,SAAS,WAAW;AACtB,UAAM,IAAI,gBAAgB,YAAY,SAAS,EAAE,OAAO,SAAS,MAAM,YAAY;AACrF,QAAM,UAAU,SAAS;AACzB,QAAM,OAAO,UAAU,QAAQ,MAAM,gBAAgB,GAAG;AACxD,QAAM,WAAW,eAAe,QAAQ,QAAQ;AAChD,QAAM,UAAU,QAAQ,YAAY,SAAY,SAAY,UAAU,QAAQ,SAAS,iBAAiB;AACxG,QAAM,SAAS,SAAS,WAAW,cAAc,cAAc,UAAU,YAAY;AACrF,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,WAAW,SAAS;AAAA,QACpB,YAAY,SAAS;AAAA,QACrB,mBAAmB,UAAU,mBAAmB,qBAAqB,GAAG;AAAA,QACxE,sBAAsB;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,UAAU,SAAS;AAAA,QACnB,WAAW;AAAA,QACX,WAAW;AAAA,QACX,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,EAAE,GAAG,QAAQ,IAAI,SAAS,SAAS,IAAI,WAAW,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAAA,IACzF,GAAG,iBAAiB;AAAA,MAClB,QAAQ,SAAS;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,WAAW,MAAM,SAAS;AAAA,MACrC,QAAQ;AAAA,MACR,UAAU,SAAS;AAAA,MACnB,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,iBAAiB,WAAW,WAAW,IAAI;AAAA,IACtD;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,QACL,QAAQ;AAAA,QACR;AAAA,QACA,YAAY;AAAA,QACZ,GAAI,MAAM,iBAAiB,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,kBAAkB,OAAuC;AACvE,QAAM,EAAE,UAAU,YAAY,IAAI,IAAI;AACtC,MAAI,SAAS,WAAW;AACtB,UAAM,IAAI,gBAAgB,YAAY,SAAS,EAAE,OAAO,SAAS,MAAM,YAAY;AACrF,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,QACL,QAAQ;AAAA,QACR;AAAA,QACA,YAAY;AAAA,QACZ,GAAI,MAAM,iBAAiB,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;;;ACjLO,SAAS,eAAe,OAAoC;AACjE,MAAI,CAAE,YAAkC,SAAS,MAAM,IAAI;AACzD,UAAM,IAAI,gBAAgB,wBAAwB,YAAY,KAAK,IAAI,CAAC,EAAE;AAC5E,QAAM,cAAc,uBAAuB,MAAM,aAAa,MAAM,IAAI;AAIxE,MAAI,MAAM,SAAS,qBAAqB,MAAM,WAAW;AACvD,UAAM,IAAI,gBAAgB,6CAA6C;AACzE,MAAI,MAAM,SAAS,qBAAqB,MAAM,WAAW;AACvD,UAAM,IAAI,gBAAgB,QAAQ,iBAAiB,mCAAmC;AACxF,MAAI,OAAO,MAAM,SAAS,YAAY,CAAC,OAAO,SAAS,MAAM,IAAI,KAAK,MAAM,QAAQ;AAClF,UAAM,IAAI,gBAAgB,oCAAoC;AAChE,MAAI,CAAC,wBAAwB,KAAK,MAAM,aAAa;AACnD,UAAM,IAAI,gBAAgB,wCAAwC;AACpE,QAAM,QAAQ,MAAM,UAAU,SAAY,SAAY,UAAU,MAAM,OAAO,SAAS,GAAG;AACzF,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI,MAAM;AAAA,MACV,OAAO;AAAA,QACL,IAAI,MAAM;AAAA,QACV,QAAQ,MAAM;AAAA,QACd,MAAM,MAAM;AAAA,QACZ,MAAM,UAAU,MAAM,MAAM,QAAQ,GAAG;AAAA,QACvC,iBAAiB,UAAU,MAAM,iBAAiB,mBAAmB,GAAG;AAAA,QACxE,eAAe,UAAU,MAAM,eAAe,iBAAiB,EAAE;AAAA,QACjE;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,YAAY,MAAM;AAAA,QAClB,sBAAsB;AAAA,UACpB,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAAA,QACA,WAAW,MAAM;AAAA,QACjB,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,QACzB,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MACjD;AAAA,IACF;AAAA,IACA,EAAE,GAAG,QAAQ,IAAI,SAAS,OAAO,IAAI,MAAM,IAAI,OAAO,QAAQ,QAAQ,MAAM,OAAO;AAAA,EACrF;AACF;AAOO,SAAS,oBACd,SACA,KACA,WACA,qBACW;AACX,SAAO,CAAC;AAAA,IACN,GAAG;AAAA,IACH,IAAI,SAAS;AAAA,IACb,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,WAAW,UAAU,WAAW,aAAa,GAAG;AAAA,MAChD,qBAAqB,UAAU,qBAAqB,uBAAuB,GAAG;AAAA,IAChF;AAAA,EACF,CAAC;AACH;AAGO,SAAS,qBAAqB,SAAoC;AACvE,SAAO,CAAC;AAAA,IACN,GAAG;AAAA,IACH,IAAI,SAAS;AAAA,IACb,IAAI;AAAA,IACJ,OAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B,CAAC;AACH;AAMA,eAAsB,kBACpB,SACA,UACA,eACA,YACA,sBACA,KACoB;AACpB,MAAI,CAAC,OAAO,cAAc,aAAa,KAAK,gBAAgB;AAC1D,UAAM,IAAI,gBAAgB,wDAAwD;AACpF,QAAM,aAAa,eAAe,QAAQ;AAC1C,SAAO;AAAA,IACL;AAAA,MACE,GAAG;AAAA,MACH,IAAI,SAAS;AAAA,MACb,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,UAAU;AAAA,QACV,kBAAkB,gBAAgB;AAAA,QAClC,gBAAgB,MAAM,gBAAgB,UAAU;AAAA,QAChD,YAAY,UAAU,YAAY,cAAc,GAAG;AAAA,QACnD,sBAAsB;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,YAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;;;AC5IO,IAAM,sBAAsB;AAMnC,SAAS,OAAO,MAAc,MAAiC;AAC7D,QAAM,OAAO,2BAA2B,IAAI;AAC5C,QAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,MAAI,QAAQ,EAAG,QAAO;AACtB,QAAM,OAAO,QAAQ,KAAK;AAC1B,QAAM,MAAM,KAAK,QAAQ,aAAa,IAAI;AAC1C,SAAO,MAAM,IAAI,OAAO,KAAK,MAAM,MAAM,GAAG;AAC9C;AAQO,SAAS,eAAe,MAAuB;AACpD,SACE,KAAK,SAAS,oCAAoC,KAClD,KAAK,SAAS,oCAAoC;AAEtD;AAGO,SAAS,iBAAiB,MAAsB;AACrD,QAAM,MAAM,KAAK;AACjB,MAAI,QAAQ,EAAG,QAAO;AACtB,QAAM,MAAM,KAAK,SAAS,IAAI,IAAI,IAAI,KAAK,SAAS,GAAG,IAAI,IAAI;AAC/D,SAAO,KAAK,IAAI,GAAG,KAAK,MAAO,MAAM,IAAK,CAAC,IAAI,GAAG;AACpD;AAEA,SAAS,gBAAgB,MAAc,MAA2B;AAChE,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,gBAAgB,mBAAmB,IAAI,2BAA2B;AAAA,EAC9E;AACF;AAEA,IAAMC,YAAW,CAAC,MAChB,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAGzD,SAAS,WAAW,KAAmC;AACrD,MAAI,CAACA,UAAS,GAAG,EAAG,OAAM,IAAI,gBAAgB,mDAAmD;AACjG,QAAM,SAA8B,CAAC;AACrC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,QAAI,CAACA,UAAS,KAAK,EAAG;AACtB,UAAM,OAAO,MAAM;AACnB,UAAM,OAAO,MAAM;AACnB,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,SAAU;AAC1D,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM,KAAK,MAAM,GAAG,GAAG;AAAA,MACvB,OAAO,iBAAiB,IAAI;AAAA,MAC5B,YAAY,MAAM,eAAe;AAAA,IACnC,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,SAAS,cAAc,KAAwB;AAC7C,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO,CAAC;AAC/C,MAAI,CAAC,MAAM,QAAQ,GAAG;AACpB,UAAM,IAAI,gBAAgB,uDAAuD;AACnF,QAAM,MAAgB,CAAC;AACvB,aAAW,SAAS,KAAK;AACvB,QAAIA,UAAS,KAAK,KAAK,OAAO,MAAM,OAAO,SAAU,KAAI,KAAK,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;AAAA,EACtF;AACA,SAAO;AACT;AAGA,SAAS,cAAc,KAAwB;AAC7C,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO,CAAC;AAC/C,MAAI,CAAC,MAAM,QAAQ,GAAG;AACpB,UAAM,IAAI,gBAAgB,oDAAoD;AAChF,SAAO,IAAI,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AAC7D;AAQO,SAAS,oBAAoB,MAAkC;AACpE,QAAM,SAAS,KAAK,QAAQ,qBAAqB;AACjD,MAAI,SAAS,EAAG,QAAO;AACvB,QAAM,OAAO,KAAK,QAAQ,QAAQ,MAAM;AACxC,MAAI,OAAO,EAAG,QAAO;AACrB,QAAM,QAAQ,KAAK,QAAQ,UAAU,IAAI;AACzC,MAAI,QAAQ,EAAG,QAAO;AACtB,QAAM,MAAM,KAAK,MAAM,MAAM,QAAQ,SAAS,MAAM;AACpD,SAAO,IAAI,SAAS,sBAAsB,SAAY;AACxD;AAmBO,SAAS,mBAAmB,MAAmD;AACpF,QAAM,MAAM,OAAO,MAAM,UAAU;AACnC,MAAI,QAAQ,KAAM,OAAM,IAAI,gBAAgB,sCAAsC;AAClF,QAAM,SAAS,gBAAgB,KAAK,UAAU;AAC9C,MAAI,CAACA,UAAS,MAAM,EAAG,OAAM,IAAI,gBAAgB,mDAAmD;AACpG,QAAM,MAA2C,CAAC;AAClD,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,QAAI,CAACA,UAAS,KAAK,EAAG;AACtB,UAAM,EAAE,MAAM,KAAK,IAAI;AACvB,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,SAAU;AAC1D,QAAI,IAAI,IAAI,EAAE,MAAM,YAAY,MAAM,eAAe,MAAM,KAAK;AAAA,EAClE;AACA,SAAO;AACT;AAWO,SAAS,kBAAkB,MAA4B;AAC5D,MAAI,CAAC,eAAe,IAAI;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AACF,QAAM,cAAc,OAAO,MAAM,UAAU;AAC3C,MAAI,gBAAgB;AAClB,UAAM,IAAI,gBAAgB,iDAAiD;AAC7E,QAAM,WAAW,gBAAgB,aAAa,UAAU;AACxD,MAAI,OAAO,aAAa;AACtB,UAAM,IAAI,gBAAgB,uDAAuD;AAEnF,QAAM,cAAc,OAAO,MAAM,UAAU;AAC3C,MAAI,gBAAgB;AAClB,UAAM,IAAI,gBAAgB,iDAAiD;AAE7E,QAAM,SAAS,OAAO,MAAM,eAAe;AAC3C,QAAM,UAAU,OAAO,MAAM,YAAY;AACzC,QAAM,eAAe,oBAAoB,IAAI;AAC7C,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,WAAW,gBAAgB,aAAa,UAAU,CAAC;AAAA,IAC3D,WAAW,cAAc,WAAW,OAAO,OAAO,gBAAgB,QAAQ,eAAe,CAAC;AAAA,IAC1F,WAAW,cAAc,YAAY,OAAO,OAAO,gBAAgB,SAAS,YAAY,CAAC;AAAA,IACzF,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,EACzC;AACF;;;AC9JO,SAAS,iBAAiB,KAAqB;AACpD,MAAI,MAAM;AACV,MAAI,IAAI;AACR,aAAS;AACP,UAAM,QAAQ,IAAI,QAAQ,MAAM,CAAC;AACjC,QAAI,QAAQ,EAAG,QAAO,MAAM,IAAI,MAAM,CAAC;AACvC,WAAO,IAAI,MAAM,GAAG,KAAK;AACzB,UAAM,MAAM,IAAI,QAAQ,MAAM,QAAQ,CAAC;AACvC,QAAI,MAAM,EAAG,QAAO;AACpB,QAAI,MAAM;AAAA,EACZ;AACF;AAOO,SAAS,eAAe,MAAsB;AACnD,QAAM,QAAkB,CAAC;AACzB,MAAI,IAAI;AACR,aAAS;AACP,UAAM,OAAO,KAAK,QAAQ,UAAU,CAAC;AACrC,QAAI,OAAO,EAAG;AACd,UAAM,KAAK,KAAK,QAAQ,KAAK,IAAI;AACjC,QAAI,KAAK,EAAG;AACZ,UAAM,QAAQ,KAAK,QAAQ,YAAY,EAAE;AACzC,QAAI,QAAQ,EAAG;AACf,UAAM,KAAK,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC;AACpC,QAAI,QAAQ,WAAW;AAAA,EACzB;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAUO,SAAS,qBAAqB,KAAmC;AACtE,QAAM,OAAO,iBAAiB,GAAG;AACjC,QAAM,QAA8B,CAAC;AACrC,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ;AACZ,MAAI,QAAQ;AAEZ,QAAM,QAAQ,CAAC,QAAsB;AACnC,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,QAAQ,KAAK,MAAM,OAAO,GAAG,EAAE,KAAK;AAC1C,QAAI,CAAC,MAAM,WAAW,IAAI,EAAG;AAC7B,UAAM,QAAQ,MAAM,QAAQ,GAAG;AAC/B,QAAI,QAAQ,EAAG;AACf,UAAM,OAAO,MAAM,MAAM,GAAG,KAAK,EAAE,KAAK;AACxC,QAAI,KAAK,SAAS,EAAG;AACrB,UAAM,KAAK,EAAE,WAAW,CAAC,GAAG,KAAK,GAAG,MAAM,OAAO,MAAM,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;AAAA,EAClF;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,OAAO,IAAK;AAAA,aACP,OAAO,IAAK,SAAQ,KAAK,IAAI,GAAG,QAAQ,CAAC;AAClD,QAAI,UAAU,EAAG;AACjB,QAAI,OAAO,KAAK;AACd,YAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC;AACtC,cAAQ,IAAI;AAAA,IACd,WAAW,OAAO,KAAK;AACrB,YAAM,CAAC;AACP,YAAM,IAAI;AACV,cAAQ,IAAI;AAAA,IACd,WAAW,OAAO,KAAK;AACrB,YAAM,CAAC;AACP,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;;;ACjFO,SAAS,QAAQ,GAAmB;AACzC,SAAO,OAAO,MAAM,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AACvD;AAEA,IAAM,OAAO;AACb,IAAM,OAAO;AACb,IAAMC,aAAY;AAQX,SAAS,SAAS,KAAkB;AACzC,QAAM,IAAI,IAAI,KAAK,EAAE,YAAY;AACjC,MAAIA,WAAU,KAAK,CAAC,GAAG;AACrB,UAAM,IAAI;AAAA,MACR,wBAAwB,GAAG;AAAA,IAC7B;AAAA,EACF;AACA,MAAI,KAAK,KAAK,CAAC,GAAG;AAChB,WAAO;AAAA,MACL,GAAG,SAAS,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,IAAI;AAAA,MACjC,GAAG,SAAS,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,IAAI;AAAA,MACjC,GAAG,SAAS,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,IAAI;AAAA,IACnC;AAAA,EACF;AACA,MAAI,KAAK,KAAK,CAAC,GAAG;AAChB,WAAO;AAAA,MACL,GAAG,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAAA,MACjC,GAAG,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAAA,MACjC,GAAG,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAAA,IACnC;AAAA,EACF;AACA,QAAM,IAAI,WAAW,gDAAgD,GAAG,GAAG;AAC7E;AAGO,SAAS,MAAM,KAAkB;AACtC,QAAM,KAAK,CAAC,MACV,KAAK,MAAM,QAAQ,CAAC,IAAI,GAAG,EACxB,SAAS,EAAE,EACX,SAAS,GAAG,GAAG;AACpB,SAAO,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;AAC9C;AAGO,SAAS,aAAa,KAAqB;AAChD,SAAO,MAAM,SAAS,GAAG,CAAC;AAC5B;;;ACxBO,SAAS,aAAa,GAAmB;AAC9C,SAAO,KAAK,UAAU,IAAI,UAAU,IAAI,SAAS,UAAU;AAC7D;AAGO,SAAS,aAAa,GAAmB;AAC9C,SAAO,KAAK,WAAY,IAAI,QAAQ,QAAQ,MAAM,IAAI,OAAO;AAC/D;AAGO,SAAS,SAAS,EAAE,GAAG,GAAG,EAAE,GAAa;AAC9C,QAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;AAC5B,QAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;AAC5B,QAAM,KAAK,MAAM,OAAO;AACxB,QAAM,IAAI,MAAM;AAChB,MAAI,MAAM,EAAG,QAAO,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE;AACpC,QAAM,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC;AACrC,MAAI;AACJ,MAAI,QAAQ,EAAG,KAAI,OAAQ,IAAI,KAAK,IAAK;AAAA,WAChC,QAAQ,EAAG,KAAI,OAAO,IAAI,KAAK,IAAI;AAAA,MACvC,KAAI,OAAO,IAAI,KAAK,IAAI;AAC7B,SAAO,EAAE,IAAI,IAAI,OAAO,KAAK,GAAG,EAAE;AACpC;AAGO,SAAS,SAAS,EAAE,GAAG,GAAG,EAAE,GAAa;AAC9C,QAAM,OAAQ,IAAI,MAAO,OAAO;AAChC,QAAM,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK;AACtC,QAAM,IAAI,KAAK,IAAI,KAAK,IAAM,MAAM,KAAM,IAAK,CAAC;AAChD,QAAM,IAAI,IAAI,IAAI;AAClB,QAAM,WAA6D;AAAA,IACjE,CAAC,GAAG,GAAG,CAAC;AAAA,IACR,CAAC,GAAG,GAAG,CAAC;AAAA,IACR,CAAC,GAAG,GAAG,CAAC;AAAA,IACR,CAAC,GAAG,GAAG,CAAC;AAAA,IACR,CAAC,GAAG,GAAG,CAAC;AAAA,IACR,CAAC,GAAG,GAAG,CAAC;AAAA,EACV;AACA,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,SAAS,KAAK,MAAM,MAAM,EAAE,IAAI,CAAC;AACnD,SAAO,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AACxC;AAGO,SAAS,WAAW,EAAE,GAAG,GAAG,EAAE,GAAe;AAClD,QAAM,IAAI,aAAa,CAAC;AACxB,QAAM,IAAI,aAAa,CAAC;AACxB,QAAM,IAAI,aAAa,CAAC;AACxB,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,SAAO;AAAA,IACL,GAAG,eAAe,IAAI,cAAc,IAAI,eAAe;AAAA,IACvD,GAAG,eAAe,IAAI,cAAc,IAAI,eAAe;AAAA,IACvD,GAAG,eAAe,IAAI,eAAe,IAAI,cAAc;AAAA,EACzD;AACF;AAQO,SAAS,WAAW,EAAE,GAAG,GAAAC,IAAG,EAAE,GAAe;AAClD,QAAM,KAAK,IAAI,eAAeA,KAAI,eAAe,MAAM;AACvD,QAAM,KAAK,IAAI,eAAeA,KAAI,eAAe,MAAM;AACvD,QAAM,KAAK,IAAI,eAAeA,KAAI,cAAc,MAAM;AACtD,SAAO;AAAA,IACL,GAAG,aAAa,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAAA,IACtE,GAAG,aAAa,gBAAgB,IAAI,eAAe,IAAI,eAAe,CAAC;AAAA,IACvE,GAAG,aAAa,gBAAgB,IAAI,eAAe,IAAI,cAAc,CAAC;AAAA,EACxE;AACF;AAGO,SAAS,aAAa,EAAE,GAAG,GAAAA,IAAG,EAAE,GAAiB;AACtD,QAAM,IAAI,KAAK,MAAMA,IAAG,CAAC;AACzB,QAAM,IAAI,IAAI,OAAO,KAAM,KAAK,MAAM,GAAGA,EAAC,IAAI,MAAO,KAAK,KAAK,OAAO;AACtE,SAAO,EAAE,GAAG,GAAG,EAAE;AACnB;AAGO,SAAS,aAAa,EAAE,GAAG,GAAG,EAAE,GAAiB;AACtD,QAAM,MAAO,IAAI,KAAK,KAAM;AAC5B,SAAO,EAAE,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,EAAE;AACzD;AAGO,SAAS,WAAW,KAAoB;AAC7C,SAAO,aAAa,WAAW,SAAS,GAAG,CAAC,CAAC;AAC/C;AAOO,SAAS,WAAW,KAAoB;AAC7C,SAAO,MAAM,WAAW,aAAa,GAAG,CAAC,CAAC;AAC5C;AAEA,IAAM,YAAY;AAGX,SAAS,YAAY,EAAE,GAAG,GAAG,EAAE,GAAiB;AACrD,QAAM,KAAK,CAAC,MAAuB,KAAK,CAAC,aAAa,KAAK,IAAI;AAC/D,SAAO,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC;AAC/B;AASO,SAAS,aAAa,KAAmB;AAC9C,QAAM,IAAI,QAAQ,IAAI,CAAC;AACvB,QAAM,IAAI,IAAI;AACd,MAAI,YAAY,WAAW,aAAa,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,EAAG,QAAO,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE;AACvF,MAAI,KAAK;AACT,MAAI,KAAK,IAAI;AACb,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,OAAO,KAAK,MAAM;AACxB,QAAI,YAAY,WAAW,aAAa,EAAE,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAG,MAAK;AAAA,QAC7D,MAAK;AAAA,EACZ;AACA,SAAO,EAAE,GAAG,GAAG,IAAI,EAAE;AACvB;;;AC/JO,SAAS,kBAAkB,KAAqB;AACrD,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,SAAS,GAAG;AAChC,SAAO,SAAS,aAAa,CAAC,IAAI,SAAS,aAAa,CAAC,IAAI,SAAS,aAAa,CAAC;AACtF;AAGO,SAAS,cAAc,MAAc,MAAsB;AAChE,QAAM,KAAK,kBAAkB,IAAI;AACjC,QAAM,KAAK,kBAAkB,IAAI;AACjC,UAAQ,KAAK,IAAI,IAAI,EAAE,IAAI,SAAS,KAAK,IAAI,IAAI,EAAE,IAAI;AACzD;AAEA,IAAM,KAAmC,EAAE,MAAM,KAAK,cAAc,GAAG,IAAI,EAAE;AAC7E,IAAM,MAAmD,EAAE,MAAM,GAAG,cAAc,IAAI;AAO/E,SAAS,QAAQ,OAAe,OAAqB,QAAiB;AAC3E,SAAO,SAAS,GAAG,IAAI;AACzB;AAOO,SAAS,SAAS,OAAe,OAAoC,QAAiB;AAC3F,SAAO,SAAS,IAAI,IAAI;AAC1B;AASO,IAAM,+BAAkD,CAAC,WAAW,SAAS;AAS7E,SAAS,WACd,OACA,aAAgC,8BACxB;AACR,MAAI,WAAW,WAAW,EAAG,OAAM,IAAI,WAAW,0CAA0C;AAC5F,MAAI,OAAO,WAAW,CAAC;AACvB,MAAI,YAAY;AAChB,aAAW,aAAa,YAAY;AAClC,UAAM,QAAQ,cAAc,OAAO,SAAS;AAC5C,QAAI,QAAQ,WAAW;AACrB,aAAO;AACP,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;;;ACjEO,SAAS,UAAU,KAAa,SAAyB;AAC9D,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,GAAG;AAClC,SAAO,WAAW,aAAa,EAAE,GAAG,GAAG,KAAM,IAAI,WAAW,MAAO,OAAO,IAAI,CAAC,CAAC;AAClF;AAGO,SAAS,cAAc,KAAqB;AACjD,SAAO,UAAU,KAAK,GAAG;AAC3B;AAGO,SAAS,UAAU,KAAa,QAAQ,IAAsB;AACnE,SAAO,CAAC,UAAU,KAAK,CAAC,KAAK,GAAG,UAAU,KAAK,KAAK,CAAC;AACvD;AAGO,SAAS,QAAQ,KAA+B;AACrD,SAAO,CAAC,UAAU,KAAK,IAAI,GAAG,UAAU,KAAK,GAAG,CAAC;AACnD;AAGO,SAAS,mBAAmB,KAA+B;AAChE,SAAO,CAAC,UAAU,KAAK,IAAI,GAAG,UAAU,KAAK,GAAG,CAAC;AACnD;AAGO,SAAS,SAAS,KAAuC;AAC9D,SAAO,CAAC,UAAU,KAAK,EAAE,GAAG,UAAU,KAAK,GAAG,GAAG,UAAU,KAAK,GAAG,CAAC;AACtE;AASO,SAAS,WAAW,KAAa,QAAQ,GAAa;AAC3D,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI,WAAW,kDAAkD,KAAK,EAAE;AAAA,EAChF;AACA,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,GAAG;AAClC,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,QAAI,KAAK,WAAW,aAAa,EAAE,GAAG,GAAG,KAAK,IAAI,KAAK,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC;AAAA,EAC3E;AACA,SAAO;AACT;;;AC7CO,IAAM,aAAa;AAGnB,IAAM,aAAa;AAG1B,IAAM,eAAe;AAUd,SAAS,cAAc,KAAa,QAAQ,GAAa;AAC9D,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI,WAAW,qDAAqD,KAAK,EAAE;AAAA,EACnF;AACA,QAAM,EAAE,GAAG,EAAE,IAAI,WAAW,GAAG;AAC/B,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,IAAI,KAAK,QAAQ;AACvB,UAAM,IAAI,cAAc,aAAa,cAAc;AACnD,UAAM,QAAQ,gBAAgB,IAAI,iBAAiB,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC;AACzE,QAAI,KAAK,WAAW,aAAa,EAAE,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC;AAAA,EAC3D;AACA,SAAO;AACT;AAKA,IAAM,aAAa;AACnB,IAAM,eAAe;AAYd,SAAS,qBACd,KACA,WACA,WACe;AACf,QAAM,QAAQ,aAAa,GAAG;AAC9B,MAAI,UAAU,KAAK,EAAG,QAAO;AAC7B,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,KAAK;AACpC,QAAM,QAAQ,cAAc,YAAY,IAAI;AAC5C,QAAM,KAAK,CAAC,MAAsB,WAAW,aAAa,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;AACzE,MAAI,WAAW;AACf,MAAI,YAAY,OAAO;AACvB,WAAS,IAAI,GAAG,KAAK,YAAY,KAAK;AACpC,UAAM,IAAI,KAAM,QAAQ,KAAK,IAAK;AAClC,QAAI,UAAU,GAAG,CAAC,CAAC,GAAG;AACpB,kBAAY;AACZ;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,OAAO,MAAM,SAAS,EAAG,QAAO;AACpC,WAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACrC,UAAM,OAAO,WAAW,aAAa;AACrC,QAAI,UAAU,GAAG,GAAG,CAAC,EAAG,aAAY;AAAA,QAC/B,YAAW;AAAA,EAClB;AACA,SAAO,GAAG,SAAS;AACrB;;;ACpFO,SAAS,YAAY,GAAU,GAAkB;AACtD,SAAO,KAAK,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACnD;AAQO,SAAS,SAAS,MAAc,MAAsB;AAC3D,SAAO,YAAY,WAAW,SAAS,IAAI,CAAC,GAAG,WAAW,SAAS,IAAI,CAAC,CAAC;AAC3E;;;ACHA,IAAM,QAAkD;AAAA,EACtD,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,wBAAwB,SAAS;AAAA,EAClC,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,oBAAoB,SAAS;AAAA,EAC9B,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,kBAAkB,SAAS;AAAA,EAC5B,CAAC,mBAAmB,SAAS;AAAA,EAC7B,CAAC,qBAAqB,SAAS;AAAA,EAC/B,CAAC,mBAAmB,SAAS;AAAA,EAC7B,CAAC,mBAAmB,SAAS;AAAA,EAC7B,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,iBAAiB,SAAS;AAAA,EAC3B,CAAC,OAAO,SAAS;AAAA,EACjB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,YAAY,SAAS;AAAA,EACtB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,eAAe,SAAS;AAAA,EACzB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,OAAO,SAAS;AAAA,EACjB,CAAC,QAAQ,SAAS;AAAA,EAClB,CAAC,WAAW,SAAS;AAAA,EACrB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,aAAa,SAAS;AAAA,EACvB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,SAAS,SAAS;AAAA,EACnB,CAAC,cAAc,SAAS;AAAA,EACxB,CAAC,UAAU,SAAS;AAAA,EACpB,CAAC,eAAe,SAAS;AAC3B;AAMO,IAAM,mBAA0C,MAAM,IAAI,CAAC,CAAC,MAAM,GAAG,OAAO;AAAA,EACjF;AAAA,EACA;AACF,EAAE;AAQF,IAAI,WAA2B;AAWxB,SAAS,kBAAkB,KAAgC;AAChE,QAAM,SAAS,WAAW,SAAS,GAAG,CAAC;AACvC,eAAa,MAAM,IAAI,CAAC,CAAC,EAAEC,MAAK,MAAM,WAAW,SAASA,MAAK,CAAC,CAAC;AACjE,MAAI,UAAU;AACd,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,IAAI,YAAY,QAAQ,SAAS,CAAC,CAAE;AAC1C,QAAI,IAAI,OAAO;AACb,cAAQ;AACR,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,CAAC,MAAM,KAAK,IAAI,MAAM,OAAO;AACnC,SAAO,EAAE,MAAM,KAAK,OAAO,UAAU,MAAM;AAC7C;;;AC3KO,IAAM,kBAAkB;AAG/B,IAAM,UAAU;AAEhB,IAAM,UAAU;AAEhB,IAAM,aAAa;AAEnB,IAAM,eAAe;AAErB,IAAM,cAAc,EAAE,MAAM,KAAK,MAAM,IAAI,QAAQ,GAAG;AACtD,IAAM,WAAW;AACjB,IAAM,WAAW;AAEjB,IAAM,YAAY,CAAC,KAAK,KAAK,MAAM,KAAK,IAAI;AAqBrC,SAAS,kBAAkB,SAAiB,OAA2B,CAAC,GAAa;AAC1F,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,WAAW,KAAK,YAAY;AAClC,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI;AACvD,UAAM,IAAI,WAAW,6DAA6D,KAAK,EAAE;AAAA,EAC3F;AACA,QAAM,MAAM,WAAW,aAAa,OAAO,CAAC;AAC5C,QAAM,OAAO,IAAI,IAAI,eAAe,aAAa,IAAI;AACrD,QAAM,UAAU,CAAC,GAAG,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG;AACtE,QAAM,aAAa,QAAQ;AAAA,IAAI,CAAC,QAC9B,WAAW,aAAa,EAAE,GAAG,SAAS,GAAG,SAAS,IAAI,OAAO,OAAO,IAAI,CAAC,CAAC;AAAA,EAC5E;AACA,QAAM,SAAmB,CAAC;AAC1B,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,UAAU,MAAO;AAC5B,QAAI,OAAO,SAAS,GAAG,EAAG;AAC1B,QAAI,OAAO,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,KAAK,QAAQ,EAAG,QAAO,KAAK,GAAG;AAAA,EACxE;AACA,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,UAAU,MAAO;AAC5B,QAAI,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO,KAAK,GAAG;AAAA,EAC5C;AACA,SAAO;AACT;AAgBO,SAAS,cAAc,SAAiB,OAA6B,CAAC,GAAa;AACxF,QAAM,YAAY,KAAK,UAAU;AACjC,QAAM,OAAO,aAAa,OAAO;AACjC,QAAM,UAAU,WAAW,IAAI;AAC/B,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,MAAM,aAAa,aAAa,QAAQ;AAE9C,QAAM,YAAY,CAAC,GAAW,MAAsB,WAAW,aAAa,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;AAC7F,QAAM,KAAK,UAAU,OAAO,IAAK;AACjC,QAAM,UAAU,UAAU,OAAO,IAAK;AACtC,QAAM,OAAO,UAAU,MAAM,KAAK;AAClC,QAAM,UAAU,UAAU,MAAM,KAAK;AAErC,QAAM,aAAa,aACf;AAAA,IACE,aAAa,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,SAAS,GAAG,WAAW,CAAC;AAAA,EAC1F,IACA;AACJ,QAAM,QAAQ,UAAU,IAAI,CAAC,QAAQ;AACnC,UAAM,MAAM,UAAU,YAAY,GAAG;AACrC,WAAO,EAAE,KAAK,KAAK,GAAG,SAAS,MAAM,GAAG,EAAE;AAAA,EAC5C,CAAC;AACD,MAAI,YAAY,MAAM,CAAC;AACvB,aAAW,KAAK,MAAO,KAAI,EAAE,IAAI,UAAU,EAAG,aAAY;AAC1D,MAAI,YAAY,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,IAAK,MAAM,CAAC;AAC5D,MAAI,UAAU,KAAK,IAAI,UAAU,GAAG,SAAS,UAAU,KAAK,UAAU,GAAG,CAAC;AAC1E,aAAW,KAAK,OAAO;AACrB,QAAI,MAAM,aAAa,MAAM,UAAW;AACxC,UAAM,QAAQ,KAAK,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,UAAU,GAAG,CAAC;AAC1D,QAAI,QAAQ,SAAS;AACnB,kBAAY;AACZ,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,SAAS,CAAC,WAA2B;AACzC,UAAM,QAAQ,WAAW,aAAa,EAAE,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,CAAC;AAC9E,WAAO,qBAAqB,OAAO,CAAC,MAAM,cAAc,GAAG,EAAE,KAAK,GAAG,QAAQ,KAAK;AAAA,EACpF;AAEA,QAAM,KAAK,CAAC,MAAkB,KAAa,eAA+B;AAAA,IACxE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,WAAqB;AAAA,IACzB,GAAG,WAAW,MAAM,YAAY;AAAA,IAChC,GAAG,aAAa,UAAU,KAAK,oBAAoB,UAAU,GAAG,mBAAW,UAAU,EAAE,QAAQ,CAAC,CAAC,eAAe;AAAA,IAChH,GAAG,aAAa,UAAU,KAAK,oBAAoB,UAAU,GAAG,yCAAsC;AAAA,IACtG,GAAG,QAAQ,OAAO,YAAY,IAAI,GAAG,uCAA+B;AAAA,IACpE,GAAG,QAAQ,OAAO,YAAY,IAAI,GAAG,sCAA8B;AAAA,IACnE,GAAG,UAAU,OAAO,YAAY,MAAM,GAAG,oCAA4B;AAAA,IACrE,GAAG,MAAM,IAAI,qCAAqC;AAAA,IAClD,GAAG,WAAW,SAAS,mCAAmC;AAAA,IAC1D,GAAG,QAAQ,MAAM,qCAAqC;AAAA,IACtD,GAAG,WAAW,SAAS,yCAAyC;AAAA,IAChE,GAAG,kBAAkB,IAAI,EAAE,IAAI,CAAC,KAAK,MAAM,GAAG,SAAS,KAAK,gBAAgB,IAAI,CAAC,EAAE,CAAC;AAAA,EACtF;AACA,SAAO,YACH,SAAS,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,kBAAkB,EAAE,GAAG,EAAE,KAAK,EAAE,IACnE;AACN;;;ACxIO,IAAM,sBAAsB;AAGnC,IAAM,cAAc;AAGpB,IAAM,aAAa;AACnB,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,gBAAgB;AAItB,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,IAAM,aAAkD;AAAA,EAC7D,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAEA,IAAM,SAAS,CAAC,MAAc,QAC5B,0BAA0B,IAAI,KAAK,GAAG;AAGxC,SAAS,OAAO,KAAa,IAAoB;AAC/C,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,GAAG;AAClC,SAAO,WAAW,aAAa,EAAE,GAAG,QAAQ,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC;AAC9D;AAGA,SAAS,MAAM,SAAiBC,QAAe,GAAmB;AAChE,QAAMC,KAAI,WAAW,OAAO;AAC5B,QAAM,IAAI,WAAWD,MAAK;AAC1B,SAAO,WAAW,aAAa,EAAE,GAAGC,GAAE,KAAK,EAAE,IAAIA,GAAE,KAAK,GAAG,GAAGA,GAAE,GAAG,GAAGA,GAAE,EAAE,CAAC,CAAC;AAC9E;AAOA,SAAS,WAAW,KAAa,IAAY,KAAqB;AAChE,QAAM,OAAO,CAAC,MAAuB,cAAc,GAAG,EAAE,KAAK;AAC7D,QAAM,OACJ,kBAAkB,EAAE,KAAK,kBAAkB,GAAG,IAAI,WAAW;AAC/D,SACE,qBAAqB,KAAK,MAAM,IAAI,KACpC,qBAAqB,KAAK,MAAM,SAAS,WAAW,YAAY,QAAQ,KACxE,WAAW,EAAE;AAEjB;AAEA,IAAM,SAAS,CAAC,KAAa,UAA0B;AACrD,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,SAAS,GAAG;AAChC,QAAM,IAAI,CAAC,MAAsB,KAAK,MAAM,IAAI,GAAG;AACnD,SAAO,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK;AACjD;AAGA,SAAS,UAAU,QAA4B,OAAuB;AACpE,QAAM,IAAI,QAAQ,KAAK,KAAK;AAC5B,MAAI,MAAM,GAAI,QAAO;AACrB,MAAI,EAAE,SAAS,GAAG,KAAK,QAAQ,KAAK,CAAC,KAAK,0BAA0B,KAAK,CAAC;AACxE,WAAO,GAAG,CAAC,KAAK,KAAK;AACvB,SAAO,IAAI,EAAE,WAAW,KAAK,EAAE,CAAC,MAAM,KAAK;AAC7C;AAQA,SAAS,QAAQ,UAAmB,UAAqC;AACvE,QAAM,SAA8C,CAAC;AACrD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,aAAS,KAAK,EAAE,OAAO,eAAe,SAAS,oDAAoD,CAAC;AACpG,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AACA,EAAC,SAAkC,QAAQ,CAAC,GAAG,MAAM;AACnD,QAAI;AACJ,QAAI;AACF,YAAM,aAAa,OAAO,GAAG,GAAG,CAAC;AAAA,IACnC,QAAQ;AACN,eAAS,KAAK;AAAA,QACZ,OAAQ,GAAG,SAAS,UAAa,WAAW,EAAE,IAAI,KAAM;AAAA,QACxD,SAAS,YAAY,CAAC,0BAA0B,OAAO,GAAG,GAAG,CAAC;AAAA,MAChE,CAAC;AACD;AAAA,IACF;AACA,UAAM,OAAO,GAAG;AAChB,QAAI,SAAS,QAAS,QAAO,KAAK,GAAG;AAAA,aAC5B,SAAS,UAAa,SAAS,YAAY,OAAO,IAAI,MAAM,OAAW,QAAO,IAAI,IAAI;AAAA,EACjG,CAAC;AACD,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAgBO,SAAS,mBAAmB,OAAgC;AACjE,QAAM,WAA2B,CAAC;AAClC,QAAM,EAAE,QAAQ,OAAO,IAAI,QAAQ,OAAO,UAAU,QAAQ;AAE5D,MAAI,SAAS,OAAO;AACpB,MAAI,WAAW,QAAW;AACxB,UAAM,YAAY,CAAC,GAAG,OAAO,OAAO,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,MACtD,CAAC,MAAM,MAAM,UAAa,WAAW,CAAC,EAAE,KAAK;AAAA,IAC/C;AACA,aAAS,aAAa;AACtB,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,SAAS,4BAA4B,cAAc,SAAY,+BAA+B,0BAA0B,IAAI,MAAM;AAAA,IACpI,CAAC;AAAA,EACH;AAEA,QAAM,KAAK,oBAAI,IAAwB;AACvC,aAAW,KAAK,cAAc,QAAQ,EAAE,OAAO,MAAM,CAAC,EAAG,KAAI,CAAC,GAAG,IAAI,EAAE,IAAI,EAAG,IAAG,IAAI,EAAE,MAAM,EAAE,GAAG;AAClG,QAAM,OAAO,CAAC,SAA6B;AACzC,UAAM,MAAM,OAAO,IAAI;AACvB,QAAI,QAAQ,OAAW,QAAO;AAC9B,UAAM,UAAU,GAAG,IAAI,IAAI;AAC3B,aAAS,KAAK,EAAE,OAAO,WAAW,IAAI,GAAI,SAAS,MAAM,IAAI,oBAAoB,OAAO,SAAS,MAAM,GAAG,CAAC;AAC3G,WAAO;AAAA,EACT;AAEA,QAAM,KAAK,KAAK,IAAI;AACpB,QAAM,UAAU,KAAK,SAAS;AAC9B,QAAM,UAAU,KAAK,SAAS;AAC9B,QAAM,WAAW,OAAO,SAAS,MAAM;AAEvC,QAAM,UAAU,KAAK,MAAM;AAC3B,QAAM,OAAO,WAAW,SAAS,IAAI,GAAG;AACxC,MAAI,SAAS;AACX,aAAS,KAAK,EAAE,OAAO,aAAa,SAAS,sCAAsC,cAAc,QAAQ,CAAC;AAE5G,QAAM,eAAe,WAAW,QAAQ,IAAI,GAAG;AAC/C,MAAI,iBAAiB;AACnB,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAEH,QAAM,SAAS,CAAC,SAA6C;AAC3D,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAQ,WAAW,KAAK,IAAI,CAAC;AACnC,QAAI,UAAU;AACZ,eAAS,KAAK,EAAE,OAAO,WAAW,IAAI,GAAI,SAAS,oCAAoC,cAAc,IAAI,CAAC;AAC5G,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,OAAO,OAAO,CAAC,MAAM,WAAW,CAAC,EAAE,KAAK,WAAW;AAC3E,MAAI;AACJ,MAAI,gBAAgB,UAAU,GAAG;AAC/B,UAAM,SAAS,gBAAgB,MAAM,GAAG,CAAC;AACzC,eAAW,KAAK,kBAAkB,QAAQ,EAAE,OAAO,GAAG,CAAC,GAAG;AACxD,UAAI,OAAO,UAAU,EAAG;AACxB,UAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO,KAAK,CAAC;AAAA,IACxC;AACA,kBAAc;AAAA,EAChB,OAAO;AACL,aAAS,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,SAAS,0CAA0C,gBAAgB,MAAM;AAAA,IAC3E,CAAC;AACD,kBAAc;AAAA,EAChB;AAEA,QAAM,YAAY,OAAO;AACzB,MAAI,cAAc;AAChB,aAAS,KAAK,EAAE,OAAO,iBAAiB,SAAS,kFAAkF,CAAC;AACtI,QAAM,YAAY,OAAO;AACzB,MAAI,cAAc;AAChB,aAAS,KAAK,EAAE,OAAO,kBAAkB,SAAS,mFAAmF,CAAC;AAExI,QAAM,IAAI,OAAO,cAAc,CAAC;AAChC,QAAM,SAAsB;AAAA,IAC1B,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,mBAAmB,WAAW,MAAM,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG;AAAA,IAC5D,mBAAmB,MAAM,MAAM,IAAI,IAAI;AAAA,IACvC,eAAe,MAAM,SAAS,IAAI,IAAI;AAAA,IACtC,sBAAsB;AAAA,IACtB,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,oBAAoB,OAAO,eAAe,EAAE;AAAA,IAC5C,kBAAkB,WAAW,MAAM;AAAA,IACnC,aAAa,OAAO,MAAM;AAAA,IAC1B,kBAAkB,OAAO,aAAa,EAAE;AAAA,IACxC,aAAa,OAAO,MAAM;AAAA,IAC1B,kBAAkB,OAAO,aAAa,EAAE;AAAA,IACxC,eAAe,OAAO,QAAQ;AAAA,IAC9B,oBAAoB,OAAO,eAAe,EAAE;AAAA,IAC5C,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,eAAe,aAAa,OAAO,MAAM,IAAI,CAAC,gBAAgB,OAAO,MAAM,IAAI,CAAC;AAAA,IAChF,kBAAkB,UAAU,EAAE,UAAU,UAAU;AAAA,IAClD,mBAAmB;AAAA,IACnB,kBAAkB,UAAU,EAAE,UAAU,UAAU;AAAA,IAClD,qBAAqB,UAAU,EAAE,eAAe,EAAE,UAAU,aAAa;AAAA,IACzE,oBAAoB,OAAO,eAAe,EAAE;AAAA,IAC5C,iBAAiB,aAAa;AAAA,IAC9B,sBAAsB,OAAO,iBAAiB,EAAE;AAAA,IAChD,kBAAkB,aAAa;AAAA,IAC/B,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,gBAAgB,YAAY,CAAC;AAAA,IAC7B,gBAAgB,YAAY,CAAC;AAAA,IAC7B,gBAAgB,YAAY,CAAC;AAAA,IAC7B,gBAAgB,YAAY,CAAC;AAAA,IAC7B,gBAAgB,YAAY,CAAC;AAAA,IAC7B,gBAAgB,YAAY,CAAC;AAAA,IAC7B,mBAAmB,OAAO,eAAe,EAAE;AAAA,IAC3C,0BAA0B,OAAO,eAAe,EAAE;AAAA,IAClD,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,yBAAyB;AAAA,IACzB,2BAA2B;AAAA,IAC3B,yBAAyB;AAAA,EAC3B;AACA,SAAO,EAAE,QAAQ,SAAS;AAC5B;;;ACzRA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAoBO,SAAS,cAAc,OAA8B;AAC1D,QAAM,OAAO,MAAM,KAAK;AACxB,MAAI,KAAK,WAAW,GAAG,GAAG;AACxB,QAAI;AACF,aAAO,UAAU,IAAI;AAAA,IACvB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,KAAK,sBAAsB,KAAK,IAAI;AAC1C,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,SAAS,GAAG,CAAC,KAAK,IAAI,MAAM,SAAS,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACnE,MAAI,MAAM,SAAS,KAAK,MAAM,SAAS,EAAG,QAAO;AACjD,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,QAAQ,MAAM,CAAC,EAAG,SAAS,GAAG,IAChC,OAAO,WAAW,MAAM,CAAC,CAAE,IAAI,MAC/B,OAAO,WAAW,MAAM,CAAC,CAAE;AAC/B,QAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,QAAO;AAAA,EACnD;AACA,QAAM,WAAW,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS;AAC/C,UAAM,IAAI,OAAO,WAAW,IAAI;AAChC,QAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO,OAAO;AACvC,WAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAK,IAAI,MAAO,MAAM,CAAC;AAAA,EAC5D,CAAC;AACD,MAAI,SAAS,KAAK,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1E,SAAO,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC1E;AAEA,IAAM,aAAa,CAAC,UAClB,MAAM,SAAS,MAAM,IACjB,+BACA,MAAM,SAAS,YAAY,IACzB,8BACA,WAAW,KAAK,KAAK,IACnB,qBACA;AAUH,SAAS,yBAAyB,QAA8C;AACrF,QAAM,QAAQ,OAAO;AACrB,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAA6B,CAAC;AACpC,QAAMC,WAAwB,CAAC;AAE/B,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,UAAU,GAA6B;AAEhF,QAAI,SAAS,QAAS;AACtB,UAAM,QAAQ,MAAM,KAAK;AACzB,QAAI,UAAU,QAAW;AACvB,MAAAA,SAAQ,KAAK,IAAI;AACjB;AAAA,IACF;AACA,UAAM,MAAM,cAAc,KAAK;AAC/B,QAAI,QAAQ,MAAM;AAChB,cAAQ,KAAK,EAAE,OAAO,OAAO,QAAQ,WAAW,KAAK,EAAE,CAAC;AACxD;AAAA,IACF;AACA,aAAS,KAAK,EAAE,MAAM,KAAK,WAAW,6BAA6B,KAAK,GAAG,CAAC;AAAA,EAC9E;AAEA,MAAI,WAAW;AACf,aAAW,SAAS,cAAc;AAChC,UAAM,QAAQ,MAAM,KAAK;AACzB,QAAI,UAAU,OAAW;AACzB,UAAM,MAAM,cAAc,KAAK;AAC/B,QAAI,QAAQ,MAAM;AAChB,cAAQ,KAAK,EAAE,OAAO,OAAO,QAAQ,WAAW,KAAK,EAAE,CAAC;AACxD;AAAA,IACF;AACA,eAAW;AACX,aAAS,KAAK,EAAE,MAAM,SAAS,KAAK,WAAW,6BAA6B,KAAK,GAAG,CAAC;AAAA,EACvF;AACA,MAAI,CAAC,SAAU,CAAAA,SAAQ,KAAK,OAAO;AAEnC,SAAO,EAAE,UAAU,SAAS,SAAAA,SAAQ;AACtC;;;ACvHA,IAAM,iBAAyC;AAAA,EAC7C,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAGO,SAAS,eAAe,MAAsB;AACnD,SAAO,KAAK,QAAQ,sDAAsD,CAAC,OAAO,SAAiB;AACjG,QAAI,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,IAAI,GAAG;AAClD,YAAM,OAAO,OAAO,SAAS,KAAK,MAAM,CAAC,GAAG,EAAE;AAC9C,aAAO,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,QAAQ,UAAW,OAAO,cAAc,IAAI,IAAI;AAAA,IAC9F;AACA,QAAI,KAAK,WAAW,GAAG,GAAG;AACxB,YAAM,OAAO,OAAO,SAAS,KAAK,MAAM,CAAC,GAAG,EAAE;AAC9C,aAAO,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,QAAQ,UAAW,OAAO,cAAc,IAAI,IAAI;AAAA,IAC9F;AACA,WAAO,eAAe,KAAK,YAAY,CAAC,KAAK;AAAA,EAC/C,CAAC;AACH;AAGO,IAAM,qBAAqB,CAAC,SAAyB,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAOpF,SAAS,WAAW,UAA0B;AACnD,QAAM,cAAc,SACjB,QAAQ,0CAA0C,GAAG,EACrD,QAAQ,wCAAwC,GAAG;AACtD,SAAO,mBAAmB,eAAe,YAAY,QAAQ,YAAY,GAAG,CAAC,CAAC;AAChF;;;AC3CO,IAAM,sBAAsB;AAE5B,IAAM,oBAAoB;AAG1B,SAAS,aAAa,MAAkC;AAC7D,QAAM,QAAQ,+CAA+C,KAAK,IAAI;AACtE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,WAAW,MAAM,CAAC,KAAK,EAAE;AACtC,SAAO,SAAS,KAAK,SAAY,KAAK,MAAM,GAAG,iBAAiB;AAClE;AASO,SAAS,eAAe,MAAqE;AAClG,QAAM,UAAU;AAChB,QAAM,UAAgC,CAAC;AACvC,aAAS;AACP,UAAM,QAAQ,QAAQ,KAAK,IAAI;AAC/B,QAAI,UAAU,KAAM;AACpB,UAAM,OAAO,WAAW,MAAM,CAAC,KAAK,EAAE;AACtC,QAAI,SAAS,GAAI;AACjB,QAAI,QAAQ,UAAU,oBAAqB,QAAO,EAAE,SAAS,WAAW,KAAK;AAC7E,YAAQ,KAAK,EAAE,OAAO,OAAO,MAAM,CAAC,CAAC,GAAG,MAAM,KAAK,MAAM,GAAG,iBAAiB,EAAE,CAAC;AAAA,EAClF;AACA,SAAO,EAAE,SAAS,WAAW,MAAM;AACrC;;;AC3BO,IAAM,YAAY;AAEzB,IAAMC,YAAW,CAAC,MAChB,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAGzD,SAAS,eAAe,MAAc,MAA6B;AACjE,QAAM,KAAK,KAAK,QAAQ,GAAG,IAAI,IAAI;AACnC,MAAI,MAAM,GAAG;AACX,UAAMC,QAAO,KAAK,KAAK,SAAS;AAChC,UAAMC,OAAM,KAAK,QAAQ,KAAKD,KAAI;AAClC,WAAOC,OAAM,IAAI,OAAO,KAAK,MAAMD,OAAMC,IAAG;AAAA,EAC9C;AACA,QAAM,SAAS,KAAK,QAAQ,GAAG,IAAI,IAAI;AACvC,MAAI,SAAS,EAAG,QAAO;AACvB,QAAM,OAAO,SAAS,KAAK,SAAS;AACpC,QAAM,MAAM,KAAK,QAAQ,KAAK,IAAI;AAClC,SAAO,MAAM,IAAI,OAAO,KAAK,MAAM,MAAM,GAAG;AAC9C;AAGA,SAAS,YAAY,OAAoC;AACvD,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,MAAM,GAAG,GAAG;AACxD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAChF,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,EAAE,MAAM,GAAG,GAAG;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,OAAO,MAAc,MAA2C;AACvE,QAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IACtC,KAAK,QAAQ,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,EAAE,MAAM,GAAG,EAAE,IAC1E;AACJ,QAAM,WAAW,YAAY,KAAK,OAAO;AACzC,SAAO;AAAA,IACL,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,IACtB,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI;AAAA,IACrE,GAAI,WAAW,QAAQ,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,IACnD,GAAI,aAAa,SAAY,EAAE,SAAS,SAAS,IAAI,CAAC;AAAA,IACtD,GAAI,OAAO,KAAK,YAAY,WAAW,EAAE,SAAS,KAAK,QAAQ,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC;AAAA,IACjF,GAAI,OAAO,KAAK,WAAW,WAAW,EAAE,QAAQ,KAAK,OAAO,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC;AAAA,EACjF;AACF;AASO,SAAS,aAAa,MAA2D;AACtF,QAAM,KAAK,KAAK,QAAQ,aAAa;AACrC,MAAI,KAAK,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,WAAW,MAAM;AACjD,QAAM,MAAM,eAAe,KAAK,MAAM,EAAE,GAAG,YAAY;AACvD,MAAI,QAAQ,KAAM,QAAO,EAAE,OAAO,CAAC,GAAG,WAAW,MAAM;AACvD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,eAAe,GAAG,CAAC;AAAA,EACzC,QAAQ;AACN,WAAO,EAAE,OAAO,CAAC,GAAG,WAAW,MAAM;AAAA,EACvC;AACA,MAAI,CAACF,UAAS,MAAM,EAAG,QAAO,EAAE,OAAO,CAAC,GAAG,WAAW,MAAM;AAC5D,QAAM,UAAU,OAAO,QAAQ,MAAM,EAAE;AAAA,IAAO,CAAC,UAC7CA,UAAS,MAAM,CAAC,CAAC;AAAA,EACnB;AACA,SAAO;AAAA,IACL,OAAO,QAAQ,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,OAAO,MAAM,IAAI,CAAC;AAAA,IAC3E,WAAW,QAAQ,SAAS;AAAA,EAC9B;AACF;;;AC3EO,IAAM,YAAY;AAElB,IAAM,aAAa;AAE1B,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,aAAa,CAAC,QAAwB,IAAI,KAAK,EAAE,QAAQ,gBAAgB,EAAE,EAAE,KAAK;AAGxF,SAAS,iBAAiB,KAAuB;AAC/C,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAS;AACf,aAAS;AACP,UAAM,QAAQ,OAAO,KAAK,GAAG;AAC7B,QAAI,UAAU,KAAM;AACpB,UAAM,WAAW,mCAAmC,KAAK,MAAM,CAAC,KAAK,EAAE;AACvE,QAAI,CAAC,SAAU;AACf,UAAM,OAAO,WAAW,SAAS,CAAC,KAAK,EAAE;AACzC,QAAI,SAAS,MAAM,CAAC,iBAAiB,IAAI,KAAK,YAAY,CAAC,EAAG,MAAK,IAAI,IAAI;AAAA,EAC7E;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AAGA,SAAS,cAAc,KAAuB;AAC5C,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,SAAS;AACf,aAAS;AACP,UAAM,QAAQ,OAAO,KAAK,GAAG;AAC7B,QAAI,UAAU,KAAM;AACpB,eAAW,SAAS,MAAM,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG;AAC9C,UAAI,CAAC,OAAO,KAAK,IAAI,EAAG;AACxB,YAAM,OAAO,WAAW,IAAI;AAC5B,UAAI,SAAS,MAAM,iBAAiB,IAAI,KAAK,YAAY,CAAC,KAAK,KAAK,SAAS,MAAM,EAAG;AACtF,aAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AAAA,IAC9C;AAAA,EACF;AACA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAACG,IAAG,MAAM,EAAE,CAAC,IAAIA,GAAE,CAAC,MAAMA,GAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AACzG;AAOO,SAAS,aAAa,cAAgC;AAC3D,QAAM,MAAM,iBAAiB,eAAe,YAAY,CAAC;AACzD,QAAM,WAAW,iBAAiB,GAAG;AACrC,UAAQ,SAAS,SAAS,IAAI,WAAW,cAAc,GAAG,GAAG,MAAM,GAAG,SAAS;AACjF;AAYO,SAAS,cAAc,cAAwC;AACpE,QAAM,MAAM,iBAAiB,eAAe,YAAY,CAAC;AACzD,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,QAAQ;AACd,aAAS;AACP,UAAM,QAAQ,MAAM,KAAK,GAAG;AAC5B,QAAI,UAAU,KAAM;AACpB,UAAM,OAAO,MAAM,CAAC,KAAK,IAAI,YAAY;AACzC,UAAM,MACJ,IAAI,WAAW,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG;AACxF,WAAO,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,EAC5C;AACA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EACxB,KAAK,CAACA,IAAG,MAAM,EAAE,CAAC,IAAIA,GAAE,CAAC,MAAMA,GAAE,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,EAAE,EACpD,MAAM,GAAG,UAAU,EACnB,IAAI,CAAC,CAAC,KAAK,KAAK,OAAuB,EAAE,KAAK,MAAM,EAAE;AAC3D;;;AC7FA,IAAM,gBAAgB;AAGtB,IAAM,eAAe;AAErB,IAAM,gBAAgB;AAGtB,SAAS,aAAa,OAAoD;AACxE,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,OAAO,IAAK;AAAA,aACP,OAAO,IAAK;AAAA,aACZ,OAAO,OAAO,UAAU;AAC/B,aAAO,EAAE,MAAM,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE;AAAA,EACjF;AACA,SAAO,EAAE,MAAM,MAAM,KAAK,EAAE;AAC9B;AAQO,SAAS,eACd,OACA,OACA,QAAQ,GACA;AACR,MAAI,SAAS,iBAAiB,CAAC,MAAM,SAAS,MAAM,EAAG,QAAO;AAC9D,MAAI,MAAM;AACV,MAAI,IAAI;AACR,aAAS;AACP,UAAM,KAAK,MAAM,QAAQ,QAAQ,CAAC;AAClC,QAAI,KAAK,EAAG,QAAO,MAAM,MAAM,MAAM,CAAC;AACtC,WAAO,MAAM,MAAM,GAAG,EAAE;AACxB,QAAI,QAAQ;AACZ,QAAI,IAAI,KAAK,OAAO;AACpB,WAAO,IAAI,MAAM,UAAU,QAAQ,GAAG,KAAK;AACzC,UAAI,MAAM,CAAC,MAAM,IAAK;AAAA,eACb,MAAM,CAAC,MAAM,IAAK;AAAA,IAC7B;AAEA,QAAI,QAAQ,EAAG,QAAO,MAAM,MAAM,MAAM,EAAE;AAC1C,UAAM,EAAE,MAAM,SAAS,IAAI,aAAa,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;AAC9E,UAAM,aAAa,MAAM,IAAI,IAAI;AACjC,UAAM,cACJ,eAAe,SACX,eAAe,YAAY,OAAO,QAAQ,CAAC,IAC3C,aAAa,SACX,eAAe,UAAU,OAAO,QAAQ,CAAC,IACzC,OAAO,IAAI;AACnB,WAAO;AACP,QAAI;AAAA,EACN;AACF;AAGA,SAAS,iBAAiB,MAAyE;AACjG,QAAM,QAAQ,oBAAI,IAAoB;AACtC,QAAM,gBAAoC,CAAC;AAC3C,aAAW,QAAQ,qBAAqB,eAAe,IAAI,CAAC,GAAG;AAC7D,UAAM,YAAY,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,KAAK;AAC/D,QAAI,CAAC,aAAa,KAAK,SAAS,EAAG;AACnC,QAAI,KAAK,UAAU,KAAK,CAAC,QAAQ,cAAc,KAAK,GAAG,CAAC,EAAG,eAAc,KAAK,CAAC,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,QAChG,OAAM,IAAI,KAAK,MAAM,KAAK,KAAK;AAAA,EACtC;AACA,QAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,aAAW,CAAC,MAAM,KAAK,KAAK,cAAe,MAAK,IAAI,MAAM,KAAK;AAC/D,SAAO,EAAE,OAAO,KAAK;AACvB;AAGA,SAAS,gBAAgB,OAA4D;AACnF,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO;AACjC,QAAI,CAAC,KAAK,WAAW,OAAO,EAAG;AAC/B,QAAI,IAAI,IAAI,eAAe,OAAO,KAAK;AAAA,EACzC;AACA,SAAO;AACT;AAWO,SAAS,oBAAoB,cAAuC;AACzE,QAAM,EAAE,OAAO,KAAK,IAAI,iBAAiB,YAAY;AACrD,SAAO,EAAE,OAAO,gBAAgB,KAAK,GAAG,MAAM,gBAAgB,IAAI,EAAE;AACtE;;;AC5FO,IAAM,gBAAgB;AAGtB,SAAS,YAAY,QAA0C;AACpE,QAAM,SAAS,oBAAI,IAA8B;AACjD,aAAW,SAAS,OAAO,QAAQ;AACjC,UAAM,QAAQ,OAAO,IAAI,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,MAAM,OAAO,GAAG,OAAO,EAAE;AAC/E,UAAM,SAAS;AACf,UAAM,SAAS,MAAM;AACrB,WAAO,IAAI,MAAM,MAAM,KAAK;AAAA,EAC9B;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,CAACC,IAAG,MAAM,EAAE,QAAQA,GAAE,UAAUA,GAAE,OAAO,EAAE,OAAO,KAAK,EAAE;AAC5F;AAQO,SAAS,mBAAmB,QAAoC;AACrE,QAAM,WAAW,OAAO;AACxB,QAAM,UAAU,eAAe,QAAQ;AACvC,QAAM,QAAQ,aAAa,QAAQ;AACnC,QAAM,cAAc,YAAY,MAAM;AACtC,QAAM,QAAQ,aAAa,QAAQ;AACnC,QAAM,YAAsB,CAAC;AAC7B,MAAI,QAAQ,UAAW,WAAU,KAAK,SAAS;AAC/C,MAAI,MAAM,UAAW,WAAU,KAAK,OAAO;AAC3C,MAAI,OAAO,UAAU,SAAS,cAAe,WAAU,KAAK,WAAW;AAEvE,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,eAAe,IAAI,YAAY,EAAE,OAAO,QAAQ,EAAE;AAAA,IAClD,YAAY,OAAO,OAAO,OAAO,CAAC,OAAO,UAAU,QAAQ,MAAM,OAAO,CAAC;AAAA,IACzE,YAAY,OAAO,OAAO;AAAA,IAC1B;AAAA,IACA,WAAW,OAAO,UAAU,MAAM,GAAG,aAAa;AAAA,IAClD,WAAW,OAAO,UAAU;AAAA,IAC5B,QAAQ,oBAAoB,QAAQ;AAAA,IACpC,OAAO,aAAa,QAAQ;AAAA,IAC5B,QAAQ,cAAc,QAAQ;AAAA,IAC9B,OAAO,MAAM;AAAA,IACb,SAAS,QAAQ;AAAA,IACjB,GAAI,OAAO,eAAe,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC;AAAA,IACnE;AAAA,EACF;AACF;AAOO,SAAS,iBAAiB,MAA4B;AAC3D,SAAO,mBAAmB,kBAAkB,IAAI,CAAC;AACnD;;;ACnEA,IAAM,SAAS,CAAC,MAAsB,KAAK,MAAM,IAAI,GAAG,IAAI;AASrD,SAAS,eAAe,UAA4C;AACzE,QAAM,SAAS,CAAC,SACd,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,GAAG;AACzC,QAAM,KAAK,OAAO,IAAI,KAAK;AAC3B,QAAM,SAAiC,CAAC;AACxC,QAAM,MAAM,CAAC,OAAe,OAAsB;AAChD,QAAI,GAAI,QAAO,KAAK,IAAI,OAAO,cAAc,IAAI,EAAE,CAAC;AAAA,EACtD;AACA,MAAI,cAAc,OAAO,MAAM,CAAC;AAChC,MAAI,iBAAiB,OAAO,SAAS,CAAC;AACtC,MAAI,cAAc,OAAO,MAAM,CAAC;AAChC,MAAI,cAAc,OAAO,MAAM,CAAC;AAChC,MAAI,gBAAgB,OAAO,QAAQ,CAAC;AACpC,QAAM,UAAU,OAAO,SAAS;AAChC,MAAI,QAAS,QAAO,iBAAiB,IAAI,OAAO,cAAc,WAAW,OAAO,GAAG,OAAO,CAAC;AAC3F,SAAO;AACT;;;ACXO,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,uBAA0C;AAAA,EACrD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;;;ACzEO,IAAM,kBAAkB;AAGxB,IAAM,kBAAkB;AAG/B,IAAM,cAAc;AAEpB,IAAMC,QAAO;AAKb,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,WAAW;AAGjB,IAAM,YAAY;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,YAAY,KAAqB;AACxC,QAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,GAAG;AAClC,QAAM,UAAU,mBAAmB,IAAI,MAAM,kBAAkB;AAC/D,SAAO,WAAW,aAAa,EAAE,GAAG,SAAS,GAAG,EAAE,CAAC,CAAC;AACtD;AAQA,SAAS,gBAAgB,KAAkB,OAAoB,UAAkB,SAAuB;AACtG,QAAM,eAAe,MAAM,cAAc;AACzC,QAAM,gBAAgB,MAAM,gBAAgB;AAC5C,MAAI;AACJ,MAAI,gBAAgB;AACpB,MAAI,iBAAiB,UAAaA,MAAK,KAAK,YAAY,GAAG;AACzD,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,YAAY;AAC3C,oBAAgB;AAChB,mBAAe,UAAU,KAAK,IAAI,KAAK,IAAI,IAAI,QAAQ,GAAG,QAAQ;AAClE,QAAI,cAAc,IAAI,WAAW,aAAa,EAAE,GAAG,cAAc,GAAG,EAAE,CAAC,CAAC;AAAA,EAC1E;AACA,MAAI,kBAAkB,UAAaA,MAAK,KAAK,aAAa,GAAG;AAC3D,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,aAAa;AAC5C,UAAM,OAAO,gBAAgB,UAAU;AACvC,UAAM,KAAK,OAAO,KAAK,IAAI,KAAK,IAAI,IAAI,aAAa,GAAG,QAAQ;AAChE,QAAI,gBAAgB,IAAI,WAAW,aAAa,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,EAClE;AACA,QAAM,cAAc,MAAM,cAAc;AACxC,MAAI,gBAAgB,UAAaA,MAAK,KAAK,WAAW,GAAG;AACvD,QAAI,gBAAgB,iBAAiB,IAAI,gBAAgB,MAAM,QAAW;AACxE,UAAI,cAAc,IAAI,IAAI,gBAAgB;AAAA,IAC5C,OAAO;AACL,YAAM,EAAE,GAAG,GAAG,EAAE,IAAI,WAAW,WAAW;AAC1C,YAAM,QAAQ,UAAU,KAAK,IAAI,KAAK,IAAI,IAAI,QAAQ,GAAG,QAAQ;AACjE,UAAI,cAAc,IAAI,WAAW,aAAa,EAAE,GAAG,OAAO,GAAG,EAAE,CAAC,CAAC;AAAA,IACnE;AAAA,EACF;AACF;AAGA,SAAS,QAAQ,KAAa,IAAY,KAAqB;AAC7D,QAAM,OAAO,CAAC,MAAuB,cAAc,GAAG,EAAE,KAAK;AAC7D,SACE,qBAAqB,KAAK,MAAM,SAAS,KACzC,qBAAqB,KAAK,MAAM,QAAQ,KACxC,WAAW,EAAE;AAEjB;AASO,SAAS,iBAAiB,OAAiC;AAChE,QAAM,MAAmB,CAAC;AAC1B,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,QAAI,SAAS,cAAe,KAAI,IAAI,IAAI;AAAA,aAC/B,aAAa,IAAI,IAAI,KAAKA,MAAK,KAAK,KAAK,EAAG,KAAI,IAAI,IAAI,YAAY,KAAK;AAAA,QAC7E,KAAI,IAAI,IAAI;AAAA,EACnB;AAEA,QAAM,KAAK,IAAI,SAAS;AACxB,QAAM,UAAU,MAAM,SAAS;AAC/B,MAAI,OAAO,UAAa,CAACA,MAAK,KAAK,EAAE,KAAK,YAAY,UAAa,CAACA,MAAK,KAAK,OAAO,EAAG,QAAO;AAE/F,kBAAgB,KAAK,OAAO,WAAW,OAAO,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;AAEnE,aAAW,QAAQ,CAAC,aAAa,iBAAiB,GAAG;AACnD,UAAM,IAAI,IAAI,IAAI;AAClB,QAAI,MAAM,UAAaA,MAAK,KAAK,CAAC,EAAG,KAAI,IAAI,IAAI,QAAQ,GAAG,IAAI,GAAG;AAAA,EACrE;AACA,QAAM,SAAS,IAAI,cAAc;AACjC,QAAM,WAAW,IAAI,gBAAgB;AACrC,MAAI,aAAa,UAAaA,MAAK,KAAK,QAAQ;AAC9C,QAAI,gBAAgB,IAAI,QAAQ,UAAU,WAAW,UAAaA,MAAK,KAAK,MAAM,IAAI,SAAS,IAAI,GAAG;AAExG,aAAW,QAAQ,WAAW;AAC5B,UAAM,IAAI,IAAI,IAAI;AAClB,QAAI,MAAM,UAAaA,MAAK,KAAK,CAAC,EAAG,KAAI,IAAI,IAAI,QAAQ,GAAG,IAAI,GAAG;AAAA,EACrE;AACA,aAAW,QAAQ,UAAU;AAC3B,UAAM,IAAI,IAAI,IAAI;AAClB,QAAI,MAAM,UAAaA,MAAK,KAAK,CAAC,EAAG,KAAI,IAAI,IAAI,QAAQ,GAAG,IAAI,CAAC;AAAA,EACnE;AAEA,QAAM,SAAS,IAAI,aAAa;AAChC,QAAM,WAAW,IAAI,gBAAgB;AACrC,MAAI,WAAW,UAAaA,MAAK,KAAK,MAAM,KAAK,aAAa,UAAaA,MAAK,KAAK,QAAQ;AAC3F,QAAI,gBAAgB,IAAI,WAAW,MAAM;AAE3C,SAAO;AACT;;;AChJA,IAAM,SACJ;AAEF,IAAM,QAAQ,IAAI;AAAA,EAChB,qBAAqB,IAAI,CAAC,MAAM,MAAwB,CAAC,MAAM,CAAC,CAAC;AACnE;AAGA,SAAS,aAAa,QAA+B;AACnD,SAAO,OAAO,KAAK,MAAM,EAAE,KAAK,CAACC,IAAG,MAAM;AACxC,UAAM,KAAK,MAAM,IAAIA,EAAC;AACtB,UAAM,KAAK,MAAM,IAAI,CAAC;AACtB,QAAI,OAAO,UAAa,OAAO,OAAW,QAAO,KAAK;AACtD,QAAI,OAAO,OAAW,QAAO;AAC7B,QAAI,OAAO,OAAW,QAAO;AAC7B,WAAOA,KAAI,IAAI,KAAKA,KAAI,IAAI,IAAI;AAAA,EAClC,CAAC;AACH;AAEA,SAAS,YACP,UACA,QACA,OACA,QACA,MACQ;AACR,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,OAAW,OAAM,KAAK,GAAG,MAAM,KAAK,IAAI,EAAE;AACvD,aAAW,QAAQ,MAAO,OAAM,KAAK,GAAG,MAAM,KAAK,IAAI,KAAK,OAAO,IAAI,CAAC,GAAG;AAC3E,MAAI,MAAM,WAAW,EAAG,QAAO,GAAG,MAAM,GAAG,QAAQ;AAAA,EAAO,MAAM;AAChE,SAAO,GAAG,MAAM,GAAG,QAAQ;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC;AAAA,EAAK,MAAM;AAC/D;AAOO,SAAS,gBAAgB,OAAoB,OAA+B,CAAC,GAAW;AAC7F,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,SAAS,aAAa;AAC5B,QAAM,QAAkB,CAAC,QAAQ,YAAY,UAAU,OAAO,aAAa,KAAK,GAAG,EAAE,CAAC;AAEtF,QAAM,OAAO,KAAK;AAClB,MAAI,SAAS,QAAW;AACtB,UAAM,YAAY,aAAa,IAAI,EAAE,OAAO,CAAC,SAAS,MAAM,IAAI,MAAM,KAAK,IAAI,CAAC;AAChF,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,eAAe,SACjB,uBAAuB,QAAQ,KAAK,QAAQ,wBAC5C;AACJ,YAAM,gBAAgB,SAClB,mCAAmC,QAAQ,KAC3C;AACJ,YAAM,KAAK,YAAY,cAAc,MAAM,WAAW,EAAE,CAAC;AACzD,YAAM;AAAA,QACJ;AAAA,EAA0C,YAAY,eAAe,MAAM,WAAW,IAAI,CAAC;AAAA;AAAA,MAC7F;AAAA,IACF;AACA,QAAI,KAAK,kBAAkB,MAAM;AAC/B,YAAM,KAAK,YAAY,cAAc,MAAM,aAAa,IAAI,GAAG,IAAI,qBAAqB,CAAC;AAAA,IAC3F;AAAA,EACF;AACA,SAAO,GAAG,MAAM,KAAK,MAAM,CAAC;AAAA;AAC9B;;;ACtFA,IAAMC,YAAW,CAAC,MAChB,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAGzD,SAAS,eACP,OACA,WACA,UACM;AACN,MAAI,cAAc,OAAW;AAC7B,MAAI,CAACA,UAAS,SAAS,GAAG;AACxB,aAAS,KAAK,EAAE,OAAO,eAAe,SAAS,mCAAmC,CAAC;AACnF;AAAA,EACF;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,QAAI,CAAC,KAAK,WAAW,IAAI,GAAG;AAC1B,eAAS,KAAK,EAAE,OAAO,MAAM,SAAS,mDAAmD,CAAC;AAC1F;AAAA,IACF;AACA,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAI;AACpD,eAAS,KAAK,EAAE,OAAO,MAAM,SAAS,qDAAqD,CAAC;AAC5F;AAAA,IACF;AACA,UAAM,IAAI,IAAI,MAAM,KAAK;AAAA,EAC3B;AACF;AAcO,SAAS,mBAAmB,OAA0C;AAC3E,QAAM,EAAE,QAAQ,OAAO,SAAS,IAAI,mBAAmB,KAAK;AAC5D,iBAAe,OAAO,OAAO,WAAW,QAAQ;AAChD,QAAM,OAAO,iBAAiB,KAAK;AACnC,SAAO,EAAE,OAAO,MAAM,SAAS;AACjC;;;AC3CO,IAAM,iBAAiB;AAE9B,IAAM,cAAmC,oBAAI,IAAI,CAAC,aAAa,cAAc,aAAa,YAAY,CAAC;AAQhG,SAAS,gBAAgB,OAA2B;AACzD,MAAI,OAAO,SAAS,YAAY;AAC9B,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAQ;AAC7C,gBAAU,OAAO,aAAa,GAAG,MAAM,SAAS,GAAG,IAAI,IAAM,CAAC;AAAA,IAChE;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACA,SAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ;AAC7C;AAEA,IAAM,WAAW,CAAC,QAAwB,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,KAAK,EAAE,YAAY;AAErF,SAAS,WAAW,OAAmB,OAAmB,aAAiC;AACzF,QAAM,UAAqB;AAAA,IACzB,MAAM;AAAA,IACN,MAAM,SAAS,MAAM,EAAE,KAAK,MAAM,IAAI,KAAK,WAAW,KAAK,MAAM,UAAU,SAAS,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,EAAE;AAAA,EAC7H;AACA,MAAI,YAAY,IAAI,WAAW,GAAG;AAChC,UAAM,QAAoB;AAAA,MACxB,MAAM;AAAA,MACN,QAAQ,EAAE,MAAM,UAAU,WAAW,aAA+B,MAAM,gBAAgB,KAAK,EAAE;AAAA,IACnG;AACA,WAAO,EAAE,SAAS,CAAC,SAAS,KAAK,EAAE;AAAA,EACrC;AACA,QAAM,WAA0B;AAAA,IAC9B,MAAM;AAAA,IACN,QAAQ,EAAE,MAAM,UAAU,WAAW,mBAAmB,MAAM,gBAAgB,KAAK,EAAE;AAAA,EACvF;AACA,SAAO,EAAE,SAAS,CAAC,SAAS,QAAQ,EAAE;AACxC;AAQO,SAAS,WAAW,KAA8B;AACvD,QAAM,YAAY,OAAO,YAAyC;AAChE,UAAM,OAAO,MAAM,IAAI,SAAS;AAChC,UAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAAA,MAC7B,CAAC,SAAS,KAAK,GAAG;AAAA,QAChB,GAAG,EAAE,OAAO,EAAE,IAAI,SAAS,QAAQ,IAAI,OAAO,EAAE;AAAA,QAChD,MAAM,CAAC;AAAA,MACT;AAAA,IACF,CAAC;AACD,UAAM,OAAO,IAAI,SAAS,KAAK,KAAK,CAAC,GAAG,CAAC;AAGzC,QACE,CAAC,OACD,IAAI,WAAW,UACf,IAAI,aACJ,CAAC,MAAM,QAAQ,IAAI,IAAI,KACvB,IAAI,KAAK,WAAW,KACpB,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,GACzB,OAAM,IAAI,mBAAmB,SAAS,OAAO,EAAE;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,YAAqB;AAAA,IACzB,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,SAAS;AAAA,MACpB,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,aAAa,qCAAqC,EAAE;AAAA,IAC/F;AAAA,IACA,aAAa,CAAC,2BAA2B;AAAA,IACzC,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,QAAQ,MAAM,UAAU,OAAO,MAAM,OAAO,CAAC;AACnD,UAAI,CAAC,IAAI,qBAAqB;AAC5B,eAAO;AAAA,UACL,SACE,4DAA4D,MAAM,EAAE;AAAA,QAIxE;AAAA,MACF;AACA,YAAM,OAAO,MAAM,IAAI,UAAU,YAAY;AAC7C,YAAM,UAAU,MAAM,IAAI,iBAAiB,MAAM,EAAE;AACnD,UAAI,QAAQ,MAAM,aAAa,gBAAgB;AAC7C,eAAO;AAAA,UACL,SACE,SAAS,MAAM,EAAE,OAAO,QAAQ,MAAM,UAAU,0BAAqB,cAAc;AAAA,QAEvF;AAAA,MACF;AACA,YAAM,SAAS,SAAS,QAAQ,WAAW;AAC3C,YAAM,YAAY,YAAY,IAAI,MAAM,KAAK,WAAW,oBAAoB,SAAS,SAAS,MAAM,WAAW;AAC/G,UAAI,CAAC,YAAY,IAAI,SAAS,KAAK,cAAc,mBAAmB;AAClE,eAAO;AAAA,UACL,SACE,SAAS,MAAM,EAAE,OAAO,SAAS;AAAA,QAErC;AAAA,MACF;AACA,aAAO,WAAW,OAAO,QAAQ,OAAO,SAAS;AAAA,IACnD,CAAC;AAAA,EACH;AAEA,QAAM,iBAA0B;AAAA,IAC9B,MAAM;AAAA,IACN,aACE;AAAA,IACF,cAAc,CAAC,2BAA2B;AAAA,IAC1C,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,WAAW,eAAe,kBAAkB,MAAM;AAAA,MAC7D,YAAY;AAAA,QACV,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,aAAa,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,QACrF,gBAAgB,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,GAAG,UAAU,IAAI,aAAa,0BAA0B;AAAA,QACjH,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,SAAS,GAAG,UAAU,GAAG;AAAA,MACjE;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,QAAQ,MAAM,UAAU,OAAO,MAAM,OAAO,CAAC;AACnD,YAAM,IAAI,UAAU,YAAY;AAChC,YAAM,WAAW,eAAe;AAAA,QAC9B,aAAa,MAAM;AAAA,QACnB,gBAAgB,MAAM;AAAA,QACtB,MAAM,MAAM;AAAA,MACd,CAAC;AACD,YAAM,UAAU,MAAM,IAAI,oBAAoB;AAAA,QAC5C,YAAY,IAAI,MAAM;AAAA,QACtB,SAAS,MAAM;AAAA,QACf;AAAA,QACA,0BAA0B,MAAM;AAAA,MAClC,CAAC;AACD,UACE,QAAQ,OAAO,MAAM,MACrB,QAAQ,WAAW,IAAI,UACvB,QAAQ,WAAW,UACnB,QAAQ,qBAAqB,MAAM,mBAAmB,KACtD,QAAQ,eAAe,IAAI,KAAK,OAChC,OAAM,IAAI,mBAAmB,8CAA8C;AAC7E,aAAO;AAAA,QACL,SAAS,+BAA+B,MAAM,EAAE,KAAK,SAAS,eAAe,MAAM,uBAAuB,SAAS,KAAK,MAAM;AAAA,MAChI;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,WAAW,cAAc;AACnC;;;ACrKA,eAAsB,sBACpB,KACA,MACA,OAC6B;AAC7B,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,gBAAgB,UAAU,OAAO,iBAAiB,GAAG;AAC3D,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,KAAK,GAAG;AAAA,MAChB,GAAG;AAAA,QACD,OAAO,EAAE,IAAI,eAAe,QAAQ,KAAK,IAAI,QAAQ,OAAO;AAAA,QAC5D,OAAO;AAAA,MACT;AAAA,MACA,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;AAAA,IAC1B;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,SAAS,KAAK,KAAK,CAAC;AACxC,QAAM,QAAQ,KAAK,WAAW,IAC1B,KAAK,CAAC,IAON;AACJ,MACE,CAAC,SACD,MAAM,OAAO,iBACb,MAAM,WAAW,KAAK,MACtB,MAAM,WAAW,UACjB,MAAM,cAAc,UACpB,CAAC,MAAM,QAAQ,MAAM,IAAI,KACzB,MAAM,KAAK,WAAW,KACtB,MAAM,KAAK,CAAC,GAAG,OAAO,KAAK,GAC3B,OAAM,IAAI;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;;;ACjCA,IAAM,aAAa,cAAc,OAAO,CAAC,SAAS,SAAS,SAAS;AAG7D,SAAS,UAAU,KAA8B;AACtD,SAAO,CAAC;AAAA,IACN,MAAM;AAAA,IACN,aACE;AAAA,IACF,cAAc,CAAC,2BAA2B;AAAA,IAC1C,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,QAAQ,WAAW,WAAW;AAAA,MACzC,YAAY;AAAA,QACV,MAAM,EAAE,MAAM,UAAU,MAAM,WAAW;AAAA,QACzC,SAAS,EAAE,MAAM,UAAU,aAAa,yCAAyC;AAAA,QACjF,WAAW,EAAE,MAAM,UAAU,aAAa,qDAAqD;AAAA,QAC/F,eAAe;AAAA,UACb,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,UAAU,oBAAI,IAAI,CAAC,QAAQ,WAAW,aAAa,eAAe,CAAC;AACzE,UAAI,OAAO,KAAK,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;AACpD,cAAM,IAAI,gBAAgB,qCAAqC;AACjE,YAAM,OAAO,MAAM,IAAI,SAAS;AAChC,YAAM,IAAI,UAAU,YAAY;AAChC,YAAM,OAAO,MAAM;AACnB,UAAI,SAAS,aAAa,CAAC,WAAW,SAAS,IAAI;AACjD,cAAM,IAAI,gBAAgB,wBAAwB,WAAW,KAAK,IAAI,CAAC,EAAE;AAC3E,YAAM,YAAY,UAAU,MAAM,WAAW,aAAa,GAAK;AAC/D,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR;AACA,YAAM,WAAW,MAAM,IAAI,eAAe;AAAA,QACxC,YAAY,IAAI,MAAM;AAAA,QACtB;AAAA,QACA,SAAS;AAAA,UACP,SAAS,qBAAqB,MAAM,MAAM,OAAO;AAAA,QACnD;AAAA,QACA;AAAA,QACA,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,MAC3C,CAAC;AACD,UACE,SAAS,WAAW,KAAK,MACzB,SAAS,cAAc,IAAI,KAAK,UAChC,SAAS,SAAS,QAClB,SAAS,WAAW,OACpB,OAAM,IAAI,gBAAgB,oDAAoD;AAChF,aAAO;AAAA,QACL,SACE,UAAU,IAAI,qBAAqB,SAAS,EAAE;AAAA,MAElD;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;;;AC1CA,IAAM,KAAK,CAAC,MAAsB,EAAE,QAAQ,CAAC;AAC7C,IAAM,KAAK,CAAC,OAAyB,KAAK,SAAS;AAEnD,IAAM,UAAU,CAAC,UACf,GAAG,GAAG,KAAK,CAAC,qBAAgB,GAAG,QAAQ,KAAK,CAAC,CAAC,iBAAiB,GAAG,QAAQ,OAAO,YAAY,CAAC,CAAC,cAAc,GAAG,SAAS,KAAK,CAAC,CAAC;AAIlI,IAAM,qBAAiE;AAAA,EACrE,eAAe,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAAA,EACvC,WAAW,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC;AAAA,EAClC,SAAS,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC;AAAA,EAC9B,OAAO,CAAC,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC;AAAA,EACvC,UAAU,CAAC,MAAM,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC;AAAA,EACvC,YAAY,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC;AAChD;AAEA,SAAS,aAAa,UAAoB,SAAiB,SAA4B;AACrF,MAAI,OAAO,YAAY,YAAY,EAAE,WAAW,qBAAqB;AACnE,UAAM,IAAI,gBAAgB,2BAA2B,OAAO,KAAK,kBAAkB,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACnG;AACA,QAAM,CAAC,WAAW,SAAS,IAAI,mBAAmB,OAAO,EAAG,OAAO;AACnE,SAAO,SAAS,IAAI,CAAC,MAAM;AACzB,UAAM,MAAM,EAAE,SAAS,cAAc,YAAY,EAAE,SAAS,cAAc,YAAY;AACtF,QAAI,CAAC,IAAK,QAAO;AACjB,WAAO,EAAE,GAAG,GAAG,KAAK,MAAM,kBAAkB,GAAG,EAAE,MAAM,WAAW,GAAG,OAAO,yBAAyB;AAAA,EACvG,CAAC;AACH;AAEA,IAAM,mBAAmB,CAAC,WAAW,MAAM;AAE3C,SAAS,aAAa,KAAa,SAA6B;AAC9D,QAAM,MAAM,WAAW,GAAG;AAC1B,QAAM,QAAQ,kBAAkB,GAAG;AACnC,QAAM,QAAQ;AAAA,IACZ,GAAG,GAAG,6BAAwB,MAAM,IAAI,eAAU,MAAM,SAAS,QAAQ,CAAC,CAAC;AAAA,IAC3E,YAAY,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,IAC1E,sBAAsB,kBAAkB,GAAG,EAAE,QAAQ,CAAC,CAAC,cAAc,GAAG,cAAc,KAAK,SAAS,CAAC,CAAC,gBAAgB,GAAG,cAAc,KAAK,SAAS,CAAC,CAAC;AAAA,IACvJ,wBAAwB,WAAW,GAAG,CAAC;AAAA,EACzC;AACA,MAAI,QAAQ,SAAS,SAAS,GAAG;AAC/B,UAAM,CAAC,QAAQ,KAAK,IAAI,UAAU,GAAG;AACrC,UAAM,CAAC,QAAQ,KAAK,IAAI,QAAQ,GAAG;AACnC,UAAM,CAAC,QAAQ,KAAK,IAAI,mBAAmB,GAAG;AAC9C,UAAM;AAAA,MACJ,gCAA2B,cAAc,GAAG,CAAC,eAAe,MAAM,IAAI,KAAK,aAAa,MAAM,IAAI,KAAK,WAAW,MAAM,IAAI,KAAK;AAAA,IACnI;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,MAAM,EAAG,OAAM,KAAK,eAAU,cAAc,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE;AACjF,SAAO;AACT;AAOO,SAAS,aAAa,KAA8B;AACzD,QAAM,eAAwB;AAAA,IAC5B,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,KAAK;AAAA,MAChB,YAAY;AAAA,QACV,KAAK,EAAE,MAAM,UAAU,aAAa,kBAAkB;AAAA,QACtD,SAAS,EAAE,MAAM,SAAS,OAAO,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,gBAAgB,EAAE,EAAE;AAAA,MACnF;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,MAAM,UAAU,MAAM,KAAK,KAAK;AACtC,YAAM,UAAU,MAAM,YAAY,SAAY,CAAC,IAAI,MAAM;AACzD,UAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,KAAK,CAAC,MAAM,CAAE,iBAAwC,SAAS,CAAC,CAAC,GAAG;AACzG,cAAM,IAAI,gBAAgB,mCAAmC,iBAAiB,KAAK,IAAI,CAAC,EAAE;AAAA,MAC5F;AACA,aAAO,EAAE,SAAS,aAAa,KAAK,OAAmB,EAAE,KAAK,IAAI,EAAE;AAAA,IACtE,CAAC;AAAA,EACH;AAEA,QAAM,mBAA4B;AAAA,IAChC,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO,EAAE,MAAM,UAAU,UAAU,CAAC,MAAM,IAAI,GAAG,YAAY,EAAE,IAAI,EAAE,MAAM,SAAS,GAAG,IAAI,EAAE,MAAM,SAAS,EAAE,EAAE;AAAA,QAClH;AAAA,QACA,OAAO,EAAE,MAAM,SAAS,UAAU,GAAG,UAAU,GAAG,OAAO,EAAE,MAAM,SAAS,EAAE;AAAA,MAC9E;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,UAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,SAAS,GAAG;AACxD,YAAI,MAAM,MAAM,SAAS,GAAI,OAAM,IAAI,gBAAgB,oCAAoC;AAC3F,cAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,KAAK,MAAM;AACxC,gBAAM,IAAK,OAAO,CAAC;AACnB,gBAAM,KAAK,UAAU,EAAE,IAAI,SAAS,CAAC,MAAM;AAC3C,gBAAM,KAAK,UAAU,EAAE,IAAI,SAAS,CAAC,MAAM;AAC3C,iBAAO,GAAG,EAAE,OAAO,EAAE,KAAK,QAAQ,cAAc,IAAI,EAAE,CAAC,CAAC;AAAA,QAC1D,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,KAAK,IAAI,EAAE;AAAA,MACrC;AACA,UAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC9B,YAAI,MAAM,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,GAAG;AACpD,gBAAM,IAAI,gBAAgB,gCAAgC;AAAA,QAC5D;AACA,cAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,GAAG,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC;AACnE,cAAM,QAAkB,CAAC;AACzB,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,mBAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,kBAAM,KAAK,GAAG,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,KAAK,QAAQ,cAAc,MAAM,CAAC,GAAI,MAAM,CAAC,CAAE,CAAC,CAAC,EAAE;AAAA,UAC1F;AAAA,QACF;AACA,eAAO,EAAE,SAAS,MAAM,KAAK,IAAI,EAAE;AAAA,MACrC;AACA,YAAM,IAAI,gBAAgB,gEAAsD;AAAA,IAClF,CAAC;AAAA,EACH;AAEA,QAAM,iBAA0B;AAAA,IAC9B,MAAM;AAAA,IACN,aACE;AAAA,IACF,cAAc,CAAC,2BAA2B;AAAA,IAC1C,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,QAAQ,WAAW;AAAA,MAC9B,YAAY;AAAA,QACV,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,WAAW,EAAE,MAAM,UAAU,aAAa,0DAAqD;AAAA,QAC/F,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,SAAS,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK,kBAAkB,EAAE;AAAA,QACjE,eAAe;AAAA,UACb,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM;AAAA,YACN,UAAU,CAAC,QAAQ,KAAK;AAAA,YACxB,YAAY;AAAA,cACV,MAAM,EAAE,MAAM,SAAS;AAAA,cACvB,KAAK,EAAE,MAAM,SAAS;AAAA,cACtB,MAAM,EAAE,MAAM,SAAS;AAAA,cACvB,WAAW,EAAE,MAAM,SAAS;AAAA,YAC9B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,OAAO,YAAY;AAC3C,YAAM,OAAO,MAAM,IAAI,SAAS;AAChC,YAAM,IAAI,UAAU,YAAY;AAChC,YAAM,OAAO,UAAU,MAAM,MAAM,QAAQ,GAAG;AAC9C,YAAM,YAAY,UAAU,MAAM,WAAW,aAAa,GAAK;AAC/D,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR;AACA,YAAM,UAAU,MAAM,YAAY,SAAY,SAAY,UAAU,MAAM,SAAS,SAAS;AAC5F,UAAI;AACJ,UAAI,MAAM,aAAa,QAAW;AAChC,mBAAW,eAAe,MAAM,QAAQ;AAAA,MAC1C,OAAO;AACL,YAAI,CAAC,QAAS,OAAM,IAAI,gBAAgB,yDAAyD;AACjG,mBAAW,cAAc,OAAO;AAChC,YAAI,MAAM,YAAY,OAAW,YAAW,aAAa,UAAU,SAAS,MAAM,OAAO;AAAA,MAC3F;AACA,YAAM,SAAS,eAAe,QAAQ;AACtC,YAAM,WAAW,MAAM,IAAI,eAAe;AAAA,QACxC,YAAY,IAAI,MAAM;AAAA,QACtB,MAAM;AAAA,QACN,SAAS;AAAA,UACP;AAAA,UACA;AAAA,UACA,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,UAC7B,gBAAgB;AAAA,QAClB;AAAA,QACA;AAAA,QACA,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,MAC3C,CAAC;AACD,UACE,SAAS,WAAW,KAAK,MACzB,SAAS,cAAc,IAAI,KAAK,UAChC,SAAS,SAAS,aAClB,SAAS,WAAW,OACpB,OAAM,IAAI,gBAAgB,oDAAoD;AAChF,YAAM,aAAa,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI;AACtF,aAAO;AAAA,QACL,SACE,2BAA2B,SAAS,EAAE,MAAM,IAAI,MAAM,SAAS,MAAM,YAClE,UAAU,iBAAiB,OAAO,KAAK,EAAE,gBAAgB,UAAU;AAAA,MAE1E;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,cAAc,kBAAkB,cAAc;AACxD;;;AC/MO,IAAM,oBAAoB;AAI1B,SAAS,eAAe,OAAmBC,SAA8B;AAC9E,QAAM,QAAkB;AAAA,IACtB,UAAU,MAAM,EAAE,GAAGA,QAAO,QAAQ,YAAOA,QAAO,KAAK,MAAM,EAAE,GAAG,MAAM,QAAQ,kBAAkB,MAAM,KAAK,OAAO,EAAE;AAAA,IACtH,YAAYA,QAAO,aAAa,WAAWA,QAAO,UAAU,qBAAqBA,QAAO,UAAU,YAAYA,QAAO,SAAS;AAAA,EAChI;AACA,MAAIA,QAAO,YAAY,SAAS;AAC9B,UAAM;AAAA,MACJ,WAAWA,QAAO,YAAY,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,QAAK,EAAE,IAAI,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,IAC7F;AACF,MAAIA,QAAO,UAAU,SAAS,EAAG,OAAM,KAAK,kBAAkBA,QAAO,UAAU,KAAK,IAAI,CAAC,EAAE;AAC3F,MAAIA,QAAO,MAAM,SAAS,EAAG,OAAM,KAAK,cAAcA,QAAO,MAAM,KAAK,IAAI,CAAC,EAAE;AAC/E,QAAM,aAAa,OAAO,KAAKA,QAAO,OAAO,KAAK;AAClD,QAAM;AAAA,IACJ,WAAW,SAAS,IAChB,YAAY,WAAW,MAAM,8BAA8B,OAAO,KAAKA,QAAO,OAAO,IAAI,EAAE,MAAM,wBAChF,CAAC,WAAW,aAAa,eAAe,sBAAsB,cAAc,EACxF,OAAO,CAAC,MAAMA,QAAO,OAAO,MAAM,CAAC,CAAC,EACpC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAIA,QAAO,OAAO,MAAM,CAAC,CAAC,EAAE,EAC3C,KAAK,IAAI,CAAC,KACf;AAAA,EACN;AACA,MAAIA,QAAO,OAAO,SAAS;AACzB,UAAM,KAAK,mBAAmBA,QAAO,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,OAAI,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAC5F,MAAIA,QAAO,MAAM,SAAS;AACxB,UAAM;AAAA,MACJ,0BACEA,QAAO,MACJ;AAAA,QACC,CAAC,MACC,KAAK,EAAE,IAAI,KAAK,EAAE,MAAM,GAAG,EAAE,UAAU,KAAK,EAAE,QAAQ,KAAK,GAAG,CAAC,KAAK,EAAE,IACnE,EAAE,YAAY,SAAY,KAAK,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,KAAK,EAAE,OAAO,MAAM,EAAE;AAAA,MAClG,EACC,KAAK,IAAI;AAAA,IAChB;AACF,MAAIA,QAAO,QAAQ,SAAS;AAC1B,UAAM;AAAA,MACJ,eACEA,QAAO,QAAQ,IAAI,CAAC,MAAM,GAAG,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI;AAAA,IAC3F;AACF,MAAIA,QAAO,UAAU,SAAS;AAC5B,UAAM,KAAK,uCAAuCA,QAAO,UAAU,KAAK,IAAI,CAAC,GAAG;AAClF,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,aACd,UACA,OAC8C;AAC9C,QAAM,SAAS,KAAK;AAAA,IAClB;AAAA,IACA,KAAK,IAAI,GAAG,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS,iBAAiB;AAAA,EACjF;AACA,MAAI;AACJ,MAAI,MAAM,SAAS,UAAa,MAAM,SAAS,IAAI;AACjD,UAAM,KAAK,SAAS,QAAQ,MAAM,IAAI;AACtC,QAAI,KAAK,EAAG,OAAM,IAAI,mBAAmB,IAAI,MAAM,IAAI,wBAAwB;AAG/E,YAAQ,KAAK,IAAI,GAAG,KAAK,GAAG;AAAA,EAC9B,OAAO;AACL,YAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,SAAS,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC,CAAC,CAAC;AAAA,EAC9E;AACA,QAAM,MAAM,KAAK,IAAI,SAAS,QAAQ,QAAQ,MAAM;AACpD,SAAO,EAAE,MAAM,SAAS,MAAM,OAAO,GAAG,GAAG,OAAO,IAAI;AACxD;AAMO,SAAS,YAAY,KAA8B;AACxD,QAAM,aAAa,OAAO,YAAyC;AACjE,UAAM,IAAI,UAAU,YAAY;AAChC,UAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAAA,MAC7B,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,SAAS,QAAQ,IAAI,QAAQ,QAAQ,OAAO,EAAE,EAAE;AAAA,IACxF,CAAC;AACD,UAAM,OAAO,IAAI,SAAS,KAAK,KAAK,CAAC,GAAG,CAAC;AACzC,QAAI,CAAC,OAAO,IAAI,SAAS,qBAAqB,CAAC,IAAI;AACjD,YAAM,IAAI,mBAAmB,gBAAgB,OAAO,EAAE;AACxD,WAAO;AAAA,EACT;AAEA,QAAM,aAAsB;AAAA,IAC1B,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,SAAS;AAAA,MACpB,YAAY;AAAA,QACV,SAAS,EAAE,MAAM,UAAU,aAAa,sCAAsC;AAAA,MAChF;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,QAAQ,MAAM,WAAW,UAAU,MAAM,SAAS,WAAW,GAAG,CAAC;AACvE,aAAO,EAAE,SAAS,eAAe,OAAO,MAAM,MAAO,EAAE;AAAA,IACzD,CAAC;AAAA,EACH;AAEA,QAAM,mBAA4B;AAAA,IAChC,MAAM;AAAA,IACN,aACE;AAAA;AAAA,IAEF,aAAa,CAAC,mCAAmC;AAAA,IACjD,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,SAAS;AAAA,MACpB,YAAY;AAAA,QACV,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,MAAM,EAAE,MAAM,UAAU,aAAa,+CAA+C;AAAA,QACpF,QAAQ,EAAE,MAAM,UAAU,aAAa,qDAAqD;AAAA,QAC5F,QAAQ,EAAE,MAAM,UAAU,aAAa,6BAA6B,iBAAiB,KAAK;AAAA,MAC5F;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,QAAQ,MAAM,WAAW,UAAU,MAAM,SAAS,WAAW,GAAG,CAAC;AACvE,YAAM,WAAW,MAAM,IAAI,mBAAmB,MAAM,EAAE;AACtD,YAAM,QAAQ,aAAa,UAAU;AAAA,QACnC,GAAI,OAAO,MAAM,SAAS,WAAW,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,QAC7D,GAAI,OAAO,MAAM,WAAW,WAAW,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QACnE,GAAI,OAAO,MAAM,WAAW,WAAW,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MACrE,CAAC;AACD,aAAO;AAAA,QACL,SACE,UAAU,MAAM,EAAE,uBAAuB,MAAM,KAAK,SAAI,MAAM,GAAG,OAAO,SAAS,MAAM;AAAA,IACvF,MAAM;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,oBAA6B;AAAA,IACjC,MAAM;AAAA,IACN,aACE;AAAA,IACF,cAAc,CAAC,mCAAmC;AAAA,IAClD,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU,CAAC,WAAW,WAAW;AAAA,MACjC,YAAY;AAAA,QACV,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,MAAM,EAAE,MAAM,UAAU,aAAa,gDAAgD;AAAA,QACrF,WAAW,EAAE,MAAM,UAAU,aAAa,uDAAuD;AAAA,MACnG;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,OAAO,MAAM,IAAI,SAAS;AAChC,YAAM,IAAI,UAAU,YAAY;AAChC,YAAM,QAAQ,MAAM,WAAW,UAAU,MAAM,SAAS,WAAW,GAAG,CAAC;AACvE,YAAMA,UAAS,MAAM;AACrB,YAAM,YAAY,UAAU,MAAM,WAAW,aAAa,GAAK;AAC/D,YAAM,OAAO;AAAA,QACX,MAAM,QAAQA,QAAO,SAAS,MAAM,SAAS;AAAA,QAC7C;AAAA,QACA;AAAA,MACF;AACA,YAAM,EAAE,UAAU,SAAS,SAAAC,SAAQ,IAAI,yBAAyBD,QAAO,MAAM;AAC7E,UAAI,SAAS,WAAW;AACtB,cAAM,IAAI;AAAA,UACR,UAAU,MAAM,EAAE;AAAA,QAEpB;AACF,YAAM,SAAS,eAAe,QAAQ;AACtC,YAAM,WAAW,MAAM,IAAI,eAAe;AAAA,QACxC,YAAY,IAAI,MAAM;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,UAAU,gBAAgB,QAAQ,QAAQ,UAAU,eAAe,MAAM,GAAG;AAAA,QAC7F;AAAA,QACA,eAAe,MAAM;AAAA,MACvB,CAAC;AACD,UACE,SAAS,WAAW,KAAK,MACzB,SAAS,cAAc,IAAI,KAAK,UAChC,SAAS,SAAS,aAClB,SAAS,WAAW,OACpB,OAAM,IAAI,gBAAgB,oDAAoD;AAChF,YAAM,QAAQ;AAAA,QACZ,QAAQ,SAAS,IACb,6CAA6C,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,WAAM,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC,MACtG;AAAA,QACJC,SAAQ,SAAS,IAAI,2CAA2CA,SAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,MAC1F,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACxB,aAAO;AAAA,QACL,SACE,2BAA2B,SAAS,EAAE,MAAM,IAAI,kBAAkB,MAAM,EAAE,KACvE,SAAS,MAAM,+DACL,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,OACxF,GAAG,MAAM,KAAK,GAAG,CAAC,4DAA4D,KAAK;AAAA,MACvF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,YAAY,kBAAkB,iBAAiB;AACzD;;;ACtNA,IAAM,MAAM,CAAC,OAAuB,IAAI,KAAK,EAAE,EAAE,YAAY;AAE7D,IAAM,UAAU,CAAC,OACf,GAAG,UAAU,KAAK,KAAK,GAAG,GAAG,MAAM,GAAG,CAAC,CAAC,SAAI,GAAG,MAAM,EAAE,CAAC;AAC1D,IAAM,iBAAiB,CACrB,IACA,cACW;AACX,QAAM,QAAQ,UAAU,IAAI,EAAE;AAC9B,SAAO,QACH,GAAG,MAAM,WAAW,KAAK,MAAM,IAAI,SAAM,QAAQ,EAAE,CAAC,MACpD,sBAAsB,QAAQ,EAAE,CAAC;AACvC;AAEA,SAAS,UACP,MACA,WACU;AACV,QAAM,QAAQ;AAAA,IACZ,eAAe,KAAK,IAAI,MAAM,KAAK,IAAI,YAAO,KAAK,MAAM;AAAA,IACzD,YAAY,KAAK,UAAU,IAAI,CAAC,OAAO,eAAe,IAAI,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAChF,mBAAmB,KAAK,mBAAmB,qBAAqB;AAAA,IAChE,KAAK,SACD,oBAAoB,IAAI,KAAK,OAAO,UAAU,CAAC,SAAS,KAAK,OAAO,SAAS,MAAM,gBACnF;AAAA,EACN;AACA,MAAI,KAAK,QAAS,OAAM,KAAK,YAAY,KAAK,OAAO,EAAE;AACvD,SAAO;AACT;AAEA,SAAS,WACP,UACA,UACA,WACA,WACU;AACV,SAAO;AAAA,IACL;AAAA,IACA,GAAI,SAAS,SACT,SAAS,IAAI,CAAC,MACZ,KAAK,EAAE,IAAI,KAAK,EAAE,MAAM,aAAa,IAAI,EAAE,SAAS,CAAC,SACrD,eAAe,EAAE,WAAW,SAAS,CAAC,IACxC,CAAC,UAAU;AAAA,IACf;AAAA,IACA,GAAI,SAAS,SACT,SAAS,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,SAAS,MAAM,YAAY,IACrG,CAAC,UAAU;AAAA,IACf;AAAA,IACA,GAAI,UAAU,SACV,UAAU,IAAI,CAAC,MACb,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,QAAQ,eAAe,EAAE,WAAW,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,IACtF,CAAC,UAAU;AAAA,EACjB;AACF;AAQO,SAAS,UAAU,KAA8B;AACtD,QAAM,gBAAyB;AAAA,IAC7B,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,IAC9C,SAAS,IAAI,MAAM,YAAY;AAC7B,YAAM,iBAAiB,MAAM,IAAI,SAAS;AAC1C,YAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAAA,QAC7B,CAAC,SAAS,OAAO,GAAG;AAAA,UAClB,GAAG,EAAE,OAAO,EAAE,QAAQ,IAAI,OAAO,GAAG,OAAO,EAAE,WAAW,MAAM,EAAE;AAAA,UAChE,MAAM,CAAC;AAAA,QACT;AAAA,QACA,CAAC,SAAS,OAAO,GAAG;AAAA,UAClB,GAAG,EAAE,OAAO,EAAE,QAAQ,IAAI,OAAO,GAAG,OAAO,EAAE,WAAW,MAAM,EAAE;AAAA,UAChE,MAAM,CAAC;AAAA,QACT;AAAA,QACA,CAAC,SAAS,QAAQ,GAAG;AAAA,UACnB,GAAG;AAAA,YACD,OAAO,EAAE,QAAQ,IAAI,QAAQ,QAAQ,OAAO;AAAA,YAC5C,OAAO,EAAE,WAAW,MAAM;AAAA,UAC5B;AAAA,UACA,MAAM,CAAC;AAAA,QACT;AAAA,MACF,CAAC;AACD,YAAM,SAAS,CACb,SACS,KAAa,OAAO,CAAC,QAC9B,IAAI,WAAW,eAAe,MAC9B,MAAM,QAAQ,IAAI,IAAI,KACtB,IAAI,KAAK,WAAW,KACpB,IAAI,KAAK,CAAC,GAAG,OAAO,eAAe,EAAE;AACvC,YAAM,WAAW;AAAA,QACf,IAAI,SAAS,OAAO,KAAK,CAAC;AAAA,MAC5B;AACA,YAAM,WAAW;AAAA,QACf,IAAI,SAAS,OAAO,KAAK,CAAC;AAAA,MAC5B;AACA,YAAM,YAAY;AAAA,QAChB,IAAI,SAAS,QAAQ,KAAK,CAAC;AAAA,MAC7B;AACA,YAAM,MAAM;AAAA,QACV,GAAG,eAAe;AAAA,QAClB,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,SAAS;AAAA,QAC9C,GAAG,UAAU,IAAI,CAAC,aAAa,SAAS,SAAS;AAAA,MACnD;AACA,YAAM,YAAY,IAAI;AAAA,SACnB,MAAM,IAAI,kBAAkB,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,IAAI,SAAS,CAAC;AAAA,MACjF;AACA,aAAO;AAAA,QACL,SAAS;AAAA,UACP,GAAG,UAAU,gBAAgB,SAAS;AAAA,UACtC,GAAG,WAAW,UAAU,UAAU,WAAW,SAAS;AAAA,QACxD,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,aAAsB;AAAA,IAC1B,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,WAAW,GAAG,aAAa,4BAA4B;AAAA,MAC3F;AAAA,IACF;AAAA,IACA,SAAS,IAAI,MAAM,OAAO,UAAU;AAClC,YAAM,IAAI,SAAS;AACnB,YAAM,QAAiC,EAAE,QAAQ,IAAI,QAAQ,QAAQ,OAAO;AAC5E,UAAI,MAAM,SAAS,QAAW;AAC5B,YAAI,OAAO,MAAM,SAAS,YAAY,CAAE,YAAkC,SAAS,MAAM,IAAI,GAAG;AAC9F,gBAAM,IAAI,gBAAgB,wBAAwB,YAAY,KAAK,IAAI,CAAC,EAAE;AAAA,QAC5E;AACA,cAAM,OAAO,MAAM;AAAA,MACrB;AACA,YAAM,MAAM,MAAM,IAAI,GAAG,MAAM;AAAA,QAC7B,CAAC,SAAS,KAAK,GAAG;AAAA,UAChB,GAAG,EAAE,OAAO,OAAO,EAAE,WAAW,MAAM,EAAE;AAAA,UACxC,MAAM,CAAC;AAAA,QACT;AAAA,MACF,CAAC;AACD,YAAM,QAAS,IAAI,SAAS,KAAK,KAAK,CAAC,GAEpC,OAAO,CAAC,UACT,MAAM,WAAW,IAAI,UACrB,MAAM,QAAQ,MAAM,IAAI,KACxB,MAAM,KAAK,WAAW,KACtB,MAAM,KAAK,CAAC,GAAG,OAAO,IAAI,MAAM;AAClC,UAAI,KAAK,WAAW,GAAG;AACrB,eAAO,EAAE,SAAS,MAAM,OAAO,OAAO,OAAO,MAAM,IAAI,CAAC,0BAA0B,2BAA2B;AAAA,MAC/G;AACA,YAAM,QAAQ,KAAK;AAAA,QACjB,CAACC,OACC,GAAGA,GAAE,EAAE,WAAMA,GAAE,IAAI,KAAKA,GAAE,WAAW,KAAKA,GAAE,IAAI,SAC7CA,GAAE,QAAQ,MAAMA,GAAE,KAAK,MAAM,EAAE,GAAGA,GAAE,WAAW,gBAAgB,iBAAiB;AAAA,MACvF;AACA,aAAO,EAAE,SAAS,MAAM,KAAK,IAAI,EAAE;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,SAAO,CAAC,eAAe,UAAU;AACnC;;;ACzBO,IAAM,qBACX;AAwBK,SAAS,WAAW,MAA6B;AACtD,MACE,KAAK,eAAe,gBAAgB,KAAK,KAAK,UAC9C,CAAC,KAAK,eAAe,cACrB,OAAM,IAAI,oBAAoB,2CAA2C;AAC3E,QAAM,OAAO,YAAY,EAAE,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC;AAC1E,QAAM,kBAAkB,oBAAI,IAA6B;AACzD,QAAM,YAAY,CAAC,eACjB,QAAQ,QAAQ,KAAK,oBAAoB;AAAA,IACrC,SAAS,KAAK,KAAK;AAAA,IACnB,QAAQ,KAAK;AAAA,IACb;AAAA,EACF,CAAC,KAAK,IAAI,EAAE,KAAK,CAAC,WAAW;AAC3B,QAAI,CAAC,UAAU,OAAO,eAAe,cAAc,CAAC,OAAO;AACzD,YAAM,IAAI,oBAAoB,eAAe,UAAU,mBAAmB,KAAK,MAAM,EAAE;AACzF,WAAO;AAAA,EACT,CAAC;AACL,QAAM,MAAoB;AAAA,IACxB,IAAI,KAAK;AAAA,IACT,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,qBAAqB,KAAK,wBAAwB;AAAA,IAClD,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,YAAY,KAAK;AAAA,IACjB,gBAAgB,CAAC,UAAU,KAAK,YAAY,eAAe;AAAA,MACzD,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,GAAG;AAAA,IACL,CAAC;AAAA,IACD,qBAAqB,CAAC,UAAU,KAAK,YAAY,oBAAoB;AAAA,MACnE,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,GAAG;AAAA,IACL,CAAC;AAAA,IACD,kBAAkB,CAAC,YAAY,KAAK,YAAY,iBAAiB;AAAA,MAC/D,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb;AAAA,IACF,CAAC;AAAA,IACD,oBAAoB,CAAC,YAAY;AAC/B,YAAM,SAAS,gBAAgB,IAAI,OAAO;AAC1C,UAAI,OAAQ,QAAO;AACnB,YAAM,UAAU,KAAK,YAClB,iBAAiB,EAAE,OAAO,KAAK,YAAY,QAAQ,KAAK,QAAQ,QAAQ,CAAC,EACzE;AAAA,QAAK,CAAC,YACL,kBAAkB,IAAI,YAAY,EAAE,OAAO,QAAQ,KAAK,CAAC,EAAE;AAAA,MAC7D;AAEF,cAAQ,MAAM,MAAM,gBAAgB,OAAO,OAAO,CAAC;AACnD,sBAAgB,IAAI,SAAS,OAAO;AACpC,aAAO;AAAA,IACT;AAAA,IACA,mBAAmB,CAAC,iBAAiB;AACnC,YAAM,MAAM,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,EAAE,MAAM,GAAG,GAAG;AACnD,aAAO,KAAK,kBAAkB;AAAA,QAC5B,kBAAkB,KAAK,KAAK;AAAA,QAC5B,QAAQ,KAAK;AAAA,QACb,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,IACA;AAAA,IACA,UAAU,YAAY;AACpB,YAAM,UAAU,YAAY;AAC5B,YAAM,MAAM,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,SAAS,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,KAAK,OAAO,EAAE,EAAE,EAAE,CAAC;AAC1F,YAAM,OAAO,IAAI,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC;AACxC,UAAI,CAAC,OAAO,CAAC,IAAI,UAAU,SAAS,KAAK,KAAK,MAAM;AAClD,cAAM,IAAI,mBAAmB,cAAc,KAAK,MAAM,EAAE;AAC1D,aAAO;AAAA,IACT;AAAA,IACA,OAAO,CAAC,YAAY,OAAO,OAAO,YAAY;AAC5C,UAAI;AACF,eAAO,MAAM,QAAQ,OAAO,OAAO;AAAA,MACrC,SAAS,OAAO;AACd,YACE,iBAAiB,mBACjB,iBAAiB,sBACjB,iBAAiB,qBACjB;AACA,iBAAO,EAAE,SAAS,MAAM,SAAS,SAAS,KAAK;AAAA,QACjD;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,IACd,OAAO;AAAA,MACL,GAAG,UAAU,GAAG;AAAA,MAChB,GAAG,WAAW,GAAG;AAAA,MACjB,GAAG,YAAY,GAAG;AAAA,MAClB,GAAG,aAAa,GAAG;AAAA,MACnB,GAAG,UAAU,GAAG;AAAA,IAClB;AAAA,EACF;AACF;;;ACvQO,IAAM,uBACX;AAyBK,SAAS,mBAAmB,MAAuC;AACxE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK,UAAU;AAAA,IACvB,WAAW,KAAK,aAAa;AAAA,IAC7B,UAAU,KAAK,YAAY;AAAA,IAC3B,QAAQ,CAAC,WAAW,KAAK,KAAK,GAAG,GAAI,KAAK,UAAU,CAAC,CAAE;AAAA,EACzD;AACF;AAqBO,SAAS,oBAAoB,MAAmD;AACrF,QAAM,OAAO,MAAM;AACnB,SAAO,CAAC,EAAE,MAAM,oBAAoB,KAAK,WAAW,KAAK;AAC3D;;;AC7DA,eAAsB,YACpB,KACA,MACA,SACA,gBAAgB,OACK;AACrB,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,KAAK,GAAG;AAAA,MAChB,GAAG,EAAE,OAAO,EAAE,IAAI,SAAS,QAAQ,KAAK,GAAG,EAAE;AAAA,MAC7C,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,MAAM,aAAa,SAAS,QAAQ,OAAO,SAAS,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC;AAG1E,QAAM,QAAQ,KAAK;AACnB,MACE,CAAC,OACD,IAAI,WAAW,KAAK,MACpB,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,WAAW,KACjB,MAAM,CAAC,GAAG,OAAO,KAAK,MACrB,IAAI,WAAW,UAAU,EAAE,iBAAiB,IAAI,WAAW,YAC5D,OAAM,IAAI,mBAAmB,SAAS,OAAO,EAAE;AACjD,SAAO;AACT;;;ACkGA,eAAsB,sBACpB,KACA,KACA,YACA,QACA,QAC8B;AAC9B,MAAI,IAAI,MAAM,SAAS;AACrB,UAAM,IAAI,oBAAoB,2DAA2D;AAC3F,QAAM,SAAS,MAAM,IAAI,oBAAoB;AAAA,IAC3C;AAAA,IACA,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA;AAAA,EACF,CAAC;AACD,MACE,CAAC,UACD,OAAO,qBAAqB,IAAI,MAAM,MACtC,OAAO,eAAe,cACtB,OAAO,WAAW,UAClB,OAAO,OAAO,iBAAiB,YAC/B,OAAO,aAAa,SAAS,KAC7B,OAAO,aAAa,SAAS,IAC7B,OAAM,IAAI,oBAAoB,eAAe,UAAU,IAAI,MAAM,YAAY;AAC/E,SAAO;AACT;AAGO,IAAM,OAAO,CAAC,MAAe,SAAS,KAAK,UAAkC,CAAC,MACnF,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,EACjC;AAAA,EACA,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,QAAQ;AAC5D,CAAC;AAII,IAAM,gBAAgB,CAAC,UAA6B;AACzD,MAAI,iBAAiB;AACnB,WAAO,KAAK,EAAE,OAAO,MAAM,SAAS,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC,EAAG,GAAG,GAAG;AAC9F,MAAI,iBAAiB,oBAAqB,QAAO,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,GAAG;AACnF,MAAI,iBAAiB,mBAAoB,QAAO,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,GAAG;AAClF,MAAI,iBAAiB,eAAgB,QAAO,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,GAAG;AAC9E,MAAI,iBAAiB;AACnB,WAAO,KAAK,EAAE,OAAO,MAAM,SAAS,MAAM,MAAM,KAAK,GAAG,GAAG;AAC7D,MAAI,iBAAiB,mBAAoB,QAAO,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,GAAG;AAClF,SAAO,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAC9C;AAGO,IAAM,mBAAmB,MAAgB,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AAGzF,eAAsB,SAAS,KAAgD;AAC7E,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,gBAAgB,mBAAmB;AAAA,EAC/C;AACA,MAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,MAAM,QAAQ,IAAI;AACjE,UAAM,IAAI,gBAAgB,4BAA4B;AACxD,SAAO;AACT;AAGO,SAAS,IAAI,MAA+B,KAAqB;AACtE,QAAM,QAAQ,KAAK,GAAG;AACtB,MAAI,OAAO,UAAU,YAAY,UAAU;AACzC,UAAM,IAAI,gBAAgB,IAAI,GAAG,8BAA8B;AACjE,SAAO;AACT;AAGO,SAAS,OAAO,MAA+B,KAAiC;AACrF,QAAM,QAAQ,KAAK,GAAG;AACtB,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,gBAAgB,IAAI,GAAG,oBAAoB;AACpF,SAAO;AACT;AAGO,SAAS,YAAY,MAA+B,KAAmC;AAC5F,QAAM,QAAQ,KAAK,GAAG;AACtB,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ;AAClE,UAAM,IAAI,gBAAgB,IAAI,GAAG,+BAA+B;AAClE,SAAO;AACT;AAGO,SAAS,SAAS,MAAiB,SAA0B;AAClE,SAAO,MAAM,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,SAAS,OAAO;AACzE;AAGA,eAAsB,SAAS,IAAa,QAAoC;AAC9E,QAAM,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,EAAE,EAAE,CAAC;AAChF,QAAM,OAAO,IAAI,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC;AACxC,MAAI,CAAC,IAAK,OAAM,IAAI,mBAAmB,cAAc,MAAM,EAAE;AAI7D,SAAO,aAAa,SAAS,MAAM,GAAG;AACxC;AAIA,eAAsB,eAAe,IAAa,QAAgB,SAAqC;AACrG,QAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AACtC,MAAI,CAAC,SAAS,MAAM,OAAO,EAAG,OAAM,IAAI,mBAAmB,cAAc,MAAM,EAAE;AACjF,SAAO;AACT;;;ACrOA,eAAe,SAAS,KAAiC;AACvD,MAAI;AACF,WAAO,MAAM,IAAI,SAAS;AAAA,EAC5B,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,cAAc,MAA6B;AACxD,QAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,MAAM,KAAK,YAAY,CAAC;AAC3E,SAAO,UAAU,CAAC,GAAG,IAAI,WAAW,IAAI,CAAC,EACtC,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE,CAAC;AACb;AAEA,eAAsB,YACpB,KACA,KACA,QACmB;AACnB,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,QAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,MAAI,EAAE,gBAAgB;AACpB,UAAM,IAAI,gBAAgB,uCAAuC;AAInE,QAAM,UAAU,KAAK,IAAI,MAAM;AAC/B,QAAM,OAAO,OAAO,YAAY,YAAY,UAAU,UAAU;AAChE,MAAI,CAAE,YAAkC,SAAS,IAAI;AACnD,UAAM,IAAI,gBAAgB,wBAAwB,YAAY,KAAK,IAAI,CAAC,EAAE;AAC5E,MAAI;AACJ,MAAI;AACF,kBAAc,uBAAuB,KAAK,MAAM,IAAI;AAAA,EACtD,SAAS,OAAO;AACd,QAAI,iBAAiB;AACnB,aAAO,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,GAAG;AAC3C,UAAM;AAAA,EACR;AACA,MAAI,KAAK,OAAO,IAAI;AAClB,WAAO,KAAK,EAAE,OAAO,gBAAgB,IAAI,cAAc,SAAS,GAAG,GAAG;AAIxE,QAAM,SACJ,SAAS,oBAAoB,iBAAiB,MAAM,KAAK,KAAK,CAAC,IAAI;AACrE,QAAM,WAAW,KAAK,IAAI,OAAO;AACjC,QAAM,QAAQ,OAAO,aAAa,YAAY,WAC1C,UAAU,UAAU,SAAS,GAAG,IAChC;AACJ,QAAM,WAAW,aAAa,KAAK,IAAI;AACvC,QAAM,KAAK,IAAI,MAAM;AACrB,QAAM,OAAO,SAAS,KAAK,EAAE,WAAW,EAAE,IAAI,QAAQ;AACtD,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAc;AAAA,IAAY,KAAK;AAAA,EAC3C;AACA,QAAMC,UAAS,MAAM,IAAI,GAAG,QAAQ;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,SAAS,KAAK;AAAA,EAClB;AACA,MAAIA,QAAO,SAAS,MAAM;AACxB,UAAM,IAAI,GAAG,QAAQ,OAAOA,QAAO,IAAI;AACvC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI;AACF,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAc;AAAA,MAAY,KAAK;AAAA,IAC3C;AACA,QAAI,QAAQ,iBAAiB,UAAU;AACrC,YAAM,IAAI,mBAAmB,4CAA4C;AAC3E,UAAM,IAAI,GAAG,SAAS,eAAe;AAAA,MACnC;AAAA,MACA,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,MAAMA,QAAO;AAAA,MACb,iBAAiBA,QAAO;AAAA,MACxB,eAAe,MAAM,cAAc,IAAI;AAAA,MACvC;AAAA,MACA,MAAMA,QAAO;AAAA,MACb,YAAY,IAAI,MAAM;AAAA,MACtB,sBAAsB,UAAU;AAAA,MAChC,UAAU,KAAK;AAAA,MACf;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,KAAK,IAAI,IAAI;AAAA,IACf,CAAC,GAAG;AAAA,MACF,YAAY,yBAAyB,EAAE;AAAA,MACvC,QAAQ;AAAA,QACN,EAAE,IAAI,SAAS,OAAO,IAAI,QAAQ,MAAM;AAAA,QACxC;AAAA,UACE,IAAI,SAAS;AAAA,UACb,IAAI,KAAK;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,SAAS,KAAK;AAAA,YACd,oBAAoB,KAAK;AAAA,YACzB,WAAW,KAAK;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,MACA,QAAQ,IAAI,MAAM;AAAA,MAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,MACtD,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,GAAG,QAAQ,OAAOA,QAAO,IAAI;AACvC,UAAM;AAAA,EACR;AACA,SAAO,KAAK,MAAM,YAAY,KAAK,MAAM,EAAE,GAAG,GAAG;AACnD;;;AC3GA,eAAsB,iBACpB,KACA,KACA,QACmB;AACnB,MAAI,IAAI,WAAW,OAAQ,QAAO,YAAY,KAAK,KAAK,MAAM;AAC9D,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,KAAK,GAAG;AAAA,MAChB,GAAG,EAAE,OAAO,EAAE,QAAQ,KAAK,IAAI,QAAQ,OAAO,GAAG,OAAO,EAAE,WAAW,MAAM,EAAE;AAAA,MAC7E,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,UAAU,OAAO,SAAS,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU;AAC9D,UAAM,MAAM;AACZ,WAAO,IAAI,WAAW,KAAK,MACzB,MAAM,QAAQ,IAAI,IAAI,KACtB,IAAI,KAAK,WAAW,KACpB,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK;AAAA,EAC7B,CAAC;AACD,SAAO,KAAK,EAAE,OAAO,CAAC;AACxB;AAIA,eAAsB,mBACpB,KACA,KACA,QACA,SACmB;AACnB,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,QAAM,QAAQ,MAAM,YAAY,KAAK,MAAM,OAAO;AAClD,QAAM,mBAAmB;AACzB,QAAM,MAAM,MAAM,IAAI,GAAG,QAAQ,KAAK,MAAM,MAAM,gBAAgB;AAClE,SAAO;AAAA,IACL,EAAE,SAAS,KAAK,iBAAiB;AAAA,IACjC;AAAA,IACA,EAAE,iBAAiB,qBAAqB,0BAA0B,UAAU;AAAA,EAC9E;AACF;AAIA,eAAsB,gBACpB,KACA,KACA,QACA,SACmB;AACnB,MAAI,IAAI,WAAW,SAAU,QAAO,iBAAiB;AACrD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,MAAI,QAAQ,MAAM,YAAY,KAAK,MAAM,SAAS,IAAI;AACtD,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAc;AAAA,IAAe,KAAK;AAAA,EAC9C;AACA,QAAM,eAAe,yBAAyB,KAAK,EAAE,IAAI,MAAM,EAAE;AACjE,MAAI,MAAM,WAAW,QAAQ;AAC3B,UAAM,YAAY,IAAI,IAAI;AAC1B,QAAI;AACF,YAAM,IAAI,GAAG,SAAS;AAAA,QACpB,MAAM;AAAA,QACN;AAAA,QACA,IAAI,MAAM;AAAA,QACV,UAAU;AAAA,MACZ,GAAG;AAAA,QACD,YAAY,GAAG,YAAY;AAAA,QAC3B,QAAQ;AAAA,UACN;AAAA,YACE,IAAI,SAAS;AAAA,YACb,IAAI,MAAM;AAAA,YACV,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,QAAQ,KAAK;AAAA,cACb,MAAM,MAAM;AAAA,cACZ,iBAAiB,MAAM;AAAA,cACvB,eAAe,MAAM;AAAA,cACrB,QAAQ;AAAA,YACV;AAAA,UACF;AAAA,UACA;AAAA,YACE,IAAI,SAAS;AAAA,YACb,IAAI,KAAK;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ,EAAE,SAAS,KAAK,SAAS,WAAW,KAAK,UAAU;AAAA,UAC7D;AAAA,QACF;AAAA,QACA,QAAQ,IAAI,MAAM;AAAA,QAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,QACtD,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UACE,OAAO,UAAU,YACjB,UAAU,QACT,MAA6B,SAAS,wBACvC,OAAM,IAAI,mBAAmB,+BAA+B;AAC9D,YAAM;AAAA,IACR;AACA,YAAQ,EAAE,GAAG,OAAO,QAAQ,YAAY,UAAU;AAAA,EACpD;AACA,QAAM,IAAI,GAAG,QAAQ,OAAO,MAAM,IAAI;AACtC,QAAM,IAAI,GAAG,SAAS,qBAAqB,MAAM,EAAE,GAAG;AAAA,IACpD,YAAY,GAAG,YAAY;AAAA,IAC3B,QAAQ,CAAC;AAAA,MACP,IAAI,SAAS;AAAA,MACb,IAAI,MAAM;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,MAAM,MAAM;AAAA,QACZ,iBAAiB,MAAM;AAAA,QACvB,eAAe,MAAM;AAAA,QACrB,QAAQ;AAAA,QACR,WAAW,MAAM,aAAa,IAAI,MAAM;AAAA,QACxC,qBAAqB,MAAM,uBAAuB,UAAU;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,IACD,QAAQ,IAAI,MAAM;AAAA,IAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,IACtD,iBAAiB;AAAA,EACnB,CAAC;AACD,SAAO,KAAK,EAAE,IAAI,MAAM,IAAI,QAAQ,WAAW,WAAW,MAAM,UAAU,CAAC;AAC7E;;;AChHA,eAAsB,gBAAgB,KAAoB,KAAiC;AACzF,MAAI,IAAI,WAAW,OAAO;AACxB,UAAM,MAAM,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,SAAS,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,MAAM,EAAE,EAAE,EAAE,CAAC;AAC1F,UAAM,SAAU,IAAI,SAAS,IAAI,KAAK,CAAC,GACpC,IAAI,CAAC,MAAM,aAAa,SAAS,MAAM,CAAC,CAAC,EACzC;AAAA,MAAO,CAAC,MACT,SAAS,GAAG,IAAI,MAAM,EAAE;AAAA,IAC1B;AACA,WAAO,KAAK,EAAE,MAAM,CAAC;AAAA,EACvB;AACA,MAAI,IAAI,WAAW,QAAQ;AACzB,QAAI,IAAI,MAAM,SAAS;AACrB,YAAM,IAAI,oBAAoB,sCAAsC;AACtE,UAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,UAAM,KAAK,IAAI,MAAM;AACrB,UAAM,YAAY,MAAM;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,MAAM,cAAc;AAAA,MACxB;AAAA,MACA,MAAM,IAAI,MAAM,MAAM;AAAA,MACtB,MAAM,IAAI,MAAM,MAAM;AAAA,MACtB,SAAS,IAAI,MAAM;AAAA,MACnB,qBAAqB,UAAU;AAAA,MAC/B,WAAW,YAAY,MAAM,WAAW,KAAK,CAAC;AAAA,MAC9C,WAAW,OAAO,MAAM,WAAW;AAAA,MACnC,KAAK,IAAI,IAAI;AAAA,IACf,CAAC;AACD,UAAM,IAAI,GAAG,SAAS,KAAK;AAAA,MACzB,YAAY;AAAA,MACZ,QAAQ,CAAC,EAAE,IAAI,SAAS,MAAM,IAAI,QAAQ,MAAM,CAAC;AAAA,MACjD,QAAQ,IAAI,MAAM;AAAA,MAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,MACtD,iBAAiB;AAAA,IACnB,CAAC;AACD,WAAO,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,GAAG,GAAG;AAAA,EAC7C;AACA,SAAO,iBAAiB;AAC1B;AAEA,IAAM,cAAc,CAAC,MAAgB,UACnC,KAAK,WAAW,MAAM,UAAU,KAAK,MAAM,CAAC,OAAO,UAAU,UAAU,MAAM,KAAK,CAAC;AACrF,IAAM,eAAe,CAAC,UACpB,OAAO,UAAU,YAAY,UAAU,QACtC,MAA6B,SAAS;AAIzC,eAAsB,kBACpB,KACA,KACA,QACmB;AACnB,MAAI,IAAI,WAAW,QAAS,QAAO,iBAAiB;AACpD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,MAAI,IAAI,MAAM,SAAS;AACrB,UAAM,IAAI,oBAAoB,2CAA2C;AAC3E,QAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,QAAM,aAAa,YAAY,MAAM,WAAW;AAChD,QAAM,cAAc,YAAY,MAAM,mBAAmB;AACzD,MAAI,CAAC,cAAc,CAAC;AAClB,UAAM,IAAI,gBAAgB,gEAAgE;AAC5F,QAAM,YAAY,MAAM,KAAK,oBAAI,IAAI;AAAA,IACnC,KAAK;AAAA,IACL,GAAG,WAAW,IAAI,CAAC,IAAI,UAAU,UAAU,IAAI,aAAa,KAAK,KAAK,GAAG,CAAC;AAAA,EAC5E,CAAC,CAAC;AACF,MAAI,UAAU,SAAS;AACrB,UAAM,IAAI,gBAAgB,2CAA2C;AACvE,QAAM,oBAAoB,YAAY,IAAI,CAAC,IAAI,UAC7C,UAAU,IAAI,qBAAqB,KAAK,KAAK,GAAG,CAAC;AACnD,MAAI,CAAC,YAAY,KAAK,WAAW,iBAAiB,KAAK,CAAC,YAAY,KAAK,WAAW,SAAS;AAC3F,UAAM,IAAI,mBAAmB,4CAA4C;AAE3E,QAAM,aAAa,UAAU,IAAI,MAAM,YAAY,GAAG,cAAc,GAAG;AACvE,QAAM,cAAc,yBAAyB,MAAM,IAAI,UAAU;AACjE,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI;AACF,UAAM,KAAK,MAAM,IAAI,GAAG;AAAA,MACtB,CAAC;AAAA,QACC,GAAG;AAAA,QACH,IAAI,SAAS;AAAA,QACb,IAAI;AAAA,QACJ,OAAO;AAAA,UACL;AAAA,UACA,SAAS,KAAK,UAAU;AAAA,UACxB,WAAW,IAAI,IAAI;AAAA,UACnB,oBAAoB,UAAU;AAAA,QAChC;AAAA,MACF,CAAC;AAAA,MACD;AAAA,QACE,YAAY;AAAA,QACZ,QAAQ,CAAC;AAAA,UACP,IAAI,SAAS;AAAA,UACb,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,QAAQ,EAAE,WAAW,mBAAmB,SAAS,KAAK,QAAQ;AAAA,QAChE,CAAC;AAAA,QACD,QAAQ,IAAI,MAAM;AAAA,QAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,QACtD,iBAAiB;AAAA,MACnB;AAAA,IACF;AACA,WAAO,KAAK,EAAE,QAAQ,WAAW,WAAW,GAAG,cAAc,KAAK,CAAC;AAAA,EACrE,SAAS,OAAO;AACd,QAAI,aAAa,KAAK;AACpB,YAAM,IAAI,mBAAmB,4CAA4C;AAC3E,UAAM;AAAA,EACR;AACF;AAIA,eAAsB,eAAe,KAAoB,KAAc,QAAmC;AACxG,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,SAAO,KAAK,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;AAChE;;;AClIA,IAAM,0BAA0B;AAWzB,SAAS,qBAAqB,gBAAkD;AACrF,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,2BAA2B;AAAA,MACzB;AAAA,MACA,mBAAmB,eAAe,KAAK,GAAG,CAAC;AAAA,IAC7C,EAAE,KAAK,IAAI;AAAA,IACX,0BAA0B;AAAA,IAC1B,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,EACnB;AACF;AAQA,eAAsB,oBACpB,KACA,KACA,QACA,SACmB;AACnB,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,QAAM,QAAQ,MAAM,YAAY,KAAK,MAAM,OAAO;AAClD,MAAI,MAAM,SAAS,kBAAmB,OAAM,IAAI,mBAAmB,UAAU,OAAO,EAAE;AACtF,QAAM,SAAS,MAAM,IAAI,GAAG,QAAQ,KAAK,MAAM,MAAM,uBAAuB;AAI5E,QAAM,oBAAoB,IAAI;AAC9B,QAAM,UAAU,MAAM,kBAAkB,QAAQ;AAAA,IAC9C,SAAS,EAAE,QAAQ,YAAY;AAAA,IAC/B,UAAU;AAAA,IACV,QAAQ,IAAI;AAAA,EACd,CAAC;AACD,MAAI,CAAC,QAAQ,MAAM,QAAQ,SAAS;AAClC,UAAM,IAAI,mBAAmB,UAAU,OAAO,EAAE;AAClD,SAAO,IAAI,SAAS,IAAI,WAAW,MAAM,QAAQ,YAAY,CAAC,GAAG;AAAA,IAC/D,QAAQ;AAAA,IACR,SAAS,qBAAqB,IAAI,qBAAqB;AAAA,EACzD,CAAC;AACH;AAQA,eAAsB,mBACpB,KACA,KACA,QACA,SACmB;AACnB,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,QAAM,QAAQ,MAAM,YAAY,KAAK,MAAM,OAAO;AAClD,MAAI,MAAM,SAAS,qBAAqB,CAAC,MAAM;AAC7C,UAAM,IAAI,mBAAmB,UAAU,OAAO,EAAE;AAClD,SAAO;AAAA,IACL,EAAE,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAO;AAAA,IAC9D;AAAA,IACA,EAAE,iBAAiB,oBAAoB;AAAA,EACzC;AACF;;;ACtGA,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAMC,UAAS,CAAC,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAS9D,SAAS,+BACd,MACA,QACA,YAC2B;AAC3B,QAAM,UAAU,oBAAI,IAAI;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,OAAO,KAAK,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;AACnD,UAAM,IAAI,gBAAgB,6CAA6C;AACzE,QAAM,aAAa,UAAU,IAAI,MAAM,YAAY,GAAG,cAAc,GAAG;AACvE,QAAM,gBAAgB,IAAI,MAAM,YAAY;AAC5C,MAAI,kBAAkB,cAAc,kBAAkB;AACpD,UAAM,IAAI,gBAAgB,+CAA+C;AAC3E,QAAM,UAAU,OAAO,MAAM,MAAM;AACnC,QAAM,iBAAiB,SAAS,KAAK,IACjC,UAAU,SAAS,QAAQ,GAAK,IAChC;AACJ,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,IACZ,UAAU,sBAAsB,KAAK,kBAAkB,QAAQ,UAAU;AAAA,IACzE,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,EAC7C;AACF;AAGO,SAAS,uBAAuB,UAAsD;AAC3F,MAAI,SAAS,WAAW;AACtB,UAAM,IAAI,mBAAmB,YAAY,SAAS,EAAE,OAAO,SAAS,MAAM,YAAY;AACxF,SAAO;AAAA,IACL,IAAI,SAAS;AAAA,IACb,QAAQ,SAAS;AAAA,IACjB,MAAM,SAAS;AAAA,IACf,QAAQ;AAAA,IACR,SAAS,SAAS;AAAA,IAClB,WAAW,SAAS;AAAA,IACpB,YAAY,SAAS;AAAA,IACrB,cAAc,SAAS;AAAA,IACvB,UAAU,SAAS;AAAA,IACnB,WAAW,SAAS;AAAA,IACpB,qBAAqB,SAAS;AAAA,IAC9B,WAAW,SAAS;AAAA,EACtB;AACF;AAGO,SAAS,sBACd,OACA,QACA,YAC6B;AAG7B,MAAI,CAAC,mBAAmB,OAAO,EAAE,UAAU,IAAI,UAAU,MAAO,UAAU,KAAK,KAAK,CAAC;AACnF,UAAM,IAAI,gBAAgB,4DAA4D;AACxF,MAAI,CAACA,QAAO,KAAK,EAAG,OAAM,IAAI,gBAAgB,sCAAsC;AACpF,QAAM,OAAO,OAAO,KAAK,KAAK,EAAE,KAAK;AACrC,MACE,KAAK,WAAW,cAAc,UAC9B,CAAC,cAAc,MAAM,CAAC,KAAK,UAAU,QAAQ,KAAK,KAAK,CAAC,EACxD,OAAM,IAAI,gBAAgB,yCAAyC;AACrE,MAAI,MAAM,OAAO,cAAc,MAAM,WAAW,UAAU,MAAM,WAAW;AACzE,UAAM,IAAI,gBAAgB,qDAAqD;AACjF,MACE,OAAO,MAAM,SAAS,YACtB,CAAE,eAAqC,SAAS,MAAM,IAAI,KAC1D,CAACA,QAAO,MAAM,OAAO,KACrB,OAAO,MAAM,cAAc,YAC3B,CAAC,MAAM,QAAQ,MAAM,QAAQ,KAC7B,MAAM,SAAS,SAAS,KACxB,MAAM,SAAS,SAAS,OACxB,MAAM,SAAS,KAAK,CAAC,OAAO,OAAO,OAAO,YAAY,GAAG,SAAS,KAAK,GAAG,SAAS,GAAG,KACtF,IAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,MAAM,SAAS,UAChD,OAAO,MAAM,cAAc,YAAY,MAAM,UAAU,SAAS,KAAK,MAAM,UAAU,SAAS,OAC9F,OAAO,MAAM,wBAAwB,YACrC,MAAM,oBAAoB,SAAS,KAAK,MAAM,oBAAoB,SAAS,OAC3E,CAAC,OAAO,cAAc,MAAM,SAAS,KAAM,MAAM,YAAuB,KACxE,OAAO,MAAM,iBAAiB,YAC9B,CAAC,wBAAwB,KAAK,MAAM,YAAY,EAChD,OAAM,IAAI,gBAAgB,uCAAuC;AACnE,MACE,CAACA,QAAO,MAAM,UAAU,KACxB,OAAO,KAAK,MAAM,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,MAC3C,4DACD,MAAM,WAAW,kBAAkB,SACjC,OAAO,MAAM,WAAW,kBAAkB,YACzC,MAAM,WAAW,cAAc,SAAS,KACxC,MAAM,WAAW,cAAc,SAAS,QAC3C,MAAM,WAAW,gBAAgB,SAC/B,CAACA,QAAO,MAAM,WAAW,WAAW,KACnC,OAAO,KAAK,MAAM,WAAW,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,MACvD,wGACF,OAAO,MAAM,WAAW,YAAY,YAAY,YAChD,MAAM,WAAW,YAAY,QAAQ,SAAS,KAC9C,MAAM,WAAW,YAAY,QAAQ,SAAS,OAC9C,OAAO,MAAM,WAAW,YAAY,eAAe,YACnD,MAAM,WAAW,YAAY,WAAW,SAAS,KACjD,MAAM,WAAW,YAAY,WAAW,SAAS,OACjD,CAAC,OAAO,cAAc,MAAM,WAAW,YAAY,UAAU,KAC5D,MAAM,WAAW,YAAY,aAAwB,KACtD,OAAO,MAAM,WAAW,YAAY,eAAe,YACnD,CAAC,wBAAwB,KAAK,MAAM,WAAW,YAAY,UAAU,KACpE,MAAM,WAAW,YAAY,gBAAgB,SAC3C,OAAO,MAAM,WAAW,YAAY,gBAAgB,YACnD,MAAM,WAAW,YAAY,YAAY,SAAS,KAClD,MAAM,WAAW,YAAY,YAAY,SAAS,QACtD,OAAO,MAAM,WAAW,YAAY,kBAAkB,YACtD,CAAC,wBAAwB,KAAK,MAAM,WAAW,YAAY,aAAa,KACvE,MAAM,WAAW,YAAY,qBAAqB,SAChD,CAAC,OAAO,cAAc,MAAM,WAAW,YAAY,gBAAgB,KACjE,MAAM,WAAW,YAAY,mBAA8B,MAC/D,MAAM,WAAW,YAAY,mBAAmB,SAC9C,OAAO,MAAM,WAAW,YAAY,mBAAmB,YACtD,CAAC,wBAAwB;AAAA,IACvB,MAAM,WAAW,YAAY;AAAA,EAC/B,MACJ,MAAM,WAAW,YAAY,YAC3B,MAAM,WAAW,kBACrB,MAAM,WAAW,kBAAkB,UAClC,MAAM,WAAW,gBAAgB,SACnC,MAAM,WAAW,cAAc,SAC7B,OAAO,MAAM,WAAW,cAAc,YACrC,MAAM,WAAW,UAAU,SAAS,KACpC,MAAM,WAAW,UAAU,SAAS,QACvC,MAAM,WAAW,WAAW,SAC1B,OAAO,MAAM,WAAW,WAAW,YAClC,MAAM,WAAW,OAAO,SAAS,KACjC,MAAM,WAAW,OAAO,SAAS,QACrC,CAAC,MAAM,QAAQ,MAAM,WAAW,WAAW,KAC3C,MAAM,WAAW,YAAY,SAAS,MACtC,MAAM,WAAW,YAAY,KAAK,CAAC,UACjC,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG,KACrE,IAAI,IAAI,MAAM,WAAW,WAAW,EAAE,SAAS,MAAM,WAAW,YAAY,OAC5E,OAAM,IAAI,gBAAgB,0CAA0C;AACtE,SAAO;AACT;AAEO,IAAM,sBAAsB,CACjC,cAC6B,EAAE,GAAG,SAAS;;;AC9I7C,eAAe,cACb,UACA,YACA,OACA,WACA,kBACA,qBACA,qBACA,wBAC8B;AAC9B,QAAM,WAAW,mBAAmB,EAAE,UAAU,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC,EAAG,CAAC;AACvF,QAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,uBAAuB;AAAA,IAC5C,wBAAwB,0BAA0B;AAAA,EACpD;AACA,SAAO;AAAA,IACL,OAAO,SAAS;AAAA,IAChB,MAAM,SAAS;AAAA,IACf,UAAU,SAAS;AAAA,IACnB,YAAY,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;AAAA,IACrD,GAAI,yBAAyB,EAAE,uBAAuB,IAAI,CAAC;AAAA,IAC3D,cAAc,MAAM,gBAAgB,OAAO;AAAA,EAC7C;AACF;AAEA,SAAS,cAAc,KAAgB,OAAkC;AACvE,QAAM,KAAK,IAAI;AAAA,IACb,CAAC,cACC,UAAU,MAAM,YAChB,UAAU,OAAO,SAAS,YAC1B,UAAU,OAAO,MAAM,SAAS;AAAA,EACpC;AACA,MAAI,CAAC,MAAM,GAAG,MAAM,SAAU,OAAM,IAAI,MAAM,gCAAgC;AAC9E,SAAO,OAAO,GAAG,OAAO;AAAA,IACtB,YAAY,MAAM;AAAA,IAClB,WAAW,MAAM;AAAA,IACjB,qBAAqB,MAAM;AAAA,IAC3B,wBAAwB,MAAM;AAAA,EAChC,CAAC;AACH;AAGA,eAAsB,oBAAoB,OAAgD;AACxF,QAAM,SAAS;AAAA,IACb,UAAU,MAAM;AAAA,IAChB,YAAY,MAAM;AAAA,IAClB,KAAK,MAAM;AAAA,IACX,gBAAgB,MAAM;AAAA,EACxB;AACA,MAAI,MAAM,eAAe,YAAY;AACnC,UAAMC,OAAM,kBAAkB,MAAM;AACpC,kBAAcA,MAAK,KAAK;AACxB,WAAOA;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,MAAM,SAAS,SAAS,WAAW;AACrC,QAAI,CAAC,MAAM,UAAW,OAAM,IAAI,MAAM,6BAA6B;AACnE,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH,WAAW,MAAM;AAAA,MACjB,mBAAmB,MAAM;AAAA,MACzB,sBAAsB,MAAM;AAAA,IAC9B,CAAC;AACD,UAAM,WAAW,eAAe,MAAM,SAAS,QAAQ,QAAQ;AAC/D,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,MAAM,oBAAoB;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,oBAAoB;AAAA,MAC1B,MAAM,oBAAoB;AAAA,IAC5B;AACA,UAAM,SAAS,IAAI;AAAA,MACjB,CAAC,OAAO,GAAG,MAAM,YAAY,GAAG,OAAO,SAAS,QAAQ,GAAG,OAAO,MAAM,KAAK;AAAA,IAC/E;AACA,QAAI,CAAC,UAAU,OAAO,MAAM,SAAU,OAAM,IAAI,MAAM,4BAA4B;AAClF,WAAO,OAAO,OAAO,OAAO;AAAA,MAC1B,SAAS,MAAM,KAAK,UAAU;AAAA,MAC9B,oBAAoB,MAAM,KAAK,qBAAqB;AAAA,MACpD;AAAA,IACF,CAAC;AACD,QAAI,MAAM,gBAAgB,MAAM,aAAa,OAAO,MAAM,WAAW;AACnE,UAAI,QAAQ;AAAA,QACV,GAAG;AAAA,QACH,IAAI,SAAS;AAAA,QACb,IAAI,MAAM,aAAa;AAAA,QACvB,OAAO,EAAE,QAAQ,YAAY,WAAW,MAAM,IAAI;AAAA,MACpD,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AACL,UAAM,UAAU,MAAM,SAAS,QAAQ;AACvC,QAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,MAAM,QAAQ,OAAO;AAC1E,YAAM,IAAI,gBAAgB,4CAA4C;AACxE,UAAM;AAAA,MACJ,GAAG,iBAAiB;AAAA,QAClB,QAAQ,MAAM,KAAK;AAAA,QACnB,MAAM,MAAM,SAAS;AAAA,QACrB;AAAA,QACA,QAAQ;AAAA,QACR,UAAU,MAAM,KAAK;AAAA,QACrB,WAAW,MAAM;AAAA,QACjB,mBAAmB,MAAM;AAAA,QACzB,sBAAsB,MAAM;AAAA,QAC5B,KAAK,MAAM;AAAA,MACb,CAAC;AAAA,MACD;AAAA,QACE,GAAG;AAAA,QACH,IAAI,SAAS;AAAA,QACb,IAAI,MAAM,KAAK;AAAA,QACf,OAAO;AAAA,UACL,oBAAoB,MAAM,KAAK,qBAAqB;AAAA,UACpD,SAAS,MAAM,KAAK,UAAU;AAAA,UAC9B,WAAW,MAAM;AAAA,QACnB;AAAA,MACF;AAAA,MACA;AAAA,QACE,GAAG;AAAA,QACH,IAAI,SAAS;AAAA,QACb,IAAI,MAAM,SAAS;AAAA,QACnB,OAAO;AAAA,UACL,QAAQ;AAAA,UACR,YAAY,MAAM;AAAA,UAClB,YAAY,MAAM;AAAA,UAClB,GAAI,MAAM,iBAAiB,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AACA,QAAI,MAAM,SAAS,SAAS,gBAAgB,MAAM,cAAc;AAC9D,YAAM,SAAS,IAAI;AAAA,QACjB,CAAC,OAAO,GAAG,MAAM,YAAY,GAAG,OAAO,SAAS,QAAQ,GAAG,OAAO,MAAM,KAAK;AAAA,MAC/E;AACA,UAAI,QAAQ,MAAM,UAAU;AAC1B,YAAI,CAAC,MAAM,aAAa,qBAAqB,CAAC,MAAM,aAAa;AAC/D,gBAAM,IAAI,gBAAgB,+CAA+C;AAC3E,eAAO,MAAM,SAAS,MAAM;AAAA,UAC1B,MAAM,aAAa;AAAA,UACnB;AAAA,UACA;AAAA,UACA,MAAM,aAAa;AAAA,UACnB,MAAM,aAAa;AAAA,UACnB,MAAM,aAAa;AAAA,UACnB,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,gBAAc,KAAK,KAAK;AACxB,SAAO;AACT;;;AC9KA,eAAsB,8BACpB,QACA,YACA,YACiB;AACjB,QAAMC,UAAS,MAAM,gBAAgB;AAAA,IACnC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,gCAAgCA,QAAO,MAAM,UAAU,MAAM,CAAC;AACvE;AAEA,eAAsB,0BACpB,KACA,aAC2C;AAC3C,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,eAAe,GAAG;AAAA,MAC1B,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE;AAAA,MAC5B,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,SAAS,eAAe,KAAK,CAAC,GAAG,CAAC;AAGtD,MACE,CAAC,OACD,CAAC,MAAM,QAAQ,IAAI,IAAI,KACvB,IAAI,KAAK,WAAW,KACpB,IAAI,KAAK,CAAC,GAAG,OAAO,IAAI,OACxB,QAAO;AACT,QAAM,EAAE,MAAM,OAAO,GAAGC,SAAQ,IAAI;AAGpC,SAAO,iBAAiBA,QAAO;AACjC;AAEA,eAAsB,yBACpB,KACA,KACA,QACA,YACA,cACA,aACyC;AACzC,QAAM,YAAY,MAAM,IAAI,kBAAkB;AAAA,IAC5C;AAAA,IACA,OAAO,IAAI;AAAA,IACX,OAAO,IAAI;AAAA,IACX,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,QAAQ;AAAA,IACR,UAAU,EAAE,QAAQ,WAAW;AAAA,IAC/B;AAAA,IACA,2BAA2B;AAAA,EAC7B,CAAC;AACD,QAAM,iBAAiB,MAAM,gBAAgB,EAAE,QAAQ,WAAW,CAAC;AACnE,MACE,CAAC,iCAAiC,SAAS,KAC3C,UAAU,qBAAqB,IAAI,MAAM,MACzC,UAAU,UAAU,IAAI,SACxB,UAAU,iBAAiB,gBAC3B,UAAU,mBAAmB,kBAC7B,UAAU,8BAA8B,YACxC,OAAM,IAAI;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,8BACdA,UACA,UACA,YACA,MACA,WACS;AACT,SAAOA,SAAQ,eAAe,eAC3BA,SAAQ,kBAAkB,WAAW,QAAQ,UAC7CA,SAAQ,aAAa,WAAW,aAAa,SAC9C,mBAAmBA,SAAQ,gBAAgB,MACzC,mBAAmB,QAAQ;AACjC;;;AC9EA,eAAe,QACb,KACA,IACA,cACA,UAO+B;AAC/B,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,eAAe,GAAG;AAAA,MAC1B,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE;AAAA,MACnB,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,SAAS,eAAe,KAAK,CAAC,GAAG,CAAC;AAGtD,MACE,CAAC,OACD,IAAI,iBAAiB,gBACrB,IAAI,eAAe,cACnB,IAAI,WAAW,SAAS,UACxB,IAAI,iBAAiB,WAAW,SAAS,UACzC,IAAI,iBAAiB,SAAS,SAAS,QACvC,CAAC,MAAM,QAAQ,IAAI,IAAI,KACvB,IAAI,KAAK,WAAW,KACpB,IAAI,KAAK,CAAC,GAAG,OAAO,SAAS,UAC5B,SAAS,cAAc,UAAa,IAAI,cAAc,SAAS,aAC/D,SAAS,eAAe,UAAa,IAAI,eAAe,SAAS,cACjE,SAAS,YAAY,UACpB,mBAAmB,IAAI,iBAAiB,QAAQ,OAAO,MACrD,mBAAmB,SAAS,OAAO,EACvC,OAAM,IAAI,mBAAmB,oBAAoB,EAAE,aAAa;AAClE,QAAM,EAAE,MAAM,OAAO,GAAG,OAAO,IAAI;AACnC,QAAM,aAAa,iBAAiB,MAAM;AAC1C,MAAI,CAAE,MAAM,2BAA2B,UAAU;AAC/C,UAAM,IAAI,mBAAmB,oBAAoB,EAAE,aAAa;AAClE,SAAO;AACT;AAEA,eAAsB,cACpB,KACA,MACqE;AACrE,MAAI,CAAC,KAAK,gBAAiB,QAAO,CAAC;AACnC,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,GAAG,EAAE,OAAO,EAAE,IAAI,KAAK,gBAAgB,EAAE;AAAA,MACzC,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,WAAW,OAAO,SAAS,OAAO,KAAK,CAAC,GAAG,CAAC;AAGlD,MACE,CAAC,WACD,QAAQ,WAAW,KAAK,MACxB,QAAQ,WAAW,YACnB,CAAC,QAAQ,cACT,CAAC,QAAQ,qBACT,CAAC,QAAQ,wBACT,CAAC,MAAM,QAAQ,QAAQ,IAAI,KAC3B,QAAQ,KAAK,WAAW,KACxB,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,GAC7B,OAAM,IAAI;AAAA,IACV;AAAA,EACF;AACA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,MACE,QAAQ,KAAK;AAAA,MACb,MAAM;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,YAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,mBAAe;AAAA,MACb,SAAS,iBAAiB,QAAQ;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AACA,uBAAmB;AAAA,MACjB,SAAS,iBAAiB,QAAQ;AAAA,IACpC;AACA,mBAAe,SAAS,iBAAiB,QAAQ,YAAY,SACzD,SACA;AAAA,MACE,SAAS,iBAAiB,QAAQ;AAAA,MAClC;AAAA,IACF;AAAA,EACN,QAAQ;AACN,UAAM,IAAI,mBAAmB,4CAA4C;AAAA,EAC3E;AACA,QAAM,iBAAiB,SAAS,iBAAiB,WAAW,cACxD,cACA,eACE,YACA;AACN,MACE,QAAQ,eAAe,SAAS,cAChC,QAAQ,SAAS,gBACjB,mBAAmB,QAAQ,QAAQ,MAAM,mBAAmB,gBAAgB,MAC3E,QAAQ,WAAW,WAAW,gBAAgB,SAC/C,QAAQ,WAAW,kBACnB,QAAQ,cAAc,SAAS,iBAAiB,aAChD,mBAAmB,QAAQ,QAAQ,MACjC,mBAAmB,SAAS,iBAAiB,QAAQ,KACvD,QAAQ,cAAc,SAAS,aAC/B,QAAQ,cAAc,SAAS,UAC/B,OAAM,IAAI;AAAA,IACV;AAAA,EACF;AACA,SAAO,EAAE,SAAS,SAAS,SAAS;AACtC;AAEA,eAAsB,mBACpB,KACA,MACqE;AACrE,QAAM,MAAM,GAAG,KAAK,EAAE;AACtB,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;AAAA,MACpB,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,WAAW,OAAO,SAAS,OAAO,KAAK,CAAC,GAAG,CAAC;AAGlD,MAAI,CAAC,WAAW,QAAQ,WAAW,WAAY,QAAO,CAAC;AACvD,MACE,QAAQ,WAAW,KAAK,MACxB,QAAQ,SAAS,gBACjB,CAAC,QAAQ,qBACT,CAAC,QAAQ,wBACT,CAAC,MAAM,QAAQ,QAAQ,IAAI,KAC3B,QAAQ,KAAK,WAAW,KACxB,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,GAC7B,OAAM,IAAI;AAAA,IACV;AAAA,EACF;AACA,uBAAqB,cAAc,QAAQ,OAAO;AAClD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,MAAM;AAAA,MACb;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,EAAE,QAAQ,KAAK,IAAI,MAAM,cAAc,SAAS,QAAQ,QAAQ;AAAA,IAClE;AAAA,EACF;AACF;AAEO,IAAM,eAAe,CAC1B,WACwB;AAAA,EACxB,IAAI,SAAS;AAAA,EACb,IAAI,MAAM;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,IACN,cAAc,MAAM;AAAA,IACpB,eAAe,MAAM;AAAA,IACrB,YAAY;AAAA,EACd;AACF;;;ACnKA,eAAsB,sBACpB,KACA,KACA,MACA,UACA,YACA,WACA,WACgC;AAChC,QAAM,eAAe,eAAe,eACjC,SAAS,SAAS,aAAa,SAAS,SAAS;AACpD,QAAM,aAAa,eAAe,MAAM,cAAc,KAAK,IAAI,IAAI,CAAC;AACpE,QAAM,UAAU,eAAe,cAAc,SAAS,SAAS,YAC3D,MAAM,mBAAmB,KAAK,IAAI,IAClC,CAAC;AACL,QAAM,mBAAyC,CAAC;AAChD,QAAM,SAAS,SAAS,WAAW;AACnC,MAAI;AACJ,MAAI,UAAU,eAAe,YAAY;AACvC,UAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,MAChC,CAAC,SAAS,KAAK,GAAG;AAAA,QAChB,GAAG,EAAE,OAAO,EAAE,IAAI,OAAO,SAAS,QAAQ,KAAK,GAAG,EAAE;AAAA,QACpD,MAAM,CAAC;AAAA,MACT;AAAA,IACF,CAAC;AACD,mBAAe,OAAO,SAAS,KAAK,KAAK,CAAC,GAAG,CAAC;AAG9C,QACE,CAAC,eACD,YAAY,OAAO,OAAO,WAC1B,YAAY,WAAW,KAAK,MAC5B,YAAY,WAAW,UACvB,YAAY,cAAc,UAC1B,YAAY,kBAAkB,OAAO,iBACrC,YAAY,SAAS,OAAO,cAC5B,YAAY,gBAAgB,OAAO,eAClC,MAAM,gBAAgB,EAAE,OAAO,IAAI,OAAO,MAAM,YAAY,KAAK,CAAC,MACjE,OAAO,cACT,YAAY,qBAAqB,OAAO,qBACvC,YAAY,kBAAkB,UAAU,OAAO,kBAChD,CAAC,MAAM,QAAQ,YAAY,IAAI,KAC/B,YAAY,KAAK,WAAW,KAC5B,YAAY,KAAK,CAAC,GAAG,OAAO,KAAK,GACjC,OAAM,IAAI;AAAA,MACV;AAAA,IACF;AACA,QAAI,CAAE,MAAM,IAAI,0BAA0B;AAAA,MACxC;AAAA,MACA,OAAO,IAAI;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,MAAM,YAAY;AAAA,MAClB,UAAU;AAAA,IACZ,CAAC,EAAI,OAAM,IAAI;AAAA,MACb;AAAA,IACF;AACA,qBAAiB,KAAK;AAAA,MACpB,IAAI,SAAS;AAAA,MACb,IAAI,YAAY;AAAA,MAChB,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,QAAQ;AAAA,QACR,MAAM,YAAY;AAAA,QAClB,iBAAiB,YAAY;AAAA,QAC7B,eAAe,OAAO;AAAA,QACtB,aAAa,OAAO;AAAA,QACpB,MAAM,OAAO;AAAA,QACb,kBAAkB,OAAO;AAAA,QACzB,GAAI,OAAO,iBAAiB,EAAE,gBAAgB,OAAO,eAAe,IAAI,CAAC;AAAA,MAC3E;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,WAAW,WAAW,WAAW,SAAS;AAC5C,qBAAiB,KAAK;AAAA,MACpB,IAAI,SAAS;AAAA,MACb,IAAI,WAAW,QAAQ;AAAA,MACvB,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,QAAQ;AAAA,QACR,MAAM,WAAW,QAAQ;AAAA,QACzB,UAAU,WAAW,QAAQ;AAAA,QAC7B,SAAS,WAAW,QAAQ,WAAW;AAAA,QACvC,QAAQ,WAAW,QAAQ;AAAA,QAC3B,WAAW,WAAW,QAAQ;AAAA,QAC9B,YAAY,WAAW,QAAQ;AAAA,QAC/B,mBAAmB,WAAW,QAAQ;AAAA,QACtC,sBAAsB,WAAW,QAAQ;AAAA,QACzC,UAAU,WAAW,QAAQ;AAAA,QAC7B,WAAW,WAAW,QAAQ;AAAA,QAC9B,WAAW,WAAW,QAAQ;AAAA,MAChC;AAAA,IACF,GAAG,aAAa,WAAW,OAAO,CAAC;AAAA,EACrC;AACA,MAAI,QAAQ,WAAW,QAAQ,SAAS;AACtC,qBAAiB,KAAK;AAAA,MACpB,IAAI,SAAS;AAAA,MACb,IAAI,QAAQ,QAAQ;AAAA,MACpB,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,KAAK,QAAQ,QAAQ;AAAA,QACrB,QAAQ,KAAK;AAAA,QACb,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS,QAAQ,QAAQ;AAAA,QACzB,mBAAmB,QAAQ,QAAQ;AAAA,QACnC,sBAAsB,QAAQ,QAAQ;AAAA,QACtC,WAAW,QAAQ,QAAQ;AAAA,MAC7B;AAAA,IACF,GAAG,aAAa,QAAQ,OAAO,CAAC;AAAA,EAClC;AAEA,MAAI,kBAAkD;AACtD,MAAI,gBAAgD;AACpD,MAAI,eAAe,cAAc,SAAS,SAAS,WAAW;AAC5D,QAAI,CAAC,UAAW,OAAM,IAAI,mBAAmB,sBAAsB;AACnE,oBAAgB;AAAA,MACd,IAAI;AAAA,MACJ,MAAM,UAAU,SAAS,QAAQ,MAAM,gBAAgB,GAAG;AAAA,MAC1D,UAAU,eAAe,SAAS,QAAQ,QAAQ;AAAA,MAClD,SAAS,SAAS,QAAQ,WAAW;AAAA,MACrC;AAAA,MACA,kBAAkB,WAAW,SAAS,MAAM;AAAA,IAC9C;AAAA,EACF,WAAW,eAAe,YAAY;AACpC,sBAAkB;AAAA,MAChB,SAAS;AAAA,MACT,SAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACA,QAAM,eAAe,eAAe,eAClC,SAAS,SAAS,aAAa,SAAS,SAAS,gBAC/C;AAAA,IACA,kBAAkB,SAAS,SAAS,YAChC,YACA,WAAW,SAAS,qBAAqB;AAAA,IAC7C,qBAAqB,SAAS,SAAS,YACnC,gBACA,WAAW,SAAS,wBAAwB;AAAA,IAChD,qBAAqB,SAAS,SAAS,eACnC,YACA,QAAQ,SAAS,qBAAqB;AAAA,IAC1C,wBAAwB,SAAS,SAAS,eACtC,gBACA,QAAQ,SAAS,wBAAwB;AAAA,EAC/C,IAAI;AACN,QAAM,mBAAmB;AAAA,IACvB,YAAY,SAAS;AAAA,IACrB;AAAA,IACA,iBAAiB,eAAe,aAAa,KAAK,UAAU,IAAI;AAAA,IAChE,wBACE,eAAe,aAAa,KAAK,qBAAqB,IAAI;AAAA,IAC5D,0BAA0B,SAAS,SAAS,aAAa,eAAe,aACpE,aAAa,OACb,KAAK,mBAAmB;AAAA,IAC5B,SAAS;AAAA,IACT,iBAAiB,kBACb,EAAE,MAAM,SAAS,MAAM,SAAS,iBAAiB,UAAU,IAC3D;AAAA,IACJ;AAAA,EACF;AACA,QAAM,UAAgC;AAAA,IACpC,SAAS;AAAA,IACT,aAAa,KAAK;AAAA,IAClB,oBAAoB,KAAK;AAAA,IACzB,iBAAiB,KAAK,mBAAmB;AAAA,IACzC,iBAAiB,MAAM,gBAAgB,KAAK,SAAS;AAAA,IACrD,qBAAqB,WAAW,UAC5B,MAAM,gBAAgB;AAAA,MACpB,IAAI,WAAW,QAAQ;AAAA,MACvB,UAAU,WAAW,QAAQ;AAAA,MAC7B,mBAAmB,WAAW,QAAQ;AAAA,MACtC,sBAAsB,WAAW,QAAQ;AAAA,IAC3C,CAAC,IACD;AAAA,IACJ,kBAAkB,QAAQ,UACtB,MAAM,gBAAgB;AAAA,MACpB,KAAK,QAAQ,QAAQ;AAAA,MACrB,SAAS,QAAQ,QAAQ;AAAA,MACzB,mBAAmB,QAAQ,QAAQ;AAAA,MACnC,sBAAsB,QAAQ,QAAQ;AAAA,IACxC,CAAC,IACD;AAAA,IACJ,mBAAmB,SACf,MAAM,gBAAgB,MAAM,IAC5B;AAAA,IACJ,cAAc,MAAM,gBAAgB,gBAAgB;AAAA,EACtD;AACA,SAAO;AAAA,IACL,GAAI,WAAW,UAAU,EAAE,cAAc,WAAW,QAAQ,IAAI,CAAC;AAAA,IACjE,GAAI,QAAQ,UAAU,EAAE,oBAAoB,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACjE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC1LA,IAAMC,UAAS,CAAC,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AACrE,IAAMC,eAAc,CAAC,MAAgB,UACnC,KAAK,WAAW,MAAM,UAAU,KAAK,MAAM,CAAC,OAAO,UAAU,UAAU,MAAM,KAAK,CAAC;AACrF,IAAMC,gBAAe,CAAC,UACpBF,QAAO,KAAK,KAAK,MAAM,SAAS;AAIlC,eAAsB,yBACpB,KACA,KACA,QACA,YACmB;AACnB,MAAI,IAAI,WAAW,OAAQ,QAAO,iBAAiB;AACnD,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,MAAM,EAAE;AAC9D,MAAI,IAAI,MAAM,SAAS;AACrB,UAAM,IAAI,oBAAoB,4DAA4D;AAE5F,QAAM,OAAO,MAAM,SAAS,GAAG;AAC/B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,+BAA+B,MAAM,QAAQ,UAAU;AAC3D,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,UAAU,MAAM,gBAAgB,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC;AAC/D,QAAM,YAAY,iBAAiB,OAAO,MAAM,GAAG,EAAE,CAAC;AACtD,QAAM,YAAY,eAAe,cAAc,SAAS,SAAS,YAC7D,iBAAiB,OAAO,MAAM,EAAE,CAAC,KACjC;AAIJ,QAAM,WAAW,MAAM,0BAA0B,KAAK,WAAW;AACjE,MAAI,UAAU;AACZ,QACE,CAAE,MAAM,2BAA2B,QAAQ,KAC3C,CAAC;AAAA,MACC;AAAA,MAAU;AAAA,MAAU;AAAA,MAAY;AAAA,MAAgB;AAAA,IAClD,EACA,OAAM,IAAI,mBAAmB,0CAA0C;AACzE,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MAAK;AAAA,MAAK;AAAA,MAAQ;AAAA,MAAY,SAAS;AAAA,MAAc;AAAA,IACvD;AACA,QACE,mBAAmB,QAAQ,MAC3B,mBAAmB,SAAS,oBAAoB,EAChD,OAAM,IAAI,mBAAmB,kCAAkC;AACjE,WAAO,KAAK,EAAE,SAAS,UAAU,WAAW,KAAK,CAAC;AAAA,EACpD;AAEA,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,QAAQ,GAAG;AAAA,MACnB,GAAG,EAAE,OAAO,EAAE,IAAI,YAAY,OAAO,EAAE;AAAA,MACvC,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AAGD,QAAM,WAAW,mBAAmB,OAAO,SAAS,QAAQ,KAAK,CAAC,GAAG,CAAC,CAAC;AAGvE,MACE,CAAC,YACD,SAAS,WAAW,KAAK,MACzB,CAAC,MAAM,QAAQ,SAAS,IAAI,KAC5B,SAAS,KAAK,WAAW,KACzB,SAAS,KAAK,CAAC,GAAG,OAAO,KAAK,GAC9B,OAAM,IAAI,mBAAmB,YAAY,UAAU,EAAE;AACvD,QAAM,UAAU,uBAAuB,QAAQ;AAC/C,QAAM,EAAE,cAAc,GAAG,eAAe,IAAI;AAC5C,MACG,MAAM,gBAAgB,cAAc,MAAO,gBAC5C,mBAAmB,OAAO,MAAM,mBAAmB,QAAQ,EAC3D,OAAM,IAAI,mBAAmB,+BAA+B;AAK9D,MAAI,eAAe,cAAc,CAACC,aAAY,QAAQ,UAAU,KAAK,SAAS;AAC5E,UAAM,IAAI,mBAAmB,oDAAoD;AAEnF,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAAU;AAAA,IAAY;AAAA,IAAW;AAAA,EACnD;AACA,QAAM,eAAe,MAAM,gBAAgB;AAAA,IACzC,SAAS;AAAA,IACT,kBAAkB;AAAA,IAClB;AAAA,IACA,gBAAgB,kBAAkB;AAAA,IAClC,WAAW,aAAa;AAAA,IACxB,iBAAiB,MAAM;AAAA,EACzB,CAAC;AACD,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAQ;AAAA,IAAY;AAAA,IAAc;AAAA,EAC9C;AACA,QAAM,cAAc;AAAA,IAClB,SAAS;AAAA,IACT,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,IAC3C,kBAAkB;AAAA,IAClB;AAAA,IACA,iBAAiB,MAAM;AAAA,IACvB,YAAY,IAAI,MAAM;AAAA,IACtB,gBAAgB;AAAA,IAChB,WAAW,IAAI,MAAM;AAAA,IACrB,eAAe;AAAA,IACf,cAAc,kBAAkB,SAAS;AAAA,IACzC,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,WAAW,UAAU;AAAA,EACvB;AACA,QAAME,WAAgC;AAAA,IACpC,GAAG;AAAA,IACH,eAAe,MAAM,gBAAgB,WAAW;AAAA,EAClD;AACA,QAAM,MAAM,MAAM,oBAAoB;AAAA,IACpC,UAAU,EAAE,GAAG,UAAU,UAAU,CAAC,GAAG,KAAK,SAAS,EAAE;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,MAAM,eAAe,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;AAAA,IACjE,GAAI,MAAM,qBACN,EAAE,oBAAoB,MAAM,mBAAmB,IAC/C,CAAC;AAAA,IACL,SAAS,IAAI,MAAM;AAAA,IACnB,KAAK,UAAU;AAAA,IACf;AAAA,EACF,CAAC;AACD,MAAI,KAAK;AAAA,IACP,GAAG;AAAA,IACH,IAAI,SAAS;AAAA,IACb,IAAIA,SAAQ;AAAA,IACZ,OAAOA;AAAA,EACT,GAAG;AAAA,IACD,GAAG;AAAA,IACH,IAAI,SAAS;AAAA,IACb,IAAIA,SAAQ;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,SAA+B;AAAA,IACnC;AAAA,MACE,IAAI,SAAS;AAAA,MACb,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,oBAAoB,OAAO;AAAA,IACrC;AAAA,IACA,EAAE,IAAI,SAAS,iBAAiB,IAAI,WAAW,QAAQ,MAAM;AAAA,IAC7D;AAAA,MACE,IAAI,SAAS;AAAA,MACb,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,SAAS,KAAK;AAAA,QACd,oBAAoB,KAAK;AAAA,QACzB,WAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,IACA,GAAG,MAAM;AAAA,EACX;AACA,MAAI,WAAW;AACb,WAAO,KAAK,EAAE,IAAI,SAAS,SAAS,IAAI,WAAW,QAAQ,MAAM,CAAC;AAAA,EACpE;AACA,MAAI;AACF,UAAM,KAAK,MAAM,IAAI,GAAG,SAAS,KAAK;AAAA,MACpC,YAAY;AAAA,MACZ;AAAA,MACA,QAAQ,IAAI,MAAM;AAAA,MAClB,GAAI,IAAI,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAM,MAAM,IAAI,CAAC;AAAA,MACtD,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,GAAG,WAAW;AAChB,YAAM,SAAS,MAAM,0BAA0B,KAAK,WAAW;AAC/D,UACE,CAAC,UACD,CAAE,MAAM,2BAA2B,MAAM,KACzC,CAAC;AAAA,QACC;AAAA,QAAQ;AAAA,QAAU;AAAA,QAAY;AAAA,QAAgB;AAAA,MAChD,KACA,mBAAmB,OAAO,oBAAoB,MAC5C,mBAAmB,SAAS;AAE9B,cAAM,IAAI,mBAAmB,qCAAqC;AACpE,aAAO,KAAK,EAAE,SAAS,QAAQ,WAAW,KAAK,CAAC;AAAA,IAClD;AACA,WAAO,KAAK,EAAE,SAAAA,UAAS,WAAW,MAAM,CAAC;AAAA,EAC3C,SAAS,OAAO;AACd,QAAID,cAAa,KAAK,EAAG,OAAM,IAAI,6BAA6B;AAChE,UAAM;AAAA,EACR;AACF;;;ACxOA,IAAME,UAAS,CAAC,UACd,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AACrE,IAAM,UAAU,CAAC,WAA0B;AACzC,QAAM,IAAI,mBAAmB,kCAAkC,MAAM,EAAE;AACzE;AAEA,eAAe,gBACb,IACA,QACA,WACA,cAC+B;AAC/B,QAAM,SAAS,MAAM,GAAG,MAAM;AAAA,IAC5B,CAAC,SAAS,eAAe,GAAG;AAAA,MAC1B,GAAG,EAAE,OAAO,EAAE,IAAI,WAAW,OAAO,EAAE;AAAA,MACtC,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAMC,YAAW,OAAO,SAAS,eAAe,KAAK,CAAC,GAAG,CAAC;AAG1D,MACE,CAACA,YACDA,SAAQ,eAAe,cACvBA,SAAQ,iBAAiB,gBACzB,CAAC,MAAM,QAAQA,SAAQ,IAAI,KAC3BA,SAAQ,KAAK,WAAW,KACxBA,SAAQ,KAAK,CAAC,GAAG,OAAO,OACxB,QAAO,QAAQ,MAAM;AACvB,QAAM,EAAE,MAAM,OAAO,GAAG,OAAO,IAAIA;AACnC,QAAM,aAAa,iBAAiB,MAAM;AAC1C,MAAI,CAAE,MAAM,2BAA2B,UAAU,EAAI,QAAO,QAAQ,MAAM;AAC1E,SAAO;AACT;AAEA,eAAe,cACb,IACA,MAC8B;AAC9B,QAAM,QAAQ,KAAK;AACnB,MACE,CAAC,SACD,CAACD,QAAO,MAAM,KAAK,KACnB,CAACA,QAAO,MAAM,IAAI,KAClB,CAAC,KAAK,mBACN,MAAM,cAAc,KAAK,mBACzB,CAAC,MAAM,oBACP,CAAC,MAAM,uBACP,CAAC,MAAM,aACP,QAAO,QAAQ,KAAK,EAAE;AACxB,QAAM,gBAAgB,MAAM,GAAG,MAAM;AAAA,IACnC,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,GAAG,EAAE,OAAO,EAAE,IAAI,MAAM,WAAW,QAAQ,KAAK,GAAG,EAAE;AAAA,MACrD,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,WAAW,cAAc,SAAS,OAAO,KAAK,CAAC,GAAG,CAAC;AAGzD,MACE,CAAC,WACD,QAAQ,WAAW,YACnB,QAAQ,sBAAsB,MAAM,oBACpC,QAAQ,yBAAyB,MAAM,uBACvC,CAAC,MAAM,QAAQ,QAAQ,IAAI,KAC3B,QAAQ,KAAK,WAAW,KACxB,QAAQ,KAAK,CAAC,GAAG,OAAO,KAAK,GAC7B,QAAO,QAAQ,KAAK,EAAE;AACxB,QAAM;AAAA,IACJ;AAAA,IAAI,KAAK;AAAA,IAAI,MAAM;AAAA,IAAkB,MAAM;AAAA,EAC7C;AAEA,QAAM,YAAY,MAAM,wBAAwB;AAChD,QAAM,gBAAgB,MAAM,2BAA2B;AACvD,MAAI,cAAc,cAAe,QAAO,QAAQ,KAAK,EAAE;AACvD,QAAM,gBAAgB,MAAM,GAAG,MAAM;AAAA,IACnC,CAAC,SAAS,OAAO,GAAG;AAAA,MAClB,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,cAAc,EAAE;AAAA,MAC7C,MAAM,CAAC;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,cAAc,cAAc,SAAS,OAAO,KAAK,CAAC,GAAG,CAAC;AAG5D,MAAI,WAAW;AACb,QACE,CAAC,cACD,WAAW,WAAW,KAAK,MAC3B,WAAW,SAAS,gBACpB,WAAW,WAAW,cACtB,WAAW,sBAAsB,MAAM,uBACvC,WAAW,yBAAyB,MAAM,0BAC1C,CAAC,MAAM,QAAQ,WAAW,IAAI,KAC9B,WAAW,KAAK,WAAW,KAC3B,WAAW,KAAK,CAAC,GAAG,OAAO,KAAK,GAChC,QAAO,QAAQ,KAAK,EAAE;AACxB,UAAM;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF,WACE,YAAY,WAAW,eACtB,WAAW,qBAAqB,WAAW,uBAC5C;AAEA,WAAO,QAAQ,KAAK,EAAE;AAAA,EACxB;AACA,QAAM,eAAe,MAAM,gBAAgB;AAAA,IACzC,WAAW,MAAM;AAAA,IACjB,kBAAkB,MAAM;AAAA,IACxB,qBAAqB,MAAM;AAAA,IAC3B,qBAAqB,MAAM,uBAAuB;AAAA,IAClD,wBAAwB,MAAM,0BAA0B;AAAA,EAC1D,CAAC;AACD,MAAI,iBAAiB,MAAM,aAAc,QAAO,QAAQ,KAAK,EAAE;AAC/D,SAAO;AACT;AAIA,eAAsB,aACpB,IACA,KACA,QACA,OACA,OACmB;AACnB,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,OAAO,UAAU,OACnB,MAAM,SAAS,IAAI,MAAM,IACzB,MAAM,eAAe,IAAI,QAAQ,MAAM,EAAE;AAC7C,QAAM,QAAQ,MAAM,cAAc,IAAI,IAAI;AAC1C,QAAM,QAAQ,MAAM;AACpB,QAAM,OAAO,MAAM;AACnB,MAAI,UAAU,cAAe,QAAO,KAAK,EAAE,OAAO,KAAK,CAAC;AACxD,QAAM,OAAO,iBAAiB,KAAK,kBAAkB,IAAI,MAAM,aAAa,MAAM,CAAC,CAAC;AACpF,MACE,IAAI,QAAQ,IAAI,eAAe,GAC3B,MAAM,GAAG,EACV,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,SAAS,IAAI,EAChB,QAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,KAAK,EAAE,CAAC;AAC9D,SAAO,IAAI,SAAS,gBAAgB,OAAO,EAAE,KAAK,CAAC,GAAG;AAAA,IACpD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AChKO,IAAM,6BAA6B;AAC1C,IAAM,mBAAmB;AACzB,IAAM,QAAQ,oBAAI,IAAI;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,OAAO,CAAC,WACX,OAAO,MAAM,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,KAAK,EAAE,YAAY;AAErD,IAAM,SAAS,CAAC,OAAmB,aACjC,SAAS,MAAM,CAAC,OAAO,UAAU,MAAM,KAAK,MAAM,KAAK;AAEzD,SAAS,aAAa,aAAqB,OAA4B;AACrE,MAAI,gBAAgB,aAAa;AAC/B,WAAO,OAAO,OAAO,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,EACvE;AACA,MAAI,gBAAgB,cAAc;AAChC,WAAO,OAAO,OAAO,CAAC,KAAM,KAAM,GAAI,CAAC;AAAA,EACzC;AACA,QAAM,SAAS,IAAI,YAAY,EAAE,OAAO,MAAM,SAAS,GAAG,EAAE,CAAC;AAC7D,MAAI,gBAAgB,aAAa;AAC/B,WAAO,OAAO,WAAW,QAAQ,KAAK,OAAO,WAAW,QAAQ;AAAA,EAClE;AACA,MAAI,gBAAgB,cAAc;AAChC,WAAO,OAAO,WAAW,MAAM,KAAK,OAAO,MAAM,GAAG,EAAE,MAAM;AAAA,EAC9D;AACA,SAAO,gBAAgB,qBAAqB,OAAO,WAAW,OAAO;AACvE;AAEA,eAAe,aACb,UACA,KAC4B;AAC5B,QAAM,SAAS,OAAO,SAAS,QAAQ,IAAI,gBAAgB,CAAC;AAC5D,MAAI,OAAO,SAAS,MAAM,KAAK,SAAS,IAAK,QAAO;AACpD,MAAI,CAAC,SAAS,KAAM,QAAO,IAAI,WAAW;AAC1C,QAAM,SAAS,SAAS,KAAK,UAAU;AACvC,QAAM,SAAuB,CAAC;AAC9B,MAAI,QAAQ;AACZ,SAAO,MAAM;AACX,UAAM,OAAO,MAAM,OAAO,KAAK;AAC/B,QAAI,KAAK,KAAM;AACf,aAAS,KAAK,MAAM;AACpB,QAAI,QAAQ,KAAK;AACf,YAAM,OAAO,OAAO;AACpB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AACA,QAAM,MAAM,IAAI,WAAW,KAAK;AAChC,MAAI,SAAS;AACb,aAAW,SAAS,QAAQ;AAC1B,QAAI,IAAI,OAAO,MAAM;AACrB,cAAU,MAAM;AAAA,EAClB;AACA,SAAO;AACT;AAEA,eAAe,OAAO,OAAoC;AACxD,QAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,WAAW,MAAM,MAAM,EAAE,MAAM;AACxE,SAAO,UAAU,CAAC,GAAG,IAAI,WAAW,KAAK,CAAC,EACvC,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAChD,KAAK,EAAE,CAAC;AACb;AAEA,SAAS,WACP,YACA,QACA,WACA,OACS;AACT,SAAO,UAAU,OAAO,WAAW,MACjC,MAAM,OAAO,OAAO,MACpB,MAAM,WAAW,OAAO,UACxB,MAAM,WAAW,UACjB,MAAM,SAAS,OAAO,QACtB,MAAM,oBAAoB,OAAO,mBACjC,MAAM,kBAAkB,OAAO,iBAC/B,MAAM,gBAAgB,OAAO,eAC7B,MAAM,SAAS,OAAO;AAC1B;AAEA,SAAS,cAAc,OAA2B;AAChD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,WAAO,MAAM,UAAU,QACnB,IAAI,aAAa,YACjB,CAAC,IAAI,YACL,CAAC,IAAI,WACL,MACA;AAAA,EACN,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,2BACpB,KACA,KACA,QACmB;AACnB,QAAM,aAAa,MAAM,eAAe,IAAI,IAAI,OAAO,QAAQ,IAAI,MAAM,EAAE;AAC3E,QAAM,SAAS,MAAM,YAAY,KAAK,YAAY,OAAO,UAAU;AACnE,QAAM,cAAc,KAAK,OAAO,WAAW;AAC3C,MAAI,CAAC,MAAM,IAAI,WAAW,GAAG;AAC3B,WAAO,KAAK,EAAE,OAAO,qCAAqC,GAAG,GAAG;AAAA,EAClE;AACA,MAAI,OAAO,OAAO,KAAK,OAAO,OAAO,4BAA4B;AAC/D,WAAO,KAAK,EAAE,OAAO,2CAA2C,GAAG,GAAG;AAAA,EACxE;AACA,QAAM,SAAS;AAAA,IACb,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,MAAM,gBAAgB;AAAA,EACzD;AACA,MAAI,CAAC,OAAQ,OAAM,IAAI,gBAAgB,8BAA8B;AAErE,QAAM,oBAAoB,IAAI;AAC9B,QAAM,WAAW,MAAM,kBAAkB,QAAQ;AAAA,IAC/C,SAAS,EAAE,QAAQ,YAAY;AAAA,IAC/B,UAAU;AAAA,IACV,QAAQ,IAAI;AAAA,EACd,CAAC;AACD,MAAI,CAAC,SAAS,MAAM,SAAS,SAAS,kBAAkB;AACtD,UAAM,IAAI,mBAAmB,SAAS,OAAO,EAAE,EAAE;AAAA,EACnD;AACA,QAAM,SAAS,KAAK,SAAS,QAAQ,IAAI,cAAc,CAAC;AACxD,MACE,WAAW,mBACV,UAAU,WAAW,8BAA8B,WAAW,aAC/D;AACA,WAAO,KAAK,EAAE,OAAO,qCAAqC,GAAG,GAAG;AAAA,EAClE;AACA,QAAM,QAAQ,MAAM,aAAa,UAAU,0BAA0B;AACrE,MACE,CAAC,SACD,MAAM,eAAe,OAAO,QAC5B,CAAC,aAAa,aAAa,KAAK,KAChC,MAAM,OAAO,KAAK,MAAM,OAAO,eAC/B;AACA,WAAO,KAAK,EAAE,OAAO,gCAAgC,GAAG,GAAG;AAAA,EAC7D;AACA,QAAM,YAAY,MAAM,eAAe,IAAI,IAAI,OAAO,QAAQ,IAAI,MAAM,EAAE;AAC1E,QAAM,QAAQ,MAAM,YAAY,KAAK,WAAW,OAAO,UAAU;AACjE,MAAI,CAAC,WAAW,YAAY,QAAQ,WAAW,KAAK,GAAG;AACrD,WAAO,KAAK,EAAE,OAAO,kCAAkC,GAAG,GAAG;AAAA,EAC/D;AACA,SAAO,KAAK;AAAA,IACV,OAAO;AAAA,MACL,WAAW,EAAE,MAAM,eAAe,IAAI,GAAG,OAAO,MAAM,IAAI,OAAO,EAAE,GAAG;AAAA,MACtE;AAAA,MACA,YAAY,MAAM;AAAA,MAClB,MAAM,OAAO,KAAK;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,EACF,GAAG,KAAK;AAAA,IACN,iBAAiB;AAAA,IACjB,0BAA0B;AAAA,EAC5B,CAAC;AACH;AAEA,SAAS,OAAO,OAA2B;AACzC,MAAI,SAAS;AACb,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,MAAQ;AACzD,cAAU,OAAO,aAAa,GAAG,MAAM,SAAS,OAAO,QAAQ,IAAM,CAAC;AAAA,EACxE;AACA,SAAO,KAAK,MAAM;AACpB;;;AChKA,IAAM,WAAW,CAAC,QAA+B;AAC/C,QAAM,SAAS,OAAO,OAAO,EAAE;AAC/B,SAAO,OAAO,UAAU,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,EAAE,CAAC,IAAI;AACxE;AAEA,IAAM,kBAAkB,CAAC,QAAoD;AAC3E,QAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,QAAM,KAAK,IAAI,aAAa,IAAI,IAAI;AACpC,MAAI,CAAC,QAAQ,CAAC,GAAI,QAAO;AACzB,MAAI,CAAC,QAAQ,CAAC,GAAI,QAAO;AACzB,QAAM,QAAQ,IAAI,IAAI,uBAAuB;AAC7C,QAAM,aAAa,IAAI,YAAY,GAAG,IAAI,IAAI,EAAE,EAAE;AAClD,SAAO,8BAA8B,KAAK;AAC5C;AAEA,IAAM,iBAAiB,CACrB,UACmB;AAAA,EACnB,eAAe,SAAS;AAAA,EACxB,iBAAiB,SAAS;AAAA,EAC1B,kBAAkB,SAAS;AAAA,EAC3B,iBAAiB,SAAS;AAC5B,GAA4D,IAAI,KAAK;AAErE,IAAM,cAAc,CAClB,MACA,SACoC;AAAA,EACpC;AAAA,EACA,QAAQ,IAAI;AAAA,EACZ,YAAY,IAAI;AAClB;AAEA,IAAM,aAAa,CACjB,KACA,KACA,MACA,QACA,QAC6B;AAC7B,MAAI,QAAQ,KAAK;AACjB,MAAI,OAAO,GAAG,KAAK,MAAM;AACzB,MAAI,UAAU,GAAG,KAAK,IAAI;AAC1B,MAAI,SAAiB,KAAK;AAC1B,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI,OAAO,SAAS,eAAe;AACjC,UAAM,QAAQ;AACd,YAAQ,MAAM,OAAO,KAAK,KAAK,GAAG,MAAM,IAAI;AAC5C,WAAO,GAAG,KAAK,IAAI,SAAM,MAAM,MAAM;AACrC,cAAU,GAAG,MAAM,IAAI,oBAAoB,KAAK,IAAI;AACpD,aAAS,MAAM;AACf,kBAAc;AAAA,EAChB,WAAW,OAAO,SAAS,iBAAiB;AAC1C,UAAM,UAAU;AAChB,eAAW,eAAe,QAAQ,QAAQ,EAAE,IAAI,CAAC,YAAY;AAAA,MAC3D,MAAM,OAAO;AAAA,MACb,KAAK,OAAO;AAAA,MACZ,GAAI,OAAO,OAAO,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,IAC7C,EAAE;AACF,YAAQ,QAAQ;AAChB,WAAO,GAAG,KAAK,IAAI,SAAM,QAAQ,MAAM;AACvC,cAAU,GAAG,QAAQ,SAAS,MAAM,qBAAqB,KAAK,IAAI;AAClE,aAAS,QAAQ;AACjB,kBAAc;AAAA,EAChB,WAAW,OAAO,SAAS,kBAAkB;AAC3C,UAAM,WAAW;AACjB,YAAQ,GAAG,SAAS,IAAI;AACxB,WAAO,GAAG,KAAK,IAAI,SAAM,SAAS,MAAM;AACxC,cAAU,SAAS;AACnB,aAAS,SAAS;AAClB,kBAAc;AAAA,EAChB,WAAW,OAAO,SAAS,iBAAiB;AAC1C,UAAME,WAAU;AAChB,YAAQ,GAAGA,SAAQ,UAAU,IAAIA,SAAQ,iBAAiB,IAAI;AAC9D,WAAO,GAAG,KAAK,IAAI;AACnB,cAAU,GAAGA,SAAQ,UAAU,IAAIA,SAAQ,iBAAiB,IAAI;AAChE,aAASA,SAAQ;AACjB,kBAAc;AAAA,EAChB;AACA,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,IAAI,2BAA2B,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,MACJ,IAAI,IAAI,IAAI,GAAG;AAAA,MACf;AAAA,MACA,IAAI;AAAA,IACN;AAAA,IACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,EACjC;AACF;AAEA,eAAe,MACb,KACA,KACA,QACqC;AACrC,QAAM,OAAO,MAAM,eAAe,IAAI,IAAI,OAAO,QAAQ,IAAI,MAAM,EAAE,EAClE,MAAM,MAAM,IAAI;AACnB,MAAI,CAAC,KAAM,QAAO,CAAC;AACnB,MAAI,OAAO,SAAS,cAAc;AAChC,WAAO,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ,IAAI,CAAC;AAAA,EAClD;AACA,QAAM,YAAY,eAAe,OAAO,IAAI;AAC5C,MAAI,CAAC,aAAa,CAAC,OAAO,WAAY,QAAO,CAAC;AAC9C,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,GAAG;AAAA,MACX,GAAG,EAAE,OAAO,EAAE,IAAI,OAAO,WAAW,GAAG,OAAO,EAAE;AAAA,IAClD;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,SAAS,KAAK,CAAC,GAAG,CAAC;AACvC,MACE,CAAC,OACD,IAAI,WAAW,KAAK,MACnB,OAAO,SAAS,iBAAkB,IAAmB,WAAW,OACjE,QAAO,CAAC;AACV,SAAO,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ,GAAG,CAAC;AACjD;AAEA,IAAM,UAAU,CACd,MACA,WACY,CAAC,UACb,GAAG,KAAK,KAAK;AAAA,EAAK,KAAK,IAAI;AAAA,EAAK,KAAK,EAAE,GAAG,YAAY,EAAE,SAAS,MAAM;AAEzE,eAAe,OACb,KACA,KACA,KACqC;AACrC,QAAM,SAAS,MAAM,IAAI,GAAG,MAAM;AAAA,IAChC,CAAC,SAAS,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,IACnE,CAAC,SAAS,KAAK,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,IACpE,CAAC,SAAS,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,IACtE,CAAC,SAAS,QAAQ,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAI,EAAE;AAAA,IACvE,CAAC,SAAS,eAAe,GAAG;AAAA,MAC1B,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAI;AAAA,IAChD;AAAA,EACF,CAAC;AACD,QAAM,SAAU,OAAO,SAAS,IAAI,KAAK,CAAC,GACvC,OAAO,CAAC,SAAS,SAAS,MAAM,IAAI,MAAM,EAAE,CAAC;AAChD,QAAM,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC7D,QAAM,QAAQ,MAAM;AAAA,IAAI,CAAC,SACvB,WAAW,KAAK,KAAK,MAAM,EAAE,MAAM,cAAc,QAAQ,KAAK,GAAG,GAAG,IAAI;AAAA,EAC1E;AACA,QAAM,SAAS,CACb,MACA,SACG;AACH,eAAW,OAAO,MAAiB;AACjC,YAAM,OAAO,SAAS,IAAI,IAAI,MAAM;AACpC,UACE,CAAC,QACA,SAAS,iBAAkB,IAAmB,WAAW,OAC1D;AACF,YAAM,KAAK,WAAW,KAAK,KAAK,MAAM,YAAY,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,IACpE;AAAA,EACF;AACA,SAAO,eAAe,OAAO,SAAS,KAAK,KAAK,CAAC,CAAC;AAClD,SAAO,iBAAiB,OAAO,SAAS,OAAO,KAAK,CAAC,CAAC;AACtD,SAAO,kBAAkB,OAAO,SAAS,QAAQ,KAAK,CAAC,CAAC;AACxD,SAAO,iBAAiB,OAAO,SAAS,eAAe,KAAK,CAAC,CAAC;AAC9D,QAAM,UAAU,IAAI,aAAa,IAAI,GAAG,KAAK,IAAI,KAAK,EAAE,YAAY,EACjE,MAAM,GAAG,GAAG;AACf,SAAO,MAAM,OAAO,CAAC,SAAS,QAAQ,MAAM,MAAM,CAAC,EAChD,MAAM,GAAG,SAAS,IAAI,aAAa,IAAI,OAAO,CAAC,CAAC;AACrD;AAMA,eAAsB,gCACpB,KACA,KACA,KACmB;AACnB,MAAI,IAAI,WAAW,MAAO,QAAO,iBAAiB;AAClD,QAAM,UAAU,IAAI,aAAa,IAAI,SAAS;AAC9C,QAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,QAAM,KAAK,IAAI,aAAa,IAAI,IAAI;AACpC,MAAK,QAAQ,CAAC,MAAQ,CAAC,QAAQ,GAAK,QAAO,KAAK,EAAE,OAAO,6BAA6B,GAAG,GAAG;AAC5F,QAAM,SAAS,gBAAgB,GAAG;AAClC,OAAK,QAAQ,OAAO,CAAC,OAAQ,QAAO,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;AACtD,MAAI,YAAY,iBAAiB;AAC/B,UAAM,UAAU,oBAAI,IAAI,CAAC,WAAW,QAAQ,IAAI,CAAC;AACjD,QACE,CAAC,GAAG,IAAI,aAAa,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC,KAC5D,QAAQ,SAAS,iBACjB,CAAC,OAAO,WACR,QAAO,KAAK,EAAE,OAAO,yCAAyC,GAAG,GAAG;AACtE,WAAO,2BAA2B,KAAK,KAAK;AAAA,MAC1C,QAAQ,OAAO;AAAA,MACf,YAAY,OAAO;AAAA,IACrB,CAAC;AAAA,EACH;AACA,MAAI,YAAY,QAAQ,YAAY,KAAK;AACvC,WAAO,KAAK,EAAE,OAAO,0BAA0B,GAAG,GAAG;AAAA,EACvD;AACA,SAAO,KAAK;AAAA,IACV,OAAO,SAAS,MAAM,MAAM,KAAK,KAAK,MAAM,IAAI,MAAM,OAAO,KAAK,KAAK,GAAG;AAAA,EAC5E,CAAC;AACH;;;ACnNA,IAAM,aAAa,CAAC,QAClB,IAAI,WAAW,KAAK,IAAI,CAAC,MAAM,YAAY,IAAI,CAAC,MAAM,gBAAgB,IAAI,CAAC,MAAM,iBAC5E,IAAI,CAAC,IACN;AAEN,eAAe,MACb,KACA,KACA,KACA,KAC0B;AAC1B,QAAM,CAAC,MAAM,IAAI,KAAK,OAAO,MAAM,IAAI;AACvC,MAAI,SAAS,2BAA2B,IAAI,WAAW;AACrD,WAAO,gCAAgC,KAAK,KAAK,GAAG;AACtD,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,IAAI,WAAW,EAAG,QAAO,gBAAgB,KAAK,GAAG;AACrD,MAAI,IAAI,WAAW,EAAG,QAAO,eAAe,KAAK,KAAK,EAAG;AACzD,MAAI,IAAI,WAAW,KAAK,QAAQ,UAAW,QAAO,kBAAkB,KAAK,KAAK,EAAG;AACjF,MAAI,QAAQ,UAAU;AACpB,QAAI,IAAI,WAAW,EAAG,QAAO,iBAAiB,KAAK,KAAK,EAAG;AAC3D,QAAI,IAAI,WAAW,EAAG,QAAO,gBAAgB,KAAK,KAAK,IAAK,KAAM;AAClE,QAAI,IAAI,WAAW,KAAK,WAAW;AACjC,aAAO,mBAAmB,KAAK,KAAK,IAAK,KAAM;AACjD,QAAI,IAAI,WAAW,KAAK,WAAW;AACjC,aAAO,oBAAoB,KAAK,KAAK,IAAK,KAAM;AAClD,QAAI,IAAI,WAAW,KAAK,WAAW;AACjC,aAAO,mBAAmB,KAAK,KAAK,IAAK,KAAM;AACjD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,eAAe,IAAI,WAAW,KAAK,WAAW;AACxD,WAAO,yBAAyB,KAAK,KAAK,IAAK,KAAM;AACvD,QAAM,OAAO,WAAW,GAAG;AAC3B,MAAI,KAAM,QAAO,aAAa,IAAI,IAAI,KAAK,IAAK,MAAM,IAAI,KAAK;AAC/D,SAAO;AACT;AAUO,SAAS,kBAAkB,SAAqE;AACrG,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,eAAe,QAAQ,iBAAiB;AAC9C,QAAM,OAAO;AAAA,IACX,IAAI,QAAQ;AAAA,IACZ,OAAO,QAAQ;AAAA,IACf,qBAAqB,QAAQ;AAAA,IAC7B,mBAAmB,QAAQ;AAAA,IAC3B,2BAA2B,QAAQ;AAAA,IACnC,KAAK,QAAQ,OAAO,KAAK;AAAA,IACzB,OAAO,QAAQ,UAAU,MAAM,OAAO,WAAW;AAAA,IACjD,gBAAgB,QAAQ,kBAAkB,IAAI,OAAO;AAAA,IACrD,oBAAoB,QAAQ,sBAAsB;AAAA;AAAA;AAAA;AAAA,IAIlD,mBAAmB,QAAQ,qBACzB,WAAW,MAAM,KAAK,UAAU;AAAA,IAClC,uBAAuB,QAAQ,yBAAyB,CAAC,QAAQ;AAAA,EACnE;AACA,SAAO,OAAO,QAA2C;AACvD,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAI,IAAI,aAAa,YAAY,CAAC,IAAI,SAAS,WAAW,GAAG,QAAQ,GAAG,EAAG,QAAO;AAClF,UAAM,MAAM,IAAI,SAAS,MAAM,SAAS,MAAM,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO;AACzE,QAAI;AACF,YAAM,OAAO,WAAW,GAAG;AAC3B,UAAI,gBAAgB,KAAM,QAAO,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI,CAAC,GAAI,MAAM,IAAI;AACrF,YAAM,QAAQ,OACZ,IAAI,CAAC,MAAM,0BACP,QAAQ,iCAAiC,QAAQ,YACjD,QAAQ,WACZ,GAAG;AACL,UAAI,CAAC,MAAO,QAAO,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AACtD,aAAQ,MAAM,MAAM,EAAE,GAAG,MAAM,MAAM,GAAG,KAAK,KAAK,GAAG,KACnD,KAAK,EAAE,OAAO,YAAY,GAAG,GAAG;AAAA,IACpC,SAAS,OAAO;AACd,aAAO,cAAc,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;;;ACnGA,IAAM,qBAAqB;AAE3B,SAAS,kBAAkB,KAAwC;AACjE,QAAM,WAAW,MAAM,QAAQ,IAAI,WAAW,IAC1C,IAAI,YAAY,QAAQ,CAAC,UAAU;AACjC,QAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK;AAC5D,aAAO,CAAC;AACV,UAAM,KAAM,MAAkC;AAC9C,WAAO,OAAO,OAAO,YAAY,GAAG,SAAS,KAAK,GAAG,UAAU,MAC3D,CAAC,EAAE,IACH,CAAC;AAAA,EACP,CAAC,IACD,CAAC;AAGL,QAAM,SAAS,MAAM,QAAQ,IAAI,QAAQ,IACrC,IAAI,SAAS,OAAO,CAAC,UACnB,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,UAAU,GAAG,IACtE,CAAC;AACL,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,kBAAkB;AAC3E;AAGA,eAAsB,sBACpB,IACA,MACA,KACmB;AACnB,QAAM,aAAa,kBAAkB,GAAG;AACxC,QAAM,SAAS,MAAM,QAAQ,IAAI,WAAW,IAAI,OAAO,OAAO;AAC5D,UAAM,SAAS,MAAM,GAAG,MAAM;AAAA,MAC5B,CAAC,SAAS,KAAK,GAAG;AAAA,QAChB,GAAG,EAAE,OAAO,EAAE,IAAI,QAAQ,KAAK,IAAI,QAAQ,OAAO,GAAG,OAAO,EAAE;AAAA,QAC9D,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,UAAM,OAAO,OAAO,SAAS,KAAK,KAAK,CAAC;AACxC,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,UAAM,QAAQ,KAAK,CAAC;AACpB,WAAO,MAAM,OAAO,MAClB,MAAM,WAAW,KAAK,MACtB,MAAM,WAAW,UACjB,MAAM,cAAc,UACpB,MAAM,QAAQ,MAAM,IAAI,KACxB,MAAM,KAAK,WAAW,KACtB,MAAM,KAAK,CAAC,GAAG,OAAO,KAAK,KACzB,KACA;AAAA,EACN,CAAC,CAAC;AACF,SAAO,OAAO,OAAO,CAAC,OAAqB,OAAO,IAAI;AACxD;;;ACzCO,IAAM,kBAAkB;AAqC/B,IAAM,YAAY,CAAC,UAA0B,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AAQtF,SAAS,gBAAgB,MAAyC;AACvE,QAAM,UAAU,CAAC,4BAA4B;AAC7C,MAAI,KAAK,QAAS,SAAQ,KAAK,uBAAuB,UAAU,KAAK,OAAO,CAAC,IAAI;AAEjF,MAAI,KAAK,KAAM,SAAQ,KAAK,IAAI,KAAK,IAAI,GAAG;AAC5C,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,OAAO,EAAE,IAAI,iBAAiB,IAAI,KAAK,MAAM,SAAS;AAAA,IACtD,MAAM,QAAQ,KAAK,MAAM;AAAA,IACzB,OAAO,EAAE,SAAS,KAAK,SAAS,SAAS,KAAK,QAAQ;AAAA,IACtD,OAAO;AAAA,IACP,UAAU;AAAA,IACV,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;AAAA,EACrD;AACF;;;AClDO,SAAS,mBAAmB,KAAwC;AACzE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,OAAO;AACb,QAAM,UAAU,KAAK;AAMrB,QAAM,QAAQ,KAAK;AAKnB,MACE,KAAK,MAAM,KACX,OAAO,KAAK,UAAU,YACtB,CAAC,KAAK,SACN,OAAO,KAAK,mBAAmB,YAC/B,CAAC,iBAAiB,KAAK,KAAK,cAAc,KAC1C,OAAO,KAAK,UAAU,YACtB,CAAC,KAAK,SACN,CAAC,WACD,OAAO,QAAQ,OAAO,YAAY,YAClC,CAAC,QAAQ,MAAM,WACf,OAAO,QAAQ,MAAM,YAAY,YACjC,CAAC,SACD,OAAO,MAAM,OAAO,YACpB,CAAC,MAAM,OACP,OAAO,MAAM,QAAQ,YACrB,MAAM,QAAQ,MAAM,GAAG,EACvB,QAAO;AACT,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,KAAK;AAAA,IACZ,gBAAgB,KAAK;AAAA,IACrB,OAAO,KAAK;AAAA,IACZ,SAAS;AAAA,MACP,IAAI,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK;AAAA,MAClD,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAC3D,OAAO;AAAA,QACL,SAAS,QAAQ,MAAM;AAAA,QACvB,SAAS,QAAQ,MAAM;AAAA,MACzB;AAAA,MACA,GAAI,OAAO,QAAQ,aAAa,WAC5B,EAAE,UAAU,QAAQ,SAAS,IAC7B,CAAC;AAAA,IACP;AAAA,IACA,OAAO;AAAA,MACL,IAAI,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK;AAAA,MAC9C,IAAI,MAAM;AAAA,MACV,KAAK,MAAM;AAAA,IACb;AAAA,EACF;AACF;AAIA,eAAsB,eACpB,IACA,WAC2B;AAC3B,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS,MAAM,GAAG,MAAM;AAAA,IAC5B,CAAC,SAAS,IAAI,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE;AAAA,EACjD,CAAC;AACD,QAAM,QAAS,OAAO,SAAS,IAAI,KAAK,CAAC;AACzC,MAAI,MAAM,SAAS;AACjB,UAAM,IAAI,mBAAmB,sCAAsC,SAAS,EAAE;AAChF,SAAO,MAAM,CAAC,KAAK;AACrB;AAIO,SAAS,cACd,MACA,aACA,QACA,mBAAsC,CAAC,GACR;AAC/B,QAAM,MAAM,KAAK,MAAM;AACvB,QAAM,QAAQ,SACV,GAAG,OAAO,WAAW,KAAK,OAAO,IAAI,GAClC,OAAO,qBACN,gBAAgB,OAAO,kBAAkB,KACzC,EAAE,MACN,IAAI,eAAe,QACjB,oBACA;AACN,QAAM,SACJ,2DACG,KAAK,MACJ,OAAO,IAAI,QAAQ,EAAE,CAAC,wQAIzB,iBAAiB,SAAS,IACvB,kDAAkD,iBAAiB,WAAW,IAAI,KAAK,GAAG,IACvF,iBAAiB,KAAK,IAAI,CAAC,qEAC9B,MACJ;AACF,SAAO,aAAa,SAChB,CAAC,GAAG,aAAa,EAAE,MAAM,QAAQ,MAAM,OAAO,CAAC,IAC/C;AACN;AAIA,eAAsB,kBACpB,MACA,MACyD;AACzD,MACE,KAAK,UAAU,KAAK,SACpB,KAAK,QAAQ,UAAU,WACvB,KAAK,MAAM,OAAO,gBAClB,OAAM,IAAI,oBAAoB,+BAA+B;AAC/D,QAAM,YAAY,OAAO,KAAK,MAAM,IAAI,aAAa,EAAE;AACvD,QAAM,OAAO,MAAM,eAAe,KAAK,IAAI,SAAS;AACpD,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR,0BAA0B,aAAa,qBAAqB;AAAA,IAC9D;AACF,QAAM,UAAU,KAAK,QAAQ,MAAM;AACnC,MAAI,CAAC,KAAK,UAAU,SAAS,OAAO;AAClC,UAAM,IAAI,mBAAmB,0BAA0B,SAAS,EAAE;AACpE,QAAM,OAAO,MAAM,KAAK,oBAAoB;AAAA,IAC1C;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,YAAY;AAAA,EACd,CAAC;AACD,MAAI,CAAC,QAAQ,KAAK,eAAe,gBAAgB,CAAC,KAAK;AACrD,UAAM,IAAI,oBAAoB,6BAA6B;AAC7D,QAAM,WACJ,OAAO,KAAK,MAAM,IAAI,aAAa,WAC/B,KAAK,MAAM,IAAI,WACf;AACN,QAAM,UAAU,WACZ,MAAM,KAAK,kBAAkB;AAAA,IAC3B,kBAAkB;AAAA,IAClB,QAAQ,KAAK;AAAA,IACb,cAAc,CAAC,QAAQ;AAAA,EACzB,CAAC,IACD,CAAC;AACL,QAAM,SAAS,QAAQ,KAAK,CAAC,cAAc,UAAU,OAAO,QAAQ;AACpE,QAAM,mBAAmB,MAAM;AAAA,IAC7B,KAAK;AAAA,IACL;AAAA,IACA,KAAK,MAAM;AAAA,EACb;AACA,QAAM,UAAU,MAAM,KAAK,gBAAgB;AAAA,IACzC,OAAO,KAAK;AAAA,IACZ;AAAA,IACA,QAAQ,KAAK;AAAA,IACb,WAAW,KAAK,QAAQ;AAAA,IACxB,SAAS,KAAK,MAAM;AAAA,IACpB,OAAO,KAAK;AAAA,EACd,CAAC;AACD,MACE,CAAC,QAAQ,iBACT,CAAC,QAAQ,SACT,QAAQ,UAAU,KAAK;AAEvB,UAAM,IAAI,oBAAoB,oCAAoC;AACpE,MAAI,iBAAiB;AACrB,QAAM,SAAS;AAAA,IACb,GAAG,QAAQ;AAAA,IACX,gBAAgB,OACd,UACG;AACH,YAAM,WAAW,MAAM,QAAQ,OAAO,eAAe,KAAK;AAC1D,uBAAiB;AACjB,aAAO;AAAA,IACT;AAAA,IACA,qBAAqB,OACnB,UACG;AACH,YAAM,QAAQ,MAAM,QAAQ,OAAO,oBAAoB,KAAK;AAC5D,uBAAiB;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,sBAAsB;AAAA,IAC1B,KAAK,UAAU,KAAK,KAAK;AAAA,EAC3B;AACA,QAAM,OAAuB;AAAA,IAC3B,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,aAAa,KAAK,QAAQ,MAAM;AAAA,EAClC;AACA,QAAM,UAAU,mBAAmB;AAAA,IACjC,OAAO,KAAK;AAAA,IACZ,OAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,gBAAgB;AAAA,QACd,aAAa;AAAA,QACb,eAAe,QAAQ;AAAA,MACzB;AAAA,MACA,YAAY,QAAQ;AAAA,MACpB,aAAa;AAAA,MACb,qBAAqB,KAAK;AAAA,MAC1B,mBAAmB,KAAK;AAAA,MACxB;AAAA,MACA,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IAC5C;AAAA,IACA,QAAQ,KAAK,eACT,CAAC,KAAK,aAAa,WAAW,IAAI,CAAC,IACnC,CAAC;AAAA,EACP,CAAC;AACD,QAAM,MAAM,MAAM,KAAK,SAAS,KAAK,WAAW,SAAS;AAAA;AAAA,IAEvD,OAAO,cAAc,MAAM,QAAW,QAAQ,gBAAgB;AAAA,EAChE,CAAC;AACD,SAAO,EAAE,WAAW,IAAI,WAAW,eAAe;AACpD;;;ACpKO,IAAM,mBAA+C;AAAA,EAC1D,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,IACR;AAAA,MACE,KAAK;AAAA,MACL,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,IACA;AAAA,MACE,KAAK;AAAA,MACL,aACE;AAAA,MAEF,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EACA,SAAS,CAAC;AAAA,EACV,QAAQ;AAAA,EACR,OAAO,WAAW;AAAA,EAClB,UAAU,CAAC;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,IACT,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAoBO,SAAS,uBACd,UAAyC,CAAC,GACd;AAC5B,QAAM,WAAW,QAAQ,YAAY;AACrC,MAAI,CAAC,sCAAsC,KAAK,QAAQ,KAAK,SAAS,SAAS,GAAG,GAAG;AACnF,UAAM,IAAI,MAAM,oFAAoF;AAAA,EACtG;AACA,QAAM,MAAM,CAAC,GAAG,iBAAiB,UAAU,GAAG;AAC9C,MAAI,QAAQ,YAAY;AACtB,QAAI,KAAK,+DAA+D,KAAK,UAAU,QAAQ,OAAO,CAAC,WAAW;AACpH,MAAI,QAAQ,iBAAiB;AAC3B,QAAI,KAAK,sDAAsD,QAAQ,+CAA+C;AACxH,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,EAAE,GAAG,iBAAiB,WAAW,IAAI;AAAA,IAChD,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,UAAU,gBAAgB,IAAI,CAAC;AAAA,EAC7D;AACF;","names":["record","record","receipt","isRecord","HEX_ALPHA","a","value","toHex","a","missing","isRecord","from","end","a","a","HEX6","a","isRecord","digest","missing","a","record","record","ops","digest","receipt","record","sameStrings","guardFailure","receipt","record","receipt","receipt"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/agent-profile.ts","../src/errors.ts","../src/schema.ts","../src/read-shape.ts","../src/deps.ts","../src/rules.ts","../src/validate.ts","../src/review-json.ts","../src/review.ts","../src/discussion-reference.ts","../src/ops/books.ts","../src/ops/sections.ts","../src/ops/palettes.ts","../src/ops/assets.ts","../src/design/bundle.ts","../src/design/css-scan.ts","../src/color/hex.ts","../src/color/convert.ts","../src/color/contrast.ts","../src/color/harmony.ts","../src/color/ramp.ts","../src/color/delta.ts","../src/color/names.ts","../src/color/palette.ts","../src/tokens/map.ts","../src/design/decompile.ts","../src/design/html-text.ts","../src/design/outline.ts","../src/design/props.ts","../src/design/styles.ts","../src/design/tokens.ts","../src/design/digest.ts","../src/palette-report.ts","../src/tokens/roles.ts","../src/tokens/dark.ts","../src/tokens/css.ts","../src/tokens/compile.ts","../src/skill/asset-tools.ts","../src/skill/source-asset.ts","../src/skill/book-tools.ts","../src/skill/palette-tools.ts","../src/skill/design-tools.ts","../src/skill/read-tools.ts","../src/skill/skill.ts","../src/skill/persona.ts","../src/routes/asset-query.ts","../src/routes/http.ts","../src/routes/asset-upload.ts","../src/routes/assets.ts","../src/routes/books.ts","../src/routes/design-preview.ts","../src/routes/proposal-input.ts","../src/routes/proposal-effects.ts","../src/routes/proposal-resolution-receipts.ts","../src/routes/proposal-dependencies.ts","../src/routes/proposal-state.ts","../src/routes/proposals.ts","../src/routes/tokens.ts","../src/routes/discussion-asset.ts","../src/routes/discussion-references.ts","../src/routes/index.ts","../src/dispatch-assets.ts","../src/triggers.ts","../src/dispatch.ts","../src/descriptor.ts"],"sourcesContent":["// @odla-ai/brand — conversational brand-book builder on odla-db.\n//\n// Pure re-export barrel; the public surface groups as:\n// data model — constants, types, schema, rules, errors, deps, validate\n// ops — pure odla-db op builders shared by routes and skill\n// color engine — zero-dep OKLCH/WCAG math (hex, convert, contrast, harmony,\n// ramp, delta, names, derivePalette)\n// tokens — brand book → --ui-* design tokens + theme CSS\n// skill — the @odla-ai/ai agent skill, persona factory, vision gate\n// worker — route factory, chat-trigger dispatch, integration descriptor\nexport * from \"./constants\";\nexport * from \"./types\";\nexport * from \"./agent-profile\";\nexport * from \"./errors\";\nexport * from \"./deps\";\nexport * from \"./schema\";\nexport * from \"./rules\";\nexport * from \"./validate\";\nexport * from \"./review\";\nexport * from \"./discussion-reference\";\nexport * from \"./ops/index\";\nexport * from \"./design/index\";\nexport * from \"./palette-report\";\nexport * from \"./color/index\";\nexport * from \"./tokens/index\";\nexport * from \"./skill/index\";\nexport * from \"./routes/index\";\nexport * from \"./dispatch\";\nexport * from \"./triggers\";\nexport * from \"./descriptor\";\n","// Namespaces + closed vocabularies for @odla-ai/brand. One brand book is a\n// row-tree across six namespaces: the book (auth roster + compiled tokens),\n// its sections (one per kind, natural-keyed `${bookId}:${kind}`), palettes\n// (the atomic proposal/approval unit), proposals (human-gated agent output),\n// assets (worker-mediated uploads mirroring real R2 objects), and immutable\n// approval receipts recording the exact human-reviewed action.\n\n/** The odla-db namespaces @odla-ai/brand installs and writes. */\nexport const BRAND_NS = {\n book: \"brand_book\",\n section: \"brand_section\",\n palette: \"brand_palette\",\n proposal: \"brand_proposal\",\n approvalReceipt: \"brand_approval_receipt\",\n asset: \"brand_asset\",\n} as const;\n\n/** Brand-book lifecycle: authored → adopted → retired (delete is owner-only). */\nexport const BOOK_STATUSES = [\"draft\", \"active\", \"archived\"] as const;\n/** Where a brand book stands in its lifecycle. */\nexport type BookStatus = (typeof BOOK_STATUSES)[number];\n\n/** The section kinds a book carries — one row per kind, upserted by natural key. */\nexport const SECTION_KINDS = [\"palette\", \"typography\", \"voice\", \"logo\", \"imagery\"] as const;\n/** Which facet of the brand a section documents. */\nexport type SectionKind = (typeof SECTION_KINDS)[number];\n\n/** Section review state: agent drafts, a human approves. */\nexport const SECTION_STATUSES = [\"draft\", \"approved\"] as const;\n/** Whether a section's content has human sign-off. */\nexport type SectionStatus = (typeof SECTION_STATUSES)[number];\n\n/** Palette lifecycle — palettes are never row-deleted, only archived. */\nexport const PALETTE_STATUSES = [\"active\", \"archived\"] as const;\n/** Whether a palette is the live one or a retired predecessor. */\nexport type PaletteStatus = (typeof PALETTE_STATUSES)[number];\n\n/** How a palette came to be: pulled from an asset, derived from a seed color,\n * or entered by hand. */\nexport const PALETTE_SOURCES = [\"extracted\", \"derived\", \"manual\"] as const;\n/** Provenance of a palette's swatches. */\nexport type PaletteSource = (typeof PALETTE_SOURCES)[number];\n\n/** Every mutable brand facet uses the same proposal/approval contract. */\nexport const PROPOSAL_KINDS = SECTION_KINDS;\n/** Which brand facet a proposal targets. */\nexport type ProposalKind = (typeof PROPOSAL_KINDS)[number];\n\n/** Proposal lifecycle: open until a HUMAN accepts/rejects it (or a newer\n * proposal supersedes it) — agents never resolve their own proposals. */\nexport const PROPOSAL_STATUSES = [\"open\", \"accepted\", \"rejected\", \"superseded\"] as const;\n/** Where a proposal stands in the human-gated review flow. */\nexport type ProposalStatus = (typeof PROPOSAL_STATUSES)[number];\n\n/** What kind of upload an asset row records. `design` is the one kind whose\n * bytes are HTML — a Claude Design standalone export — and the only kind the\n * preview route will ever serve as a document; see `design/` and\n * `routes/design-preview.ts`. */\nexport const ASSET_KINDS = [\n \"logo\",\n \"wordmark\",\n \"inspiration\",\n \"document\",\n \"design\",\n \"other\",\n] as const;\n/** The declared purpose of an uploaded asset. */\nexport type AssetKind = (typeof ASSET_KINDS)[number];\n\n/** The asset kind carrying a Claude Design bundle. Its content type, digest,\n * preview route, and agent tools are all keyed off this one value. */\nexport const DESIGN_ASSET_KIND = \"design\";\n\n/** Every swatch role a palette may assign. `chart` may repeat (a series);\n * `custom` is the escape hatch for roles the token compiler doesn't map. */\nexport const SWATCH_ROLES = [\n \"primary\",\n \"secondary\",\n \"highlight\",\n \"bg\",\n \"surface\",\n \"text\",\n \"neutral\",\n \"good\",\n \"warn\",\n \"danger\",\n \"chart\",\n \"custom\",\n] as const;\n","/** Canonical least-privilege runtime profile for a Brand collaborator agent. */\nexport interface BrandAgentProfile {\n version: 1;\n projectCapabilities: readonly [\"brand.read\", \"brand.edit\"];\n semanticOperations: readonly [\n \"brand.proposal.create\",\n \"brand.asset.analysis.record\",\n \"brand.asset.content.read\",\n ];\n rawBrandWrites: false;\n rawFileOperations: false;\n approval: {\n principalKind: \"human\";\n projectCapability: \"brand.approve\";\n capability: \"brand.proposal.resolve\";\n exactAction: true;\n };\n}\n\n/** Install-time contract: agents use semantic Brand operations; only a direct\n * human may consume exact approval authority for a reviewed proposal. */\nexport const BRAND_AGENT_PROFILE: BrandAgentProfile = {\n version: 1,\n projectCapabilities: [\"brand.read\", \"brand.edit\"],\n semanticOperations: [\n \"brand.proposal.create\",\n \"brand.asset.analysis.record\",\n \"brand.asset.content.read\",\n ],\n rawBrandWrites: false,\n rawFileOperations: false,\n approval: {\n principalKind: \"human\",\n projectCapability: \"brand.approve\",\n capability: \"brand.proposal.resolve\",\n exactAction: true,\n },\n};\n","/** Caller-fault error (bad hex, oversized payload, blocked transition…) — the\n * route layer maps it to a 400. `fields` carries per-field messages when the\n * failure came from input validation. */\nexport class BrandInputError extends Error {\n readonly fields?: Record<string, string>;\n constructor(message: string, fields?: Record<string, string>) {\n super(message);\n this.name = \"BrandInputError\";\n this.fields = fields;\n }\n}\n\n/** Missing entity — the route layer maps it to a 404. */\nexport class BrandNotFoundError extends Error {\n constructor(what: string) {\n super(`${what} not found`);\n this.name = \"BrandNotFoundError\";\n }\n}\n\n/** A once-valid central authority/resource is permanently unavailable. */\nexport class BrandGoneError extends Error {\n constructor(message = \"brand authority or resource is no longer available\") {\n super(message);\n this.name = \"BrandGoneError\";\n }\n}\n\n/** Authenticated principal lacks the required principal kind/capability. */\nexport class BrandForbiddenError extends Error {\n constructor(message = \"forbidden\") {\n super(message);\n this.name = \"BrandForbiddenError\";\n }\n}\n\n/** Reviewed state or an idempotent action no longer matches current state. */\nexport class BrandConflictError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BrandConflictError\";\n }\n}\n\n/**\n * A proposal authority use was consumed, but the local guarded Brand write\n * lost its compare-and-swap race. Clients must preserve the reviewed draft but\n * rotate their idempotency key before a fresh human decision attempt.\n */\nexport class BrandReviewStateChangedError extends BrandConflictError {\n readonly code = \"brand_review_state_changed\";\n\n constructor(\n message = \"proposal or live brand dependencies changed; review and approve again\",\n ) {\n super(message);\n this.name = \"BrandReviewStateChangedError\";\n }\n}\n","// The odla-db schema @odla-ai/brand installs (POST to `/app/:id/schema` as\n// `{ schema: BRAND_SCHEMA }`). Ships pre-serialized (the wire shape) so\n// provisioning needs no schema-builder dependency, mirroring @odla-ai/chat\n// and @odla-ai/crm. The serialized types are inlined so the package has zero\n// deps.\n//\n// Design notes (grounded in the odla-db engine):\n// - Swatches are json ON `brand_palette`, NOT their own namespace: the\n// palette is the atomic proposal/approval unit — a human accepts or rejects\n// a palette whole, and swatches are never queried across palettes.\n// - Every child has a schema link to its book. CEL reads membership from the\n// CURRENT `book.memberIds` via ref(), so roster changes never require an\n// eventually-consistent audience fan-out. Proposal audience remains frozen\n// review provenance, not authorization state.\n// - Entity ids are not attributes in odla-db (`where: { id }` matches\n// nothing), so id-addressed rows mirror their id as a unique attr — the\n// crm pattern.\nimport { BRAND_NS } from \"./constants\";\n\n/** Wire-shape attribute value kinds odla-db stores. */\nexport type AttrType = \"string\" | \"number\" | \"boolean\" | \"date\" | \"json\";\n/** One serialized attribute: its type and index/uniqueness flags. */\nexport interface SerializedAttr {\n type: AttrType;\n unique: boolean;\n indexed: boolean;\n optional: boolean;\n}\n/** One serialized namespace: its attribute map. */\nexport interface SerializedEntity {\n attrs: Record<string, SerializedAttr>;\n}\n/** One end of a serialized schema link. */\nexport interface SerializedLinkEnd {\n on: string;\n has: \"one\" | \"many\";\n label: string;\n}\n/** A serialized schema link used for current-book authorization. */\nexport interface SerializedLink {\n forward: SerializedLinkEnd;\n reverse: SerializedLinkEnd;\n}\n/** The wire-shape schema POSTed to `/app/:id/schema`. */\nexport interface SerializedSchema {\n entities: Record<string, SerializedEntity>;\n links: Record<string, SerializedLink>;\n}\n\ntype Opt = Partial<Omit<SerializedAttr, \"type\">>;\nconst a = (type: AttrType, o: Opt = {}): SerializedAttr => ({\n type,\n unique: false,\n indexed: false,\n optional: false,\n ...o,\n});\nconst uniq = (type: AttrType): SerializedAttr => a(type, { unique: true, indexed: true });\nconst idx = (type: AttrType, optional = false): SerializedAttr => a(type, { indexed: true, optional });\nconst opt = (type: AttrType): SerializedAttr => a(type, { optional: true });\n\n/**\n * The pre-serialized (wire-shape) odla-db schema for the six brand\n * namespaces; POST it to `/app/:id/schema` as `{ schema: BRAND_SCHEMA }`.\n * Natural keys (`book.slug`, `section.key`) make provisioning and section\n * upserts idempotent; mirrored `id` attrs make rows addressable by\n * `where: { id }`.\n */\nexport const BRAND_SCHEMA: SerializedSchema = {\n entities: {\n [BRAND_NS.book]: {\n attrs: {\n id: uniq(\"string\"),\n version: a(\"number\"),\n slug: uniq(\"string\"),\n name: idx(\"string\"),\n status: idx(\"string\"), // draft | active | archived\n ownerId: idx(\"string\"),\n createdAuthorityRef: idx(\"string\"),\n rosterAuthorityRef: opt(\"string\"),\n memberIds: a(\"json\"), // the auth roster, incl. the bot agent id\n channelId: a(\"string\", { unique: true, indexed: true, optional: true }),\n activePaletteId: opt(\"string\"),\n activationRevision: a(\"number\"),\n tokens: opt(\"json\"), // maps + complete palette/typography receipt provenance\n summary: opt(\"string\"),\n createdAt: idx(\"date\"),\n updatedAt: idx(\"date\"),\n },\n },\n [BRAND_NS.section]: {\n attrs: {\n key: uniq(\"string\"), // `${bookId}:${kind}` — one section per kind\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // palette | typography | voice | logo | imagery\n status: idx(\"string\"), // draft | approved\n content: a(\"json\"),\n audience: a(\"json\"),\n updatedBy: a(\"string\"),\n updatedAt: idx(\"date\"),\n approvalReceiptId: opt(\"string\"),\n approvalActionDigest: opt(\"string\"),\n },\n },\n [BRAND_NS.palette]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n name: a(\"string\"),\n status: idx(\"string\"), // active | archived\n swatches: a(\"json\"), // Swatch[] — see the header design note\n seedHex: opt(\"string\"),\n source: a(\"string\"), // extracted | derived | manual\n rationale: opt(\"string\"),\n proposalId: idx(\"string\"),\n approvalReceiptId: a(\"string\"),\n approvalActionDigest: a(\"string\"),\n audience: a(\"json\"),\n createdAt: idx(\"date\"),\n updatedAt: idx(\"date\"),\n },\n },\n [BRAND_NS.proposal]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // palette | typography | voice | logo\n status: idx(\"string\"), // open | accepted | rejected | superseded\n payload: a(\"json\"),\n rationale: a(\"string\"),\n provenance: a(\"json\"), // exact source asset/message/turn ids (nullable asset)\n reviewDigest: idx(\"string\"),\n audience: a(\"json\"),\n createdBy: a(\"string\"),\n createdAuthorityRef: a(\"string\"),\n createdAt: idx(\"date\"),\n resolvedBy: opt(\"string\"),\n resolvedAt: opt(\"date\"),\n resolutionNote: opt(\"string\"),\n approvedBy: opt(\"string\"),\n appliedBy: opt(\"string\"),\n resolutionReceiptId: opt(\"string\"),\n resolutionActionDigest: opt(\"string\"),\n },\n },\n [BRAND_NS.approvalReceipt]: {\n attrs: {\n id: uniq(\"string\"),\n version: a(\"number\"),\n mutationKey: uniq(\"string\"),\n bookId: idx(\"string\"),\n proposalId: idx(\"string\"),\n resolution: idx(\"string\"), // accepted | rejected\n paletteId: opt(\"string\"),\n resolutionNote: opt(\"string\"),\n reviewedProposal: a(\"json\"),\n actionDigest: idx(\"string\"),\n decisionBinding: a(\"json\"),\n approvedBy: idx(\"string\"),\n approvedByKind: a(\"string\"),\n appliedBy: idx(\"string\"),\n appliedByKind: a(\"string\"),\n authorityRef: idx(\"string\"),\n authorityCapability: a(\"string\"),\n authorityConsumption: a(\"json\"),\n createdAt: idx(\"date\"),\n receiptDigest: idx(\"string\"),\n },\n },\n [BRAND_NS.asset]: {\n attrs: {\n id: uniq(\"string\"),\n bookId: idx(\"string\"),\n kind: idx(\"string\"), // logo | wordmark | inspiration | document | design | other\n path: idx(\"string\"),\n storageObjectId: idx(\"string\"),\n contentDigest: idx(\"string\"),\n contentType: a(\"string\"),\n size: a(\"number\"),\n status: idx(\"string\"), // live | deleting | deleted\n title: opt(\"string\"),\n analysis: opt(\"json\"), // { description, dominantColors: hex[], tags }\n analyzedAt: opt(\"date\"),\n // `design` kind only: the DesignDigest computed from the uploaded\n // bundle at upload time. Machine-derived and deterministic — unlike\n // `analysis`, which is what a model reports seeing — so it needs no\n // review gate and is rewritten only by re-uploading.\n design: opt(\"json\"),\n analysisRevision: a(\"number\"),\n analysisDigest: opt(\"string\"),\n analyzedBy: opt(\"string\"),\n analyzedAuthorityRef: opt(\"string\"),\n audience: a(\"json\"),\n uploadedBy: a(\"string\"),\n uploadedAuthorityRef: a(\"string\"),\n createdAt: idx(\"date\"),\n deletedAt: opt(\"date\"), // tombstone — asset rows are never row-deleted\n deletedBy: opt(\"string\"),\n deletedAuthorityRef: opt(\"string\"),\n },\n },\n },\n links: {\n brandSectionBook: {\n forward: { on: BRAND_NS.section, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"sections\" },\n },\n brandPaletteBook: {\n forward: { on: BRAND_NS.palette, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"palettes\" },\n },\n brandProposalBook: {\n forward: { on: BRAND_NS.proposal, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"proposals\" },\n },\n brandApprovalReceiptBook: {\n forward: { on: BRAND_NS.approvalReceipt, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"approvalReceipts\" },\n },\n brandAssetBook: {\n forward: { on: BRAND_NS.asset, has: \"one\", label: \"book\" },\n reverse: { on: BRAND_NS.book, has: \"many\", label: \"assets\" },\n },\n },\n};\n","// Reading a stored row back in the shape it was written.\n//\n// Split from review.ts along the seam between NORMALISING a row and VERIFYING\n// one. They are different jobs — the verifier proves self-consistency, this\n// undoes a storage detail — and only the second one needs to know the schema.\n//\n// The engine stores a `date` as the epoch ms it was given and hands a reader\n// ISO-8601 text back. Brand digests rows that CONTAIN dates, so a row read\n// straight out of the store can never match the digest stored beside it.\nimport { BRAND_NS } from \"./constants\";\nimport { BRAND_SCHEMA } from \"./schema\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/**\n * Attrs declared `date`, per namespace, from the schema itself.\n *\n * Derived rather than listed so a new `date` attr is covered the day it is\n * declared: a hand-kept list is the same defect one release later.\n */\nconst DATE_FIELDS = new Map<string, Set<string>>();\nfor (const [ns, entity] of Object.entries(BRAND_SCHEMA.entities))\n DATE_FIELDS.set(\n ns,\n new Set(\n Object.entries(entity.attrs)\n .filter(([, attr]) => attr.type === \"date\")\n .map(([label]) => label),\n ),\n );\n\n/**\n * A stored row in the shape it was WRITTEN, ready to verify.\n *\n * The engine stores a `date` as the epoch ms it was given and hands a reader\n * ISO-8601 text back. Brand digests rows that CONTAIN dates — a proposal's\n * `reviewDigest` covers its `createdAt`, and an approval receipt's\n * `receiptDigest` covers its own — so a row read straight out of the store can\n * never match the digest stored beside it. Two production symptoms, both 409:\n * resolving any proposal (\"proposal changed since review\") and reading a book's\n * tokens after approval.\n *\n * Normalising at the READ is the fix, not tolerating both shapes in the\n * verifier. Tolerance would repair a `safeTime` check and leave the digest\n * failing, because the digest was taken over the number and nothing can change\n * that after the fact.\n *\n * Anything that is not date-shaped text passes through untouched, so a row that\n * never round-tripped verifies exactly as before. `json` attrs are left alone:\n * their contents round-trip as written, which is why an `authorityConsumption`\n * and the `createdAt` beside it disagreed at all.\n */\nexport function rowAsWritten<T>(ns: string, row: T): T {\n const dates = DATE_FIELDS.get(ns);\n if (!dates?.size || !record(row)) return row;\n let changed = false;\n const out: Record<string, unknown> = { ...row };\n for (const field of dates) {\n const value = out[field];\n if (typeof value !== \"string\") continue;\n const parsed = Date.parse(value);\n if (!Number.isSafeInteger(parsed) || parsed < 0) continue;\n out[field] = parsed;\n changed = true;\n }\n return (changed ? out : row) as T;\n}\n\n/** A stored approval receipt in the shape it was written. */\nexport function receiptAsWritten<T>(row: T): T {\n return rowAsWritten(BRAND_NS.approvalReceipt, row);\n}\n\n/** A stored proposal in the shape it was written, so `reviewDigest` matches. */\nexport function proposalAsWritten<T>(row: T): T {\n return rowAsWritten(BRAND_NS.proposal, row);\n}\n\n/**\n * Every row of a query result in the shape it was written, keyed by the\n * namespace it came back under.\n *\n * Applied once, where an op resolves its database, rather than at each of the\n * two dozen read sites — which is the arrangement that left `crm` wrong at 26\n * of them after three were fixed by hand. A read site added tomorrow inherits\n * this; it cannot forget it.\n */\nexport function resultAsWritten<T extends Record<string, unknown>>(result: T): T {\n const out: Record<string, unknown> = { ...result };\n for (const [ns, rows] of Object.entries(out)) {\n if (Array.isArray(rows)) out[ns] = rows.map((row) => rowAsWritten(ns, row));\n }\n return out as T;\n}\n","// The dependency bundle brand operations take. `now`/`newId` are injectable\n// so tests can pin time and ids and assert exact written attrs; `fetchBytes`\n// is the one network seam (asset bytes for vision), injectable so tests and\n// service-binding hosts never touch the public internet.\nimport { resultAsWritten } from \"./read-shape\";\nimport type { BrandDb } from \"./types\";\n\n/** What `fetchBytes` resolves to: raw bytes plus the served content type. */\nexport interface BrandFetchedBytes {\n bytes: Uint8Array;\n contentType: string;\n}\n\n/** What every brand operation needs: the injected db, plus test overrides. */\nexport interface BrandDeps {\n db: BrandDb;\n /** Clock override (default `Date.now`). */\n now?: () => number;\n /** Id factory override (default `crypto.randomUUID`). */\n newId?: () => string;\n /** Asset-byte fetcher override (default: global `fetch`). */\n fetchBytes?: (url: string) => Promise<BrandFetchedBytes>;\n}\n\n/** {@link BrandDeps} with the injectable defaults filled in. */\nexport interface ResolvedBrandDeps {\n db: BrandDb;\n now: () => number;\n newId: () => string;\n fetchBytes: (url: string) => Promise<BrandFetchedBytes>;\n}\n\nasync function defaultFetchBytes(url: string): Promise<BrandFetchedBytes> {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`asset fetch failed: ${res.status} for ${url}`);\n return {\n bytes: new Uint8Array(await res.arrayBuffer()),\n contentType: res.headers.get(\"content-type\") ?? \"application/octet-stream\",\n };\n}\n\n/**\n * The database every op reads through, with a `date` handed back as the epoch\n * ms it was written as.\n *\n * Brand digests rows that contain dates, so a row read straight out of the\n * store could never match the digest stored beside it — #486 fixed that at\n * roughly a dozen read sites and left the other eleven. Doing it here means a\n * read site added later inherits it. Writes are untouched: only what comes\n * back changes shape.\n *\n * Methods are forwarded one by one rather than spread: the db is often a class\n * instance, and spreading one leaves every prototype method behind.\n */\nfunction readingAsWritten(db: BrandDb): BrandDb {\n return {\n query: async (q) => resultAsWritten(await db.query(q)),\n transact: (ops, opts) => db.transact(ops, opts),\n storage: db.storage,\n };\n}\n\n/** Fill the injectable defaults. */\nexport function resolveDeps(deps: BrandDeps): ResolvedBrandDeps {\n return {\n db: readingAsWritten(deps.db),\n now: deps.now ?? Date.now,\n newId: deps.newId ?? (() => crypto.randomUUID()),\n fetchBytes: deps.fetchBytes ?? defaultFetchBytes,\n };\n}\n","// Default-deny CEL rules for the brand namespaces (POST to\n// `/app/:id/admin/rules`). Access is denormalized (see schema.ts): books gate\n// on `data.memberIds`; child rows follow their required book link and read the\n// current roster with `ref()`. Child writes are closed: proposals and\n// approval receipts all pass through worker routes/tools with explicit actor\n// attribution instead of letting an audience member mutate approval state.\n//\n// Asset writes are closed: rows mirror private object storage and only the\n// worker performs upload/mirror and delete/tombstone pairs.\nimport { BRAND_NS } from \"./constants\";\n\n/** Per-namespace CEL rule strings (missing action = deny). */\nexport interface BrandRule {\n view?: string;\n create?: string;\n update?: string;\n delete?: string;\n}\n/** Namespace → rule set, as installed at `/app/:id/admin/rules`. */\nexport type BrandRules = Record<string, BrandRule>;\n\n// Membership in the audience snapshot — implies a signed identity, since an\n// anonymous auth.id is never written into an audience.\n// A has-one link's ref() result is still a list; the json memberIds value is\n// therefore nested one level (`[[id,…]]`) and must be checked with exists.\nconst CURRENT_BOOK_MEMBER =\n \"ref('book.memberIds').exists(members, auth.id in members)\";\n\n/**\n * Default-deny CEL rules for the six brand namespaces; install at\n * `/app/:id/admin/rules`. Books gate on the `memberIds` roster (owner-only\n * writes); child rows gate reads on current linked-book membership and all\n * writes are worker-mediated. Use\n * {@link brandRules} for a per-install copy.\n */\nexport const BRAND_RULES: BrandRules = {\n [BRAND_NS.book]: {\n view: \"auth.id in data.memberIds\",\n // Every mutation is worker-routed: CEL cannot distinguish an update from\n // a retract, so effect-bearing fields must never be browser-writable.\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.section]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.palette]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.proposal]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.approvalReceipt]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n [BRAND_NS.asset]: {\n view: CURRENT_BOOK_MEMBER,\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n};\n\n/**\n * Rules factory, mirroring `chatRules()`/`crmRules()`. Today it returns a\n * fresh copy of {@link BRAND_RULES}; it exists so a future option (e.g.\n * locking views to an org email domain) can widen or tighten namespaces\n * without apps changing their provisioning call shape.\n */\nexport function brandRules(): BrandRules {\n return Object.fromEntries(Object.entries(BRAND_RULES).map(([ns, r]) => [ns, { ...r }]));\n}\n","// Input validation for brand writes — THE enforcement layer. Taint marking on\n// tool output is advisory; nothing an agent (or a route caller) produces\n// reaches odla-db without passing these checks. Every failure throws\n// {@link BrandInputError} with an actionable message.\nimport { DESIGN_ASSET_KIND, SECTION_KINDS, SWATCH_ROLES } from \"./constants\";\nimport { BrandInputError } from \"./errors\";\nimport type {\n AssetAnalysis,\n ImagerySection,\n LogoSection,\n PaletteSection,\n Swatch,\n SwatchRole,\n TypographySection,\n VoiceSection,\n} from \"./types\";\n\n/** Most swatches a single palette may carry. */\nexport const MAX_SWATCHES = 24;\n\n/** Upload content types the asset pipeline accepts for every kind EXCEPT\n * `design`. Deliberately free of `text/html`: these bytes are handed back to\n * members over signed storage URLs, and an HTML document served from a\n * storage origin is a script-execution surface. */\nexport const ASSET_CONTENT_TYPES: ReadonlySet<string> = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/pdf\",\n]);\n\n/** The only content type a `design` asset may carry. Designs are the one\n * HTML-bearing kind, and they are never served raw — the preview route\n * proxies them under a `sandbox` CSP (see `routes/design-preview.ts`). */\nexport const DESIGN_CONTENT_TYPES: ReadonlySet<string> = new Set([\"text/html\"]);\n\nconst HEX_RGB = /^#[0-9a-f]{3}$/;\nconst HEX_RRGGBB = /^#[0-9a-f]{6}$/;\nconst HEX_ALPHA = /^#[0-9a-f]{4}$|^#[0-9a-f]{8}$/;\nconst UI_TOKEN_NAME = /^--ui-[a-z0-9-]+$/;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/**\n * Assert `value` is a `#rgb`/`#rrggbb` hex color and normalize it to\n * lowercase `#rrggbb`. Alpha channels (`#rgba`/`#rrggbbaa`) and every other\n * color syntax are rejected — tokens and contrast math are defined on opaque\n * sRGB hex.\n */\nexport function assertHex(value: unknown, label = \"color\"): string {\n if (typeof value !== \"string\")\n throw new BrandInputError(`${label} must be a hex string like #1a2b3c`);\n const hex = value.trim().toLowerCase();\n if (HEX_ALPHA.test(hex))\n throw new BrandInputError(`${label} must not carry alpha (got ${value}); use #rrggbb`);\n if (HEX_RGB.test(hex)) return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;\n if (!HEX_RRGGBB.test(hex))\n throw new BrandInputError(`${label} must be #rgb or #rrggbb hex (got ${value})`);\n return hex;\n}\n\n/** Assert a trimmed non-empty string of at most `max` characters. */\nexport function capString(value: unknown, label: string, max: number): string {\n if (typeof value !== \"string\") throw new BrandInputError(`${label} must be a string`);\n const s = value.trim();\n if (s === \"\") throw new BrandInputError(`${label} must not be empty`);\n if (s.length > max)\n throw new BrandInputError(`${label} must be at most ${max} characters (got ${s.length})`);\n return s;\n}\n\n/** Assert an array of capped strings (each trimmed and non-empty). */\nexport function capStringArray(\n value: unknown,\n label: string,\n opts: { maxItems: number; maxLen: number; minItems?: number },\n): string[] {\n if (!Array.isArray(value)) throw new BrandInputError(`${label} must be an array of strings`);\n const min = opts.minItems ?? 0;\n if (value.length < min)\n throw new BrandInputError(`${label} must have at least ${min} item${min === 1 ? \"\" : \"s\"}`);\n if (value.length > opts.maxItems)\n throw new BrandInputError(`${label} must have at most ${opts.maxItems} items`);\n return value.map((v, i) => capString(v, `${label}[${i}]`, opts.maxLen));\n}\n\n/**\n * Assert a swatch list: 1–{@link MAX_SWATCHES} entries, each with a known\n * role, a valid hex (normalized), and capped optional name/rationale.\n * Returns the normalized copy — write THAT, never the raw input.\n */\nexport function assertSwatches(value: unknown): Swatch[] {\n if (!Array.isArray(value) || value.length === 0)\n throw new BrandInputError(\"swatches must be a non-empty array\");\n if (value.length > MAX_SWATCHES)\n throw new BrandInputError(`swatches must have at most ${MAX_SWATCHES} entries`);\n return value.map((raw, i) => {\n if (!isRecord(raw)) throw new BrandInputError(`swatches[${i}] must be an object`);\n const role = raw.role;\n if (typeof role !== \"string\" || !(SWATCH_ROLES as readonly string[]).includes(role))\n throw new BrandInputError(\n `swatches[${i}].role must be one of: ${SWATCH_ROLES.join(\", \")}`,\n );\n const out: Swatch = { role: role as SwatchRole, hex: assertHex(raw.hex, `swatches[${i}].hex`) };\n if (raw.name !== undefined) out.name = capString(raw.name, `swatches[${i}].name`, 80);\n if (raw.rationale !== undefined)\n out.rationale = capString(raw.rationale, `swatches[${i}].rationale`, 500);\n return out;\n });\n}\n\nfunction assertPaletteSection(c: Record<string, unknown>): PaletteSection {\n return {\n paletteId: capString(c.paletteId, \"content.paletteId\", 128),\n name: capString(c.name, \"content.name\", 120),\n swatches: assertSwatches(c.swatches),\n };\n}\n\nfunction assertTypographySection(c: Record<string, unknown>): TypographySection {\n const out: TypographySection = {};\n if (c.fontDisplay !== undefined) out.fontDisplay = capString(c.fontDisplay, \"content.fontDisplay\", 120);\n if (c.fontBody !== undefined) out.fontBody = capString(c.fontBody, \"content.fontBody\", 120);\n if (c.fontMono !== undefined) out.fontMono = capString(c.fontMono, \"content.fontMono\", 120);\n if (c.scale !== undefined) {\n if (typeof c.scale !== \"number\" || !Number.isFinite(c.scale) || c.scale <= 1 || c.scale > 2)\n throw new BrandInputError(\"content.scale must be a modular type-scale ratio in (1, 2]\");\n out.scale = c.scale;\n }\n if (c.notes !== undefined) out.notes = capString(c.notes, \"content.notes\", 2000);\n if (c.tokenOverrides !== undefined) {\n if (!isRecord(c.tokenOverrides))\n throw new BrandInputError(\"content.tokenOverrides must be an object\");\n const entries = Object.entries(c.tokenOverrides);\n if (entries.length > 64)\n throw new BrandInputError(\"content.tokenOverrides must have at most 64 entries\");\n out.tokenOverrides = Object.fromEntries(entries.map(([name, raw]) => {\n if (!UI_TOKEN_NAME.test(name))\n throw new BrandInputError(`content.tokenOverrides.${name} must be a --ui-* token name`);\n const value = capString(raw, `content.tokenOverrides.${name}`, 500);\n if (/[;{}]/.test(value) || /url\\s*\\(/i.test(value))\n throw new BrandInputError(`content.tokenOverrides.${name} contains an unsafe CSS value`);\n return [name, value];\n }));\n }\n return out;\n}\n\nfunction assertVoiceSection(c: Record<string, unknown>): VoiceSection {\n const out: VoiceSection = {\n tone: capString(c.tone, \"content.tone\", 200),\n principles: capStringArray(c.principles, \"content.principles\", { maxItems: 12, maxLen: 200, minItems: 1 }),\n };\n if (c.examples !== undefined)\n out.examples = capStringArray(c.examples, \"content.examples\", { maxItems: 12, maxLen: 500 });\n return out;\n}\n\nfunction assertLogoSection(c: Record<string, unknown>): LogoSection {\n const out: LogoSection = {\n usage: capStringArray(c.usage, \"content.usage\", { maxItems: 16, maxLen: 300, minItems: 1 }),\n donts: capStringArray(c.donts, \"content.donts\", { maxItems: 16, maxLen: 300 }),\n };\n if (c.clearspace !== undefined) out.clearspace = capString(c.clearspace, \"content.clearspace\", 120);\n if (c.minSize !== undefined) out.minSize = capString(c.minSize, \"content.minSize\", 120);\n return out;\n}\n\nfunction assertImagerySection(c: Record<string, unknown>): ImagerySection {\n return {\n style: capString(c.style, \"content.style\", 200),\n guidance: capStringArray(c.guidance, \"content.guidance\", { maxItems: 16, maxLen: 300, minItems: 1 }),\n };\n}\n\n/**\n * Validate + normalize a section's `content` payload for its kind. Returns\n * the normalized content to write; throws {@link BrandInputError} on an\n * unknown kind or an invalid payload.\n */\nexport function assertSectionContent(kind: string, content: unknown): Record<string, unknown> {\n if (!isRecord(content)) throw new BrandInputError(\"content must be an object\");\n switch (kind) {\n case \"palette\":\n return { ...assertPaletteSection(content) };\n case \"typography\":\n return { ...assertTypographySection(content) };\n case \"voice\":\n return { ...assertVoiceSection(content) };\n case \"logo\":\n return { ...assertLogoSection(content) };\n case \"imagery\":\n return { ...assertImagerySection(content) };\n default:\n throw new BrandInputError(`unknown section kind ${kind}; expected one of: ${SECTION_KINDS.join(\", \")}`);\n }\n}\n\n/**\n * Validate an upload file name for an R2 key. Path/URL delimiters and control\n * characters are rejected; leading dots are stripped and length is capped.\n */\nexport function safeFileName(name: unknown): string {\n if (typeof name !== \"string\") throw new BrandInputError(\"file name must be a string\");\n // eslint-disable-next-line no-control-regex\n if (/[/\\\\?#%\\u0000-\\u001f\\u007f]/.test(name))\n throw new BrandInputError(\"file name must not contain path or URL delimiter characters\");\n const cleaned = name\n .trim()\n .replace(/^\\.+/, \"\");\n if (cleaned === \"\" || cleaned === \".\" || cleaned === \"..\")\n throw new BrandInputError(\"file name is empty or a dot segment after sanitizing\");\n return cleaned.slice(0, 120);\n}\n\n/**\n * Assert an upload content type is allowed FOR ITS KIND, and return the\n * normalized bare type (case-folded, `; charset=…` stripped).\n *\n * The allowlist is per-kind, not global: `design` accepts\n * {@link DESIGN_CONTENT_TYPES} and nothing else, every other kind accepts\n * {@link ASSET_CONTENT_TYPES} and nothing else. The two sets are disjoint on\n * purpose — it must be impossible to store HTML under a kind whose bytes are\n * handed out by signed URL, or to store an image under the kind the preview\n * route serves as a document.\n */\nexport function assertAssetContentType(value: unknown, kind?: string): string {\n if (typeof value !== \"string\") throw new BrandInputError(\"contentType must be a string\");\n const ct = value.split(\";\")[0]!.trim().toLowerCase();\n const allowed = kind === DESIGN_ASSET_KIND ? DESIGN_CONTENT_TYPES : ASSET_CONTENT_TYPES;\n if (!allowed.has(ct))\n throw new BrandInputError(\n `unsupported content type ${ct || \"(empty)\"} for kind ${kind ?? \"other\"}; allowed: ${[...allowed].join(\", \")}`,\n );\n return ct;\n}\n\n/**\n * Validate + normalize an agent's asset analysis: description ≤ 2000 chars,\n * ≤ 12 dominant colors (each normalized hex), ≤ 24 tags of ≤ 60 chars.\n */\nexport function assertAnalysis(value: unknown): AssetAnalysis {\n if (!isRecord(value)) throw new BrandInputError(\"analysis must be an object\");\n const colors = value.dominantColors;\n if (!Array.isArray(colors)) throw new BrandInputError(\"analysis.dominantColors must be an array\");\n if (colors.length > 12)\n throw new BrandInputError(\"analysis.dominantColors must have at most 12 entries\");\n return {\n description: capString(value.description, \"analysis.description\", 2000),\n dominantColors: colors.map((c, i) => assertHex(c, `analysis.dominantColors[${i}]`)),\n tags: capStringArray(value.tags, \"analysis.tags\", { maxItems: 24, maxLen: 60 }),\n };\n}\n","const record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype ||\n Object.getPrototypeOf(value) === null);\n\n/** Stay materially below the server's whole-guards parser budget. */\nexport function isBoundedBrandJson(\n root: unknown,\n limits: { maxDepth?: number; maxNodes?: number; maxBytes?: number } = {},\n): boolean {\n const maxDepth = limits.maxDepth ?? 12;\n const maxNodes = limits.maxNodes ?? 2_048;\n const maxBytes = limits.maxBytes ?? 32 * 1024;\n const stack: Array<{ value: unknown; depth: number }> = [{\n value: root,\n depth: 0,\n }];\n const seen = new Set<object>();\n let nodes = 0;\n while (stack.length) {\n const { value, depth } = stack.pop()!;\n if (++nodes > maxNodes || depth > maxDepth) return false;\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"boolean\"\n ) continue;\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) return false;\n continue;\n }\n if (typeof value !== \"object\" || seen.has(value)) return false;\n seen.add(value);\n if (Array.isArray(value)) {\n for (const child of value)\n stack.push({ value: child, depth: depth + 1 });\n } else if (record(value)) {\n for (const child of Object.values(value))\n stack.push({ value: child, depth: depth + 1 });\n } else {\n return false;\n }\n }\n try {\n return new TextEncoder().encode(JSON.stringify(root)).byteLength <= maxBytes;\n } catch {\n return false;\n }\n}\n\nfunction canonical(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n const row = value as Record<string, unknown>;\n return `{${Object.keys(row).sort().map((key) =>\n `${JSON.stringify(key)}:${canonical(row[key])}`).join(\",\")}}`;\n}\n\n/** Deterministic JSON with recursively sorted object keys. */\nexport function canonicalBrandJson(value: unknown): string {\n if (!isBoundedBrandJson(value, {\n maxDepth: 20,\n maxNodes: 8_192,\n maxBytes: 128 * 1024,\n })) throw new TypeError(\"brand digest input must be bounded finite JSON\");\n return canonical(value);\n}\n\n/** `sha256:<hex>` over {@link canonicalBrandJson}. */\nexport async function brandJsonDigest(value: unknown): Promise<string> {\n const bytes = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(canonicalBrandJson(value)),\n );\n return `sha256:${[...new Uint8Array(bytes)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n","// Bounded canonical JSON and self-consistency checks for Brand review and\n// approval records. A local digest is not an authenticity proof: authenticity\n// comes from the credential-bound central authority consumption embedded in\n// the receipt.\nimport { PROPOSAL_KINDS } from \"./constants\";\nexport { proposalAsWritten, receiptAsWritten, rowAsWritten } from \"./read-shape\";\nimport type {\n BrandApprovalReceipt,\n BrandHumanAuthorityConsumption,\n BrandProposalReviewSnapshot,\n} from \"./types\";\nimport {\n brandJsonDigest,\n isBoundedBrandJson,\n} from \"./review-json\";\n\nexport {\n brandJsonDigest,\n canonicalBrandJson,\n isBoundedBrandJson,\n} from \"./review-json\";\n\nconst DIGEST = /^sha256:[0-9a-f]{64}$/;\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);\nconst exactKeys = (value: Record<string, unknown>, required: readonly string[], optional: readonly string[] = []) => {\n const allowed = new Set([...required, ...optional]);\n return required.every((key) => Object.hasOwn(value, key)) &&\n Object.keys(value).every((key) => allowed.has(key));\n};\nconst boundedString = (value: unknown, max = 200): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= max;\nconst safeTime = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\n/** Stable local reference to one immutable central grant revision. */\nexport function brandAuthorityRef(\n consumption: Pick<BrandHumanAuthorityConsumption, \"grantId\" | \"grantVersion\">,\n): string {\n return `authority:${consumption.grantId}:v${consumption.grantVersion}`;\n}\n\nconst SNAPSHOT_REQUIRED = [\n \"id\", \"bookId\", \"kind\", \"status\", \"payload\", \"rationale\", \"provenance\",\n \"reviewDigest\", \"audience\", \"createdBy\", \"createdAuthorityRef\", \"createdAt\",\n] as const;\n\nfunction validSnapshotShape(value: unknown): value is BrandProposalReviewSnapshot {\n if (!record(value) || !exactKeys(value, SNAPSHOT_REQUIRED)) return false;\n const provenance = value.provenance;\n return boundedString(value.id) &&\n boundedString(value.bookId) &&\n typeof value.kind === \"string\" &&\n (PROPOSAL_KINDS as readonly string[]).includes(value.kind) &&\n value.status === \"open\" &&\n record(value.payload) &&\n boundedString(value.rationale, 2_000) &&\n record(provenance) &&\n exactKeys(provenance, [\n \"sourceAssetId\", \"sourceAsset\", \"messageId\", \"turnId\", \"taintLabels\",\n ]) &&\n (provenance.sourceAssetId === null ||\n boundedString(provenance.sourceAssetId)) &&\n (provenance.sourceAsset === null ||\n (record(provenance.sourceAsset) &&\n exactKeys(provenance.sourceAsset, [\n \"assetId\", \"contentDigest\", \"objectEtag\", \"objectSize\", \"pathDigest\",\n \"contentType\", \"analysisRevision\", \"analysisDigest\",\n ]) &&\n boundedString(provenance.sourceAsset.assetId) &&\n typeof provenance.sourceAsset.contentDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.contentDigest) &&\n boundedString(provenance.sourceAsset.objectEtag) &&\n Number.isSafeInteger(provenance.sourceAsset.objectSize) &&\n (provenance.sourceAsset.objectSize as number) > 0 &&\n typeof provenance.sourceAsset.pathDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.pathDigest) &&\n (provenance.sourceAsset.contentType === null ||\n boundedString(provenance.sourceAsset.contentType, 160)) &&\n (provenance.sourceAsset.analysisRevision === null ||\n (Number.isSafeInteger(provenance.sourceAsset.analysisRevision) &&\n (provenance.sourceAsset.analysisRevision as number) >= 0)) &&\n (provenance.sourceAsset.analysisDigest === null ||\n (typeof provenance.sourceAsset.analysisDigest === \"string\" &&\n DIGEST.test(provenance.sourceAsset.analysisDigest))))) &&\n ((provenance.sourceAssetId === null && provenance.sourceAsset === null) ||\n (provenance.sourceAssetId !== null &&\n provenance.sourceAsset !== null &&\n provenance.sourceAsset.assetId === provenance.sourceAssetId)) &&\n (provenance.messageId === null || boundedString(provenance.messageId)) &&\n (provenance.turnId === null || boundedString(provenance.turnId)) &&\n Array.isArray(provenance.taintLabels) &&\n provenance.taintLabels.length <= 16 &&\n provenance.taintLabels.every((label) => boundedString(label, 120)) &&\n new Set(provenance.taintLabels).size === provenance.taintLabels.length &&\n typeof value.reviewDigest === \"string\" && DIGEST.test(value.reviewDigest) &&\n Array.isArray(value.audience) &&\n value.audience.length > 0 && value.audience.length <= 100 &&\n value.audience.every((id) => boundedString(id)) &&\n new Set(value.audience).size === value.audience.length &&\n boundedString(value.createdBy) &&\n boundedString(value.createdAuthorityRef) &&\n safeTime(value.createdAt);\n}\n\nconst CONSUMPTION_REQUIRED = [\n \"id\", \"grantId\", \"grantVersion\", \"useNumber\", \"actorPrincipalId\",\n \"actorKind\", \"credentialId\", \"credentialKind\", \"appId\", \"appIncarnation\",\n \"capability\",\n \"projectCapability\", \"effect\", \"actionDigest\", \"resourceDigest\",\n \"constraintEvidence\",\n \"consumptionIdempotencyKey\", \"requestDigest\", \"consumedAt\",\n] as const;\n\n/** Validate the exact direct-human central authority receipt shape. */\nexport function isBrandHumanAuthorityConsumption(\n value: unknown,\n): value is BrandHumanAuthorityConsumption {\n if (!record(value) || !exactKeys(value, CONSUMPTION_REQUIRED)) return false;\n return boundedString(value.id) &&\n boundedString(value.grantId) &&\n Number.isSafeInteger(value.grantVersion) && (value.grantVersion as number) > 0 &&\n Number.isSafeInteger(value.useNumber) && (value.useNumber as number) > 0 &&\n boundedString(value.actorPrincipalId) &&\n value.actorKind === \"human\" &&\n boundedString(value.credentialId) &&\n value.credentialKind === \"clerk\" &&\n boundedString(value.appId) &&\n typeof value.appIncarnation === \"string\" &&\n /^[a-f0-9]{32}$/.test(value.appIncarnation) &&\n value.capability === \"brand.proposal.resolve\" &&\n value.projectCapability === \"brand.approve\" &&\n value.effect === \"internal\" &&\n typeof value.actionDigest === \"string\" && DIGEST.test(value.actionDigest) &&\n typeof value.resourceDigest === \"string\" && DIGEST.test(value.resourceDigest) &&\n record(value.constraintEvidence) &&\n boundedString(value.consumptionIdempotencyKey) &&\n typeof value.requestDigest === \"string\" && DIGEST.test(value.requestDigest) &&\n safeTime(value.consumedAt);\n}\n\nconst RECEIPT_REQUIRED = [\n \"version\", \"id\", \"mutationKey\", \"bookId\", \"proposalId\", \"resolution\",\n \"reviewedProposal\", \"actionDigest\", \"decisionBinding\", \"approvedBy\", \"approvedByKind\",\n \"appliedBy\", \"appliedByKind\", \"authorityRef\", \"authorityCapability\",\n \"authorityConsumption\", \"createdAt\", \"receiptDigest\",\n] as const;\n\n/** Verify exact shape, cross-field bindings, and every local digest. This\n * proves receipt self-consistency only; the host must authenticate the\n * central consumption behind `authorityConsumption.id`. */\nexport async function verifyBrandApprovalReceipt(receipt: unknown): Promise<boolean> {\n try {\n if (!isBoundedBrandJson(receipt, { maxDepth: 14, maxNodes: 2_500, maxBytes: 48 * 1024 }))\n return false;\n if (!record(receipt) || !exactKeys(receipt, RECEIPT_REQUIRED, [\"paletteId\", \"resolutionNote\"]))\n return false;\n const binding = receipt.decisionBinding;\n if (\n receipt.version !== 1 ||\n !boundedString(receipt.id) ||\n !boundedString(receipt.mutationKey) ||\n !boundedString(receipt.bookId) ||\n !boundedString(receipt.proposalId) ||\n (receipt.resolution !== \"accepted\" && receipt.resolution !== \"rejected\") ||\n !validSnapshotShape(receipt.reviewedProposal) ||\n typeof receipt.actionDigest !== \"string\" || !DIGEST.test(receipt.actionDigest) ||\n !record(binding) ||\n !exactKeys(binding, [\n \"version\", \"bookVersion\", \"activationRevision\", \"activePaletteId\",\n \"memberIdsDigest\", \"activePaletteDigest\", \"typographyDigest\",\n \"sourceAssetDigest\", \"effectDigest\",\n ]) ||\n binding.version !== 1 ||\n !Number.isSafeInteger(binding.bookVersion) || (binding.bookVersion as number) < 1 ||\n !Number.isSafeInteger(binding.activationRevision) ||\n (binding.activationRevision as number) < 0 ||\n (binding.activePaletteId !== null && !boundedString(binding.activePaletteId)) ||\n typeof binding.memberIdsDigest !== \"string\" || !DIGEST.test(binding.memberIdsDigest) ||\n (binding.activePaletteDigest !== null &&\n (typeof binding.activePaletteDigest !== \"string\" ||\n !DIGEST.test(binding.activePaletteDigest))) ||\n (binding.typographyDigest !== null &&\n (typeof binding.typographyDigest !== \"string\" ||\n !DIGEST.test(binding.typographyDigest))) ||\n (binding.sourceAssetDigest !== null &&\n (typeof binding.sourceAssetDigest !== \"string\" ||\n !DIGEST.test(binding.sourceAssetDigest))) ||\n typeof binding.effectDigest !== \"string\" || !DIGEST.test(binding.effectDigest) ||\n !boundedString(receipt.approvedBy) ||\n receipt.approvedByKind !== \"human\" ||\n !boundedString(receipt.appliedBy) ||\n receipt.appliedByKind !== \"human\" ||\n !boundedString(receipt.authorityRef) ||\n receipt.authorityCapability !== \"brand.approve\" ||\n !isBrandHumanAuthorityConsumption(receipt.authorityConsumption) ||\n !safeTime(receipt.createdAt) ||\n typeof receipt.receiptDigest !== \"string\" || !DIGEST.test(receipt.receiptDigest) ||\n (receipt.paletteId !== undefined && !boundedString(receipt.paletteId)) ||\n (receipt.resolutionNote !== undefined && !boundedString(receipt.resolutionNote, 1_000))\n ) return false;\n\n const reviewed = receipt.reviewedProposal;\n const authority = receipt.authorityConsumption;\n if (\n reviewed.id !== receipt.proposalId ||\n reviewed.bookId !== receipt.bookId ||\n receipt.approvedBy !== receipt.appliedBy ||\n authority.actorPrincipalId !== receipt.approvedBy ||\n authority.actionDigest !== receipt.actionDigest ||\n authority.consumptionIdempotencyKey !== receipt.mutationKey ||\n receipt.authorityRef !== brandAuthorityRef(authority) ||\n authority.consumedAt > receipt.createdAt ||\n (receipt.resolution === \"rejected\" && receipt.paletteId !== undefined) ||\n (receipt.resolution === \"accepted\" && reviewed.kind === \"palette\" && !receipt.paletteId) ||\n (reviewed.kind !== \"palette\" && receipt.paletteId !== undefined)\n ) return false;\n\n const { reviewDigest, ...unsignedReview } = reviewed;\n if ((await brandJsonDigest(unsignedReview)) !== reviewDigest) return false;\n const expectedAction = await brandJsonDigest({\n version: 1,\n reviewedProposal: reviewed,\n resolution: receipt.resolution,\n resolutionNote: receipt.resolutionNote ?? null,\n paletteId: receipt.paletteId ?? null,\n decisionBinding: binding,\n });\n if (expectedAction !== receipt.actionDigest) return false;\n if ((await brandJsonDigest({ bookId: receipt.bookId, proposalId: receipt.proposalId })) !==\n authority.resourceDigest) return false;\n\n const { receiptDigest, ...immutable } = receipt;\n return (await brandJsonDigest(immutable)) === receiptDigest;\n } catch {\n return false;\n }\n}\n","/** Brand resources that can be shared into a Discussion message. */\nexport const BRAND_DISCUSSION_REFERENCE_KINDS = [\n \"brand:book\",\n \"brand:asset\",\n \"brand:palette\",\n \"brand:proposal\",\n \"brand:receipt\",\n] as const;\n\n/** One Brand resource kind understood by the native Brand destination. */\nexport type BrandDiscussionReferenceKind =\n (typeof BRAND_DISCUSSION_REFERENCE_KINDS)[number];\n\n/** Canonical Brand destination target parsed from an `odla-ref` deep link. */\nexport interface BrandDiscussionReferenceTarget {\n kind: BrandDiscussionReferenceKind;\n bookId: string;\n resourceId?: string;\n}\n\n/** Bounded color projection shared with Discussion people and agents. */\nexport interface BrandDiscussionSwatch {\n /** Semantic role used by the Brand token compiler. */\n role: string;\n /** Normalized opaque sRGB color (`#rrggbb`). */\n hex: string;\n /** Optional product-authored color name. */\n name?: string;\n}\n\n/** Product-owned projection returned to Discussion typeahead and exact lookup. */\nexport interface BrandDiscussionReference {\n /** Canonical Brand kind used in stored Discussion ref markup. */\n kind: BrandDiscussionReferenceKind;\n /** Opaque durable product id; never infer membership from its segments. */\n id: string;\n /** Product-authored primary display name. */\n label: string;\n /** Short product-authored secondary context for the picker. */\n hint: string;\n /** Bounded product-authored context safe to show an LLM or person. */\n summary: string;\n /** Current product status at inspection time. */\n status: string;\n /** Human-readable native surface the link opens. */\n destination: string;\n /** Same-origin native link; navigation is not mutation authority. */\n href: string;\n /** Present only for a validated Brand palette, capped by Brand's swatch limit. */\n swatches?: BrandDiscussionSwatch[];\n}\n\nconst SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._~-]{0,199}$/;\n\n/** Durable ref id: a book id, or `bookId/resourceId` for a child resource. */\nexport function brandDiscussionReferenceId(\n target: BrandDiscussionReferenceTarget,\n): string {\n return target.resourceId\n ? `${target.bookId}/${target.resourceId}`\n : target.bookId;\n}\n\n/** Canonical value stored in the stable `odla-ref` query parameter. */\nexport function formatBrandDiscussionReference(\n target: BrandDiscussionReferenceTarget,\n): string {\n return `${target.kind}/${brandDiscussionReferenceId(target)}`;\n}\n\n/** Parse and validate a Brand `odla-ref`; malformed and cross-product refs fail closed. */\nexport function parseBrandDiscussionReference(\n input: URL | string,\n): BrandDiscussionReferenceTarget | null {\n let raw: string | null;\n try {\n raw = input instanceof URL\n ? input.searchParams.get(\"odla-ref\")\n : new URL(input, \"https://brand.invalid\").searchParams.get(\"odla-ref\");\n } catch {\n return null;\n }\n if (!raw) return null;\n const [kind, bookId, resourceId, extra] = raw.split(\"/\");\n if (\n extra !== undefined ||\n !BRAND_DISCUSSION_REFERENCE_KINDS.includes(\n kind as BrandDiscussionReferenceKind,\n ) ||\n !bookId ||\n !SEGMENT.test(bookId)\n ) return null;\n const typedKind = kind as BrandDiscussionReferenceKind;\n if (typedKind === \"brand:book\") {\n return resourceId === undefined ? { kind: typedKind, bookId } : null;\n }\n return resourceId && SEGMENT.test(resourceId)\n ? { kind: typedKind, bookId, resourceId }\n : null;\n}\n\n/** Build the native Brand deep link while preserving the deployed origin. */\nexport function brandDiscussionReferenceHref(\n current: URL,\n target: BrandDiscussionReferenceTarget,\n basePath = \"/\",\n): string {\n const next = new URL(current.origin);\n next.pathname = basePath.startsWith(\"/\") ? basePath : `/${basePath}`;\n next.searchParams.set(\"odla-ref\", formatBrandDiscussionReference(target));\n return next.toString();\n}\n","// Pure op-builders for brand_book rows: (input) -> BrandOp[]. No I/O — this\n// is the unit-test seam (assert the emitted ops); routes and the skill share\n// these so every write path commits identical shapes.\nimport { BOOK_STATUSES, BRAND_NS, type BookStatus } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandAttrs, BrandBook, BrandEntityRef, BrandOp } from \"../types\";\nimport { capString } from \"../validate\";\n\nconst SLUG_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/** Input to {@link createBookOps}. `memberIds` is the full auth roster —\n * include the bot agent's id so it can pass the audience rules. */\nexport interface CreateBookInput {\n id: string;\n slug: string;\n name: string;\n ownerId: string;\n createdAuthorityRef: string;\n memberIds: string[];\n channelId?: string;\n now: number;\n}\n\n/**\n * Ops to create a brand book: one `brand_book` row in `draft` status with the\n * id mirrored as an attr (odla-db ids aren't attrs), the owner always folded\n * into the deduplicated `memberIds` roster (the create rule requires it), and\n * both timestamps set to `now`.\n */\nexport function createBookOps(input: CreateBookInput): BrandOp[] {\n const slug = capString(input.slug, \"slug\", 80);\n if (!SLUG_RE.test(slug))\n throw new BrandInputError(\"slug must be lowercase letters, digits, and inner hyphens\");\n const name = capString(input.name, \"name\", 120);\n const ownerId = capString(input.ownerId, \"ownerId\", 160);\n const createdAuthorityRef = capString(input.createdAuthorityRef, \"createdAuthorityRef\", 200);\n const memberIds = Array.from(new Set([ownerId, ...input.memberIds.map((id, index) =>\n capString(id, `memberIds[${index}]`, 160))]));\n if (memberIds.length > 100)\n throw new BrandInputError(\"a brand book supports at most 100 members\");\n return [\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: input.id,\n attrs: {\n id: input.id,\n version: 1,\n slug,\n name,\n status: \"draft\",\n ownerId,\n createdAuthorityRef,\n memberIds,\n activationRevision: 0,\n createdAt: input.now,\n updatedAt: input.now,\n ...(input.channelId ? { channelId: input.channelId } : {}),\n },\n },\n ];\n}\n\n// Patchable book columns, and which of them may be cleared with `null`\n// (required attrs can't be retracted — the final-state schema check fails).\nconst PATCHABLE = new Set([\"name\", \"status\", \"channelId\", \"summary\"]);\nconst CLEARABLE = new Set([\"channelId\", \"summary\"]);\n\nfunction validateBookField(key: string, value: unknown): unknown {\n switch (key) {\n case \"name\":\n return capString(value, \"name\", 120);\n case \"status\":\n if (typeof value !== \"string\" || !(BOOK_STATUSES as readonly string[]).includes(value))\n throw new BrandInputError(`status must be one of: ${BOOK_STATUSES.join(\", \")}`);\n return value as BookStatus;\n case \"channelId\":\n return capString(value, \"channelId\", 128);\n case \"summary\":\n return capString(value, \"summary\", 2000);\n default:\n return value;\n }\n}\n\n/**\n * Ops to patch a brand book. `null` means CLEAR (a `retract` op — odla-db has\n * no storable scalar null) and is only allowed on optional columns;\n * `undefined` keys are dropped. Any write stamps `updatedAt`; an empty\n * effective patch emits no ops at all.\n */\nexport function updateBookOps(\n bookId: BrandEntityRef,\n patch: Record<string, unknown>,\n now: number,\n): BrandOp[] {\n const attrs: BrandAttrs = {};\n const retract: string[] = [];\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) continue;\n if (!PATCHABLE.has(key)) throw new BrandInputError(`unknown book field: ${key}`);\n if (value === null) {\n if (!CLEARABLE.has(key)) throw new BrandInputError(`${key} is required and cannot be cleared`);\n retract.push(key);\n continue;\n }\n attrs[key] = validateBookField(key, value);\n }\n if (Object.keys(attrs).length === 0 && retract.length === 0) return [];\n const ops: BrandOp[] = [\n { t: \"update\", ns: BRAND_NS.book, id: bookId, attrs: { ...attrs, updatedAt: now } },\n ];\n if (retract.length > 0) ops.push({ t: \"retract\", ns: BRAND_NS.book, id: bookId, attrs: retract });\n return ops;\n}\n\n/** The child rows whose `audience` snapshots a roster change must rewrite.\n * Pass the rows you queried — the builder stays pure. */\nexport interface AudienceChildren {\n sections?: Array<{ id: string }>;\n palettes?: Array<{ id: string }>;\n proposals?: Array<{ id: string }>;\n assets?: Array<{ id: string }>;\n}\n\n/**\n * Ops to change a book's roster: rewrite `memberIds` (owner always kept) and\n * fan the new list out to every child row's denormalized `audience` snapshot.\n * Query the children first and pass them in — this builder does no I/O, so\n * tests can assert the exact fan-out.\n */\nexport function audienceFanoutOps(\n book: Pick<BrandBook, \"id\" | \"ownerId\">,\n newMemberIds: string[],\n children: AudienceChildren,\n now: number,\n): BrandOp[] {\n const memberIds = Array.from(new Set([book.ownerId, ...newMemberIds]));\n const ops: BrandOp[] = [\n { t: \"update\", ns: BRAND_NS.book, id: book.id, attrs: { memberIds, updatedAt: now } },\n ];\n const fan = (ns: string, rows?: Array<{ id: string }>) => {\n for (const row of rows ?? []) ops.push({ t: \"update\", ns, id: row.id, attrs: { audience: memberIds } });\n };\n fan(BRAND_NS.section, children.sections);\n fan(BRAND_NS.palette, children.palettes);\n fan(BRAND_NS.proposal, children.proposals);\n fan(BRAND_NS.asset, children.assets);\n return ops;\n}\n","// Pure op-builder for brand_section rows. One section per (book, kind),\n// upserted through a natural-key Lookup ref so re-writing the same section\n// binds to the same row (no read-modify-write race, idempotent installs).\nimport { BRAND_NS, SECTION_STATUSES, type SectionKind, type SectionStatus } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandOp, BrandProposal } from \"../types\";\nimport { assertSectionContent, capString } from \"../validate\";\n\n/** The natural key a section row is upserted by: `${bookId}:${kind}`. */\nexport function sectionKey(bookId: string, kind: SectionKind): string {\n return `${bookId}:${kind}`;\n}\n\n/** Input to {@link upsertSectionOps}. `audience` is the book's roster\n * snapshot; `status` defaults to `draft` (a human approves later). */\nexport interface UpsertSectionInput {\n bookId: string;\n kind: SectionKind;\n content: Record<string, unknown>;\n status?: SectionStatus;\n audience: string[];\n updatedBy: string;\n now: number;\n approvalReceiptId?: string;\n approvalActionDigest?: string;\n}\n\n/**\n * Ops to create-or-replace a book's section of one kind: a single `update`\n * addressed by the `{ ns, attr: \"key\", value }` Lookup ref, carrying the\n * validated + normalized content (see `assertSectionContent`), the audience\n * snapshot, and the author/timestamp.\n */\nexport function upsertSectionOps(input: UpsertSectionInput): BrandOp[] {\n const status = input.status ?? \"draft\";\n if (!(SECTION_STATUSES as readonly string[]).includes(status))\n throw new BrandInputError(`status must be one of: ${SECTION_STATUSES.join(\", \")}`);\n const content = assertSectionContent(input.kind, input.content);\n if (\n status === \"approved\" &&\n (!input.approvalReceiptId || !input.approvalActionDigest)\n ) throw new BrandInputError(\"approved sections require approval receipt provenance\");\n const key = sectionKey(input.bookId, input.kind);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.section,\n id: { ns: BRAND_NS.section, attr: \"key\", value: key },\n attrs: {\n key,\n bookId: input.bookId,\n kind: input.kind,\n status,\n content,\n audience: input.audience,\n updatedBy: input.updatedBy,\n updatedAt: input.now,\n ...(input.approvalReceiptId\n ? { approvalReceiptId: capString(input.approvalReceiptId, \"approvalReceiptId\", 200) }\n : {}),\n ...(input.approvalActionDigest\n ? { approvalActionDigest: capString(input.approvalActionDigest, \"approvalActionDigest\", 80) }\n : {}),\n },\n },\n {\n t: \"link\",\n ns: BRAND_NS.section,\n id: { ns: BRAND_NS.section, attr: \"key\", value: key },\n label: \"book\",\n target: input.bookId,\n },\n ];\n}\n\n/** Input for an agent-authored non-palette facet proposal. */\nexport interface ProposeSectionInput {\n id: string;\n bookId: string;\n kind: Exclude<SectionKind, \"palette\">;\n content: Record<string, unknown>;\n rationale: string;\n audience: string[];\n createdBy: string;\n createdAuthorityRef: string;\n sourceAsset?: BrandProposal[\"provenance\"][\"sourceAsset\"];\n messageId: string;\n turnId: string;\n taintLabels: string[];\n now: number;\n}\n\n/** Validate a facet draft and park it as an immutable OPEN proposal. */\nexport async function proposeSectionOps(input: ProposeSectionInput): Promise<BrandOp[]> {\n if (input.taintLabels.length > 16)\n throw new BrandInputError(\"taintLabels must have at most 16 entries\");\n const proposal = {\n id: input.id,\n bookId: input.bookId,\n kind: input.kind,\n status: \"open\" as const,\n payload: { content: assertSectionContent(input.kind, input.content) },\n rationale: capString(input.rationale, \"rationale\", 2000),\n provenance: {\n sourceAssetId: input.sourceAsset?.assetId ?? null,\n sourceAsset: input.sourceAsset ?? null,\n messageId: capString(input.messageId, \"messageId\", 200),\n turnId: capString(input.turnId, \"turnId\", 200),\n taintLabels: [...new Set(input.taintLabels.map((label, index) =>\n capString(label, `taintLabels[${index}]`, 120)))].sort(),\n },\n audience: input.audience,\n createdBy: input.createdBy,\n createdAuthorityRef: input.createdAuthorityRef,\n createdAt: input.now,\n };\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.id,\n attrs: { ...proposal, reviewDigest: await brandJsonDigest(proposal) },\n },\n { t: \"link\", ns: BRAND_NS.proposal, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n","// Pure op-builders for the palette proposal flow: the agent proposes, a\n// HUMAN accepts or rejects. Acceptance is one atomic transact — palette row,\n// approved palette section, the book's `activePaletteId`, and the proposal's\n// resolution — so a book can never point at a palette that wasn't written.\n//\n// Note on op kinds: the design doc says \"book merge {activePaletteId}\", but\n// odla-db's `merge` op deep-merges JSON attributes only (the engine rejects\n// it on scalars) — a scalar write on an existing row is an attr-merge\n// `update`, which is what these builders emit.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandOp, BrandProposal } from \"../types\";\nimport { assertHex, assertSwatches, capString } from \"../validate\";\nimport { upsertSectionOps } from \"./sections\";\n\n/** Input to {@link proposePaletteOps}. `audience` is the book's roster\n * snapshot; `contrastReport` is stored verbatim in the payload for the\n * human reviewer. */\nexport interface ProposePaletteInput {\n id: string;\n bookId: string;\n name: string;\n rationale: string;\n swatches: unknown;\n seedHex?: string;\n contrastReport?: unknown;\n createdBy: string;\n createdAuthorityRef: string;\n audience: string[];\n sourceAsset?: BrandProposal[\"provenance\"][\"sourceAsset\"];\n messageId: string;\n turnId: string;\n taintLabels: string[];\n now: number;\n}\n\n/**\n * Ops to park a palette proposal for human review: one `brand_proposal` row,\n * `kind: \"palette\"`, `status: \"open\"`, with the validated swatches (and\n * optional seed/contrast report) in `payload`.\n */\nexport async function proposePaletteOps(input: ProposePaletteInput): Promise<BrandOp[]> {\n const name = capString(input.name, \"name\", 120);\n const rationale = capString(input.rationale, \"rationale\", 2000);\n const swatches = assertSwatches(input.swatches);\n const seedHex = input.seedHex === undefined ? undefined : assertHex(input.seedHex, \"seedHex\");\n if (input.taintLabels.length > 16)\n throw new BrandInputError(\"taintLabels must have at most 16 entries\");\n const payload: Record<string, unknown> = {\n name,\n swatches,\n ...(seedHex ? { seedHex } : {}),\n ...(input.contrastReport !== undefined ? { contrastReport: input.contrastReport } : {}),\n };\n const proposal = {\n id: input.id,\n bookId: input.bookId,\n kind: \"palette\" as const,\n status: \"open\" as const,\n payload,\n rationale,\n provenance: {\n sourceAssetId: input.sourceAsset?.assetId ?? null,\n sourceAsset: input.sourceAsset ?? null,\n messageId: capString(input.messageId, \"messageId\", 200),\n turnId: capString(input.turnId, \"turnId\", 200),\n taintLabels: [...new Set(input.taintLabels.map((label, index) =>\n capString(label, `taintLabels[${index}]`, 120)))].sort(),\n },\n audience: input.audience,\n createdBy: input.createdBy,\n createdAuthorityRef: input.createdAuthorityRef,\n createdAt: input.now,\n };\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.id,\n attrs: { ...proposal, reviewDigest: await brandJsonDigest(proposal) },\n },\n { t: \"link\", ns: BRAND_NS.proposal, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n\n/** Input to {@link acceptProposalOps}: the proposal row as read back, the id\n * to mint the palette under, and who resolved it. */\nexport interface AcceptProposalInput {\n proposal: BrandProposal;\n paletteId: string;\n resolvedBy: string;\n approvalReceiptId: string;\n approvalActionDigest: string;\n now: number;\n resolutionNote?: string;\n}\n\n/**\n * Ops to accept an OPEN palette proposal, all in one transact:\n * 1. the `brand_palette` row (source: `extracted` when the proposal came from\n * an asset, `derived` when seeded, else `manual`),\n * 2. the approved `palette` section upsert,\n * 3. the book's `activePaletteId` pointer,\n * 4. the proposal flipped to `accepted` with resolver + timestamp.\n * Throws on a non-palette or already-resolved proposal, or a payload that no\n * longer validates.\n */\nexport function acceptProposalOps(input: AcceptProposalInput): BrandOp[] {\n const {\n proposal,\n paletteId,\n resolvedBy,\n approvalReceiptId,\n approvalActionDigest,\n now,\n } = input;\n if (proposal.kind !== \"palette\")\n throw new BrandInputError(`proposal ${proposal.id} is a ${proposal.kind} proposal, not a palette`);\n if (proposal.status !== \"open\")\n throw new BrandInputError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n const payload = proposal.payload;\n const name = capString(payload.name, \"payload.name\", 120);\n const swatches = assertSwatches(payload.swatches);\n const seedHex = payload.seedHex === undefined ? undefined : assertHex(payload.seedHex, \"payload.seedHex\");\n const source = proposal.provenance.sourceAsset ? \"extracted\" : seedHex ? \"derived\" : \"manual\";\n return [\n {\n t: \"update\",\n ns: BRAND_NS.palette,\n id: paletteId,\n attrs: {\n id: paletteId,\n bookId: proposal.bookId,\n name,\n status: \"active\",\n swatches,\n source,\n rationale: proposal.rationale,\n proposalId: proposal.id,\n approvalReceiptId: capString(approvalReceiptId, \"approvalReceiptId\", 200),\n approvalActionDigest: capString(\n approvalActionDigest,\n \"approvalActionDigest\",\n 80,\n ),\n audience: proposal.audience,\n createdAt: now,\n updatedAt: now,\n ...(seedHex ? { seedHex } : {}),\n },\n },\n { t: \"link\", ns: BRAND_NS.palette, id: paletteId, label: \"book\", target: proposal.bookId },\n ...upsertSectionOps({\n bookId: proposal.bookId,\n kind: \"palette\",\n content: { paletteId, name, swatches },\n status: \"approved\",\n audience: proposal.audience,\n updatedBy: resolvedBy,\n approvalReceiptId,\n approvalActionDigest,\n now,\n }),\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: proposal.bookId,\n attrs: { activePaletteId: paletteId, updatedAt: now },\n },\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: proposal.id,\n attrs: {\n status: \"accepted\",\n resolvedBy,\n resolvedAt: now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n}\n\n/** Input to {@link rejectProposalOps}. */\nexport interface RejectProposalInput {\n proposal: BrandProposal;\n resolvedBy: string;\n now: number;\n resolutionNote?: string;\n}\n\n/**\n * Ops to reject an OPEN proposal (any kind): flip it to `rejected` with\n * resolver, timestamp, and the optional note. Nothing else is touched — the\n * proposal row itself is the audit trail.\n */\nexport function rejectProposalOps(input: RejectProposalInput): BrandOp[] {\n const { proposal, resolvedBy, now } = input;\n if (proposal.status !== \"open\")\n throw new BrandInputError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: proposal.id,\n attrs: {\n status: \"rejected\",\n resolvedBy,\n resolvedAt: now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n}\n","// Pure op-builders for brand_asset rows. Asset rows are worker-mediated\n// (rules deny everything): the caller uploads to storage FIRST, then commits\n// the mirroring row — and \"delete\" is a `deletedAt` tombstone (an attr-merge\n// `update`; odla-db's `merge` op is json-only), never a row delete, so\n// analyses and proposals that reference the asset stay coherent.\nimport { ASSET_KINDS, BRAND_NS, DESIGN_ASSET_KIND, type AssetKind } from \"../constants\";\nimport type { DesignDigest } from \"../design/types\";\nimport { BrandInputError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type { BrandEntityRef, BrandOp } from \"../types\";\nimport { assertAnalysis, assertAssetContentType, capString } from \"../validate\";\n\n/** Input to {@link createAssetOps} — the storage upload's receipt fields\n * (`path`/`size`) plus the declared kind and the book's audience. */\nexport interface CreateAssetInput {\n id: string;\n bookId: string;\n kind: AssetKind;\n path: string;\n storageObjectId: string;\n contentDigest: string;\n contentType: string;\n size: number;\n uploadedBy: string;\n uploadedAuthorityRef: string;\n audience: string[];\n title?: string;\n /** `design` kind only: the digest parsed from the uploaded bundle. */\n design?: DesignDigest;\n now: number;\n}\n\n/**\n * Ops to record one uploaded asset: a single `brand_asset` row mirroring the\n * storage object, with the content type re-checked against the allowlist and\n * the size required to be a positive byte count.\n */\nexport function createAssetOps(input: CreateAssetInput): BrandOp[] {\n if (!(ASSET_KINDS as readonly string[]).includes(input.kind))\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n const contentType = assertAssetContentType(input.contentType, input.kind);\n // The digest and the kind are two halves of one fact; letting them\n // disagree would leave an HTML asset no tool can read, or a digest\n // attached to a PNG.\n if (input.kind === DESIGN_ASSET_KIND && input.design === undefined)\n throw new BrandInputError(\"a design asset must carry its parsed digest\");\n if (input.kind !== DESIGN_ASSET_KIND && input.design !== undefined)\n throw new BrandInputError(`only ${DESIGN_ASSET_KIND} assets may carry a design digest`);\n if (typeof input.size !== \"number\" || !Number.isFinite(input.size) || input.size <= 0)\n throw new BrandInputError(\"size must be a positive byte count\");\n if (!/^sha256:[0-9a-f]{64}$/.test(input.contentDigest))\n throw new BrandInputError(\"contentDigest must be a SHA-256 digest\");\n const title = input.title === undefined ? undefined : capString(input.title, \"title\", 160);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.asset,\n id: input.id,\n attrs: {\n id: input.id,\n bookId: input.bookId,\n kind: input.kind,\n path: capString(input.path, \"path\", 512),\n storageObjectId: capString(input.storageObjectId, \"storageObjectId\", 200),\n contentDigest: capString(input.contentDigest, \"contentDigest\", 80),\n contentType,\n size: input.size,\n status: \"live\",\n analysisRevision: 0,\n audience: input.audience,\n uploadedBy: input.uploadedBy,\n uploadedAuthorityRef: capString(\n input.uploadedAuthorityRef,\n \"uploadedAuthorityRef\",\n 200,\n ),\n createdAt: input.now,\n ...(title ? { title } : {}),\n ...(input.design ? { design: input.design } : {}),\n },\n },\n { t: \"link\", ns: BRAND_NS.asset, id: input.id, label: \"book\", target: input.bookId },\n ];\n}\n\n/**\n * Ops to tombstone an asset after its storage object was deleted: stamp\n * `deletedAt` in place. List reads exclude tombstoned rows; the row itself\n * stays for provenance.\n */\nexport function beginAssetDeleteOps(\n assetId: BrandEntityRef,\n now: number,\n deletedBy: string,\n deletedAuthorityRef: string,\n): BrandOp[] {\n return [{\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: {\n status: \"deleting\",\n deletedAt: now,\n deletedBy: capString(deletedBy, \"deletedBy\", 160),\n deletedAuthorityRef: capString(deletedAuthorityRef, \"deletedAuthorityRef\", 200),\n },\n }];\n}\n\n/** Complete a previously authorized deletion after storage is tombstoned. */\nexport function finishAssetDeleteOps(assetId: BrandEntityRef): BrandOp[] {\n return [{\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: { status: \"deleted\" },\n }];\n}\n\n/**\n * Ops to record an agent's analysis of an asset: the validated + capped\n * analysis json plus `analyzedAt`. Replaces any prior analysis whole.\n */\nexport async function recordAnalysisOps(\n assetId: BrandEntityRef,\n analysis: unknown,\n priorRevision: number,\n analyzedBy: string,\n analyzedAuthorityRef: string,\n now: number,\n): Promise<BrandOp[]> {\n if (!Number.isSafeInteger(priorRevision) || priorRevision < 0)\n throw new BrandInputError(\"prior analysis revision must be a non-negative integer\");\n const normalized = assertAnalysis(analysis);\n return [\n {\n t: \"update\",\n ns: BRAND_NS.asset,\n id: assetId,\n attrs: {\n analysis: normalized,\n analysisRevision: priorRevision + 1,\n analysisDigest: await brandJsonDigest(normalized),\n analyzedBy: capString(analyzedBy, \"analyzedBy\", 160),\n analyzedAuthorityRef: capString(\n analyzedAuthorityRef,\n \"analyzedAuthorityRef\",\n 200,\n ),\n analyzedAt: now,\n },\n },\n ];\n}\n","// Parser for the Claude Design standalone-HTML bundle format.\n//\n// Scanning is deliberately indexOf-based rather than regex-based: a bundle is\n// routinely megabytes of base64 on a single line, where a `[\\s\\S]*?` pattern\n// is both slow and a backtracking risk. Every scan here is linear.\n//\n// Asset PAYLOADS are never decoded — only measured. A manifest entry's byte\n// length is derived from its base64 length, so parsing a 30 MB bundle costs\n// one JSON.parse and no binary allocation.\nimport { BrandInputError } from \"../errors\";\nimport type { DesignBundle, DesignBundleAsset } from \"./types\";\n\n/** Longest poster SVG carried into a digest; larger ones are dropped. */\nexport const MAX_THUMBNAIL_CHARS = 16_384;\n\nconst ISLAND_TYPES = [\"manifest\", \"ext_resources\", \"page_order\", \"template\"] as const;\ntype IslandType = (typeof ISLAND_TYPES)[number];\n\n/** Extract one `<script type=\"__bundler/NAME\">` island's raw text. */\nfunction island(html: string, name: IslandType): string | null {\n const open = `<script type=\"__bundler/${name}\">`;\n const start = html.indexOf(open);\n if (start < 0) return null;\n const from = start + open.length;\n const end = html.indexOf(\"</script>\", from);\n return end < 0 ? null : html.slice(from, end);\n}\n\n/**\n * Cheap structural sniff: does this text look like a Claude Design bundle?\n * Checks for the two islands that carry the design itself, so a plain HTML\n * page (or an unrelated file that happens to be HTML) is rejected before any\n * parsing work happens.\n */\nexport function isDesignBundle(html: string): boolean {\n return (\n html.includes('<script type=\"__bundler/manifest\">') &&\n html.includes('<script type=\"__bundler/template\">')\n );\n}\n\n/** Decoded byte length of a base64 payload, without decoding it. */\nexport function base64ByteLength(data: string): number {\n const len = data.length;\n if (len === 0) return 0;\n const pad = data.endsWith(\"==\") ? 2 : data.endsWith(\"=\") ? 1 : 0;\n return Math.max(0, Math.floor((len * 3) / 4) - pad);\n}\n\nfunction parseIslandJson(text: string, name: IslandType): unknown {\n try {\n return JSON.parse(text);\n } catch {\n throw new BrandInputError(`design bundle's ${name} island is not valid JSON`);\n }\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Manifest object → payload-free asset summaries, in manifest order. */\nfunction readAssets(raw: unknown): DesignBundleAsset[] {\n if (!isRecord(raw)) throw new BrandInputError(\"design bundle's manifest island must be an object\");\n const assets: DesignBundleAsset[] = [];\n for (const [uuid, value] of Object.entries(raw)) {\n if (!isRecord(value)) continue;\n const data = value.data;\n const mime = value.mime;\n if (typeof data !== \"string\" || typeof mime !== \"string\") continue;\n assets.push({\n uuid,\n mime: mime.slice(0, 120),\n bytes: base64ByteLength(data),\n compressed: value.compressed === true,\n });\n }\n return assets;\n}\n\n/** ext_resources array → the CDN URLs the design was authored against. */\nfunction readExternals(raw: unknown): string[] {\n if (raw === null || raw === undefined) return [];\n if (!Array.isArray(raw))\n throw new BrandInputError(\"design bundle's ext_resources island must be an array\");\n const out: string[] = [];\n for (const entry of raw) {\n if (isRecord(entry) && typeof entry.id === \"string\") out.push(entry.id.slice(0, 512));\n }\n return out;\n}\n\n/** page_order array → nested page-bundle uuids. */\nfunction readPageOrder(raw: unknown): string[] {\n if (raw === null || raw === undefined) return [];\n if (!Array.isArray(raw))\n throw new BrandInputError(\"design bundle's page_order island must be an array\");\n return raw.filter((v): v is string => typeof v === \"string\");\n}\n\n/**\n * The loader's poster: the `<svg>` inside `#__bundler_thumbnail`. It renders\n * with no JavaScript and no blob URLs, so it is the one part of a design that\n * can be shown anywhere. Returns undefined when absent or over\n * {@link MAX_THUMBNAIL_CHARS}.\n */\nexport function extractThumbnailSvg(html: string): string | undefined {\n const anchor = html.indexOf(\"__bundler_thumbnail\");\n if (anchor < 0) return undefined;\n const open = html.indexOf(\"<svg\", anchor);\n if (open < 0) return undefined;\n const close = html.indexOf(\"</svg>\", open);\n if (close < 0) return undefined;\n const svg = html.slice(open, close + \"</svg>\".length);\n return svg.length > MAX_THUMBNAIL_CHARS ? undefined : svg;\n}\n\n/** One manifest entry WITH its base64 payload. */\nexport interface DesignManifestEntry {\n mime: string;\n compressed: boolean;\n /** Base64 payload, gzipped first when `compressed`. */\n data: string;\n}\n\n/**\n * Read the manifest island's entries INCLUDING their payloads, keyed by uuid.\n *\n * Everything else in this module deliberately leaves payloads encoded and\n * only measures them, because the worker never needs the bytes. This is the\n * one exception, for callers that genuinely write assets out — the CLI's\n * `brand design unpack`. It holds the whole manifest in memory, so use it\n * only where that is affordable.\n */\nexport function readDesignManifest(html: string): Record<string, DesignManifestEntry> {\n const raw = island(html, \"manifest\");\n if (raw === null) throw new BrandInputError(\"design bundle has no manifest island\");\n const parsed = parseIslandJson(raw, \"manifest\");\n if (!isRecord(parsed)) throw new BrandInputError(\"design bundle's manifest island must be an object\");\n const out: Record<string, DesignManifestEntry> = {};\n for (const [uuid, value] of Object.entries(parsed)) {\n if (!isRecord(value)) continue;\n const { data, mime } = value;\n if (typeof data !== \"string\" || typeof mime !== \"string\") continue;\n out[uuid] = { mime, compressed: value.compressed === true, data };\n }\n return out;\n}\n\n/**\n * Parse a Claude Design standalone-HTML export into its parts: the real\n * document (JSON-decoded from the template island), payload-free manifest\n * summaries, the external-resource index, nested page uuids, and the poster\n * SVG.\n *\n * Throws {@link BrandInputError} when the text is not a bundle or an island\n * is malformed — the messages are safe to return to a caller as a 400.\n */\nexport function parseDesignBundle(html: string): DesignBundle {\n if (!isDesignBundle(html))\n throw new BrandInputError(\n \"not a Claude Design bundle: no __bundler/manifest and __bundler/template script islands. \" +\n \"Export the design as standalone HTML and upload that file.\",\n );\n const templateRaw = island(html, \"template\");\n if (templateRaw === null)\n throw new BrandInputError(\"design bundle's template island is unterminated\");\n const template = parseIslandJson(templateRaw, \"template\");\n if (typeof template !== \"string\")\n throw new BrandInputError(\"design bundle's template island must be a JSON string\");\n\n const manifestRaw = island(html, \"manifest\");\n if (manifestRaw === null)\n throw new BrandInputError(\"design bundle's manifest island is unterminated\");\n\n const extRaw = island(html, \"ext_resources\");\n const pageRaw = island(html, \"page_order\");\n const thumbnailSvg = extractThumbnailSvg(html);\n return {\n template,\n assets: readAssets(parseIslandJson(manifestRaw, \"manifest\")),\n externals: readExternals(extRaw === null ? null : parseIslandJson(extRaw, \"ext_resources\")),\n pageOrder: readPageOrder(pageRaw === null ? null : parseIslandJson(pageRaw, \"page_order\")),\n ...(thumbnailSvg ? { thumbnailSvg } : {}),\n };\n}\n","// A small, linear CSS scanner — enough to read custom-property declarations\n// out of a design's stylesheets, and nothing more.\n//\n// This is NOT a CSS parser and does not try to be one. It answers one\n// question: which `--name: value` declarations does this document make, on\n// document-level selectors, in cascade order. That is all the token\n// extractor needs, and a real parser would be a dependency this\n// zero-dependency package does not take.\n//\n// Known limits (documented rather than papered over): specificity is not\n// modelled — declarations are applied in document order, last one wins,\n// which matches how token sheets are actually authored (a base tier, then\n// theme overrides). Comment stripping is textual, so a `/*` inside a string\n// literal would confuse it; token sheets do not contain those.\n\n/** One declaration the scanner found, with the selectors it was nested in. */\nexport interface ScannedDeclaration {\n /** Outermost → innermost selector/at-rule preludes. */\n selectors: string[];\n /** Property name, including the leading `--`. */\n name: string;\n /** Declaration value, trimmed, with comments already removed. */\n value: string;\n}\n\n/** Remove `/* … *​/` comments so they cannot break declaration splitting. */\nexport function stripCssComments(css: string): string {\n let out = \"\";\n let i = 0;\n for (;;) {\n const start = css.indexOf(\"/*\", i);\n if (start < 0) return out + css.slice(i);\n out += css.slice(i, start);\n const end = css.indexOf(\"*/\", start + 2);\n if (end < 0) return out;\n i = end + 2;\n }\n}\n\n/**\n * Concatenate every `<style>` element's text in document order. Designs ship\n * their theme as a sequence of style blocks (a vendored base tier, then\n * overrides), and the cascade between them is exactly this order.\n */\nexport function styleSheetText(html: string): string {\n const parts: string[] = [];\n let i = 0;\n for (;;) {\n const open = html.indexOf(\"<style\", i);\n if (open < 0) break;\n const gt = html.indexOf(\">\", open);\n if (gt < 0) break;\n const close = html.indexOf(\"</style>\", gt);\n if (close < 0) break;\n parts.push(html.slice(gt + 1, close));\n i = close + \"</style>\".length;\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * Walk `css` and yield every custom-property declaration with its enclosing\n * selector stack, in document order. Brace and paren depth are tracked so\n * nested at-rules (`@media { :root { … } }`) and parenthesised values\n * (`color-mix(in srgb, …)`) are handled correctly.\n *\n * Only `--*` declarations are reported; ordinary properties are skipped.\n */\nexport function scanCustomProperties(css: string): ScannedDeclaration[] {\n const text = stripCssComments(css);\n const found: ScannedDeclaration[] = [];\n const stack: string[] = [];\n let paren = 0;\n let start = 0;\n\n const flush = (end: number): void => {\n if (stack.length === 0) return;\n const chunk = text.slice(start, end).trim();\n if (!chunk.startsWith(\"--\")) return;\n const colon = chunk.indexOf(\":\");\n if (colon < 0) return;\n const name = chunk.slice(0, colon).trim();\n if (name.length < 3) return;\n found.push({ selectors: [...stack], name, value: chunk.slice(colon + 1).trim() });\n };\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (ch === \"(\") paren++;\n else if (ch === \")\") paren = Math.max(0, paren - 1);\n if (paren !== 0) continue;\n if (ch === \"{\") {\n stack.push(text.slice(start, i).trim());\n start = i + 1;\n } else if (ch === \"}\") {\n flush(i);\n stack.pop();\n start = i + 1;\n } else if (ch === \";\") {\n flush(i);\n start = i + 1;\n }\n }\n return found;\n}\n","// Hex color parsing and formatting.\n//\n// Accepts the CSS `#rgb` and `#rrggbb` forms (case-insensitive, surrounding\n// whitespace tolerated) and normalizes to lowercase `#rrggbb`. Alpha forms\n// (`#rgba` / `#rrggbbaa`) are rejected on purpose: the brand color engine\n// works in opaque colors only — translucency is expressed downstream by the\n// token compiler via `color-mix()` strings, never baked into swatches.\n//\n// Errors are plain RangeError so the color engine stays dependency-free;\n// the package's validate layer wraps them in BrandInputError where a typed\n// HTTP-facing error is needed.\n\n/** An sRGB color with channels as fractions in [0, 1]. */\nexport interface Rgb {\n /** Red channel, 0..1. */\n r: number;\n /** Green channel, 0..1. */\n g: number;\n /** Blue channel, 0..1. */\n b: number;\n}\n\n/** Clamps a number into [0, 1]; NaN clamps to 0. */\nexport function clamp01(x: number): number {\n return Number.isNaN(x) ? 0 : x < 0 ? 0 : x > 1 ? 1 : x;\n}\n\nconst HEX3 = /^#[0-9a-f]{3}$/;\nconst HEX6 = /^#[0-9a-f]{6}$/;\nconst HEX_ALPHA = /^#([0-9a-f]{4}|[0-9a-f]{8})$/;\n\n/**\n * Parses `#rgb` or `#rrggbb` (case-insensitive) into channel fractions.\n *\n * @throws RangeError for anything else — named colors, missing `#`, wrong\n * digit counts; alpha forms (`#rgba`/`#rrggbbaa`) get a dedicated message.\n */\nexport function parseHex(hex: string): Rgb {\n const s = hex.trim().toLowerCase();\n if (HEX_ALPHA.test(s)) {\n throw new RangeError(\n `parseHex: alpha hex \"${hex}\" is not supported — use an opaque \"#rrggbb\" value`,\n );\n }\n if (HEX3.test(s)) {\n return {\n r: parseInt(s[1]! + s[1]!, 16) / 255,\n g: parseInt(s[2]! + s[2]!, 16) / 255,\n b: parseInt(s[3]! + s[3]!, 16) / 255,\n };\n }\n if (HEX6.test(s)) {\n return {\n r: parseInt(s.slice(1, 3), 16) / 255,\n g: parseInt(s.slice(3, 5), 16) / 255,\n b: parseInt(s.slice(5, 7), 16) / 255,\n };\n }\n throw new RangeError(`parseHex: expected \"#rgb\" or \"#rrggbb\", got \"${hex}\"`);\n}\n\n/** Formats channel fractions as lowercase `#rrggbb`, clamping each into [0, 1]. */\nexport function toHex(rgb: Rgb): string {\n const ch = (c: number): string =>\n Math.round(clamp01(c) * 255)\n .toString(16)\n .padStart(2, \"0\");\n return `#${ch(rgb.r)}${ch(rgb.g)}${ch(rgb.b)}`;\n}\n\n/** Normalizes any accepted hex form to lowercase `#rrggbb` (throws like parseHex). */\nexport function normalizeHex(hex: string): string {\n return toHex(parseHex(hex));\n}\n","// Color space conversions: sRGB ↔ HSL, sRGB ↔ linear-light, sRGB ↔ OKLab,\n// OKLab ↔ OKLCH — plus an sRGB gamut clamp that reduces OKLCH chroma while\n// preserving lightness and hue.\n//\n// Algorithm sources:\n// - sRGB transfer function: IEC 61966-2-1 (electro-optical form: c ≤ 0.04045\n// → c/12.92, else ((c+0.055)/1.055)^2.4), as restated in CSS Color 4.\n// - HSL: CSS Color 4 § 7 (the hue-sextant algorithm inherited from CSS3\n// Color § 4.2.4).\n// - OKLab: Björn Ottosson, \"A perceptual color space for image processing\"\n// (bottosson.github.io/posts/oklab, 2020; sRGB matrices as updated\n// 2021-01-25): linear sRGB → LMS via M1, per-component cube root, → OKLab\n// via M2, and his published inverse matrices for the way back.\n// - OKLCH: CSS Color 4 § 9.2 — the polar form of OKLab (C = chroma radius,\n// h = hue angle in degrees).\n\nimport { clamp01, parseHex, toHex, type Rgb } from \"./hex\";\n\n/** A color in HSL: hue in degrees [0, 360), saturation and lightness 0..1. */\nexport interface Hsl {\n /** Hue angle in degrees, [0, 360); 0 when achromatic. */\n h: number;\n /** Saturation, 0..1. */\n s: number;\n /** Lightness, 0..1. */\n l: number;\n}\n\n/** A color in OKLab: L 0..1, a/b roughly within ±0.4 for sRGB colors. */\nexport interface Oklab {\n /** Perceived lightness, 0..1. */\n L: number;\n /** Green–red axis. */\n a: number;\n /** Blue–yellow axis. */\n b: number;\n}\n\n/** A color in OKLCH — OKLab in polar form. */\nexport interface Oklch {\n /** Perceived lightness, 0..1. */\n L: number;\n /** Chroma (radius in the a/b plane), ≥ 0. */\n C: number;\n /** Hue angle in degrees, [0, 360); 0 when achromatic. */\n h: number;\n}\n\n/** IEC 61966-2-1 sRGB decoding: gamma-encoded channel → linear-light, both 0..1. */\nexport function srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\n/** IEC 61966-2-1 sRGB encoding: linear-light channel → gamma-encoded, both 0..1. */\nexport function linearToSrgb(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;\n}\n\n/** Converts sRGB channel fractions to HSL (CSS Color 4 § 7). */\nexport function rgbToHsl({ r, g, b }: Rgb): Hsl {\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d === 0) return { h: 0, s: 0, l };\n const s = d / (1 - Math.abs(2 * l - 1));\n let h: number;\n if (max === r) h = 60 * (((g - b) / d) % 6);\n else if (max === g) h = 60 * ((b - r) / d + 2);\n else h = 60 * ((r - g) / d + 4);\n return { h: (h + 360) % 360, s, l };\n}\n\n/** Converts HSL to sRGB channel fractions (CSS Color 4 § 7; any hue angle accepted). */\nexport function hslToRgb({ h, s, l }: Hsl): Rgb {\n const hue = ((h % 360) + 360) % 360;\n const c = (1 - Math.abs(2 * l - 1)) * s;\n const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = l - c / 2;\n const sextants: ReadonlyArray<readonly [number, number, number]> = [\n [c, x, 0],\n [x, c, 0],\n [0, c, x],\n [0, x, c],\n [x, 0, c],\n [c, 0, x],\n ];\n const [r, g, b] = sextants[Math.floor(hue / 60) % 6]!;\n return { r: r + m, g: g + m, b: b + m };\n}\n\n/** Converts gamma-encoded sRGB to OKLab (Ottosson M1 → cbrt → M2). */\nexport function rgbToOklab({ r, g, b }: Rgb): Oklab {\n const R = srgbToLinear(r);\n const G = srgbToLinear(g);\n const B = srgbToLinear(b);\n const l = Math.cbrt(0.4122214708 * R + 0.5363325363 * G + 0.0514459929 * B);\n const m = Math.cbrt(0.2119034982 * R + 0.6806995451 * G + 0.1073969566 * B);\n const s = Math.cbrt(0.0883024619 * R + 0.2817188376 * G + 0.6299787005 * B);\n return {\n L: 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n a: 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n b: 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n };\n}\n\n/**\n * Converts OKLab to gamma-encoded sRGB (Ottosson's inverse matrices).\n * Out-of-gamut inputs yield channels outside [0, 1] — feed the OKLCH form\n * through {@link clampToGamut} first when hue fidelity matters (toHex would\n * clip per channel, which distorts hue).\n */\nexport function oklabToRgb({ L, a, b }: Oklab): Rgb {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return {\n r: linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),\n g: linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),\n b: linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),\n };\n}\n\n/** OKLab → OKLCH (polar form). Hue is 0 for achromatic colors (C ≈ 0). */\nexport function oklabToOklch({ L, a, b }: Oklab): Oklch {\n const C = Math.hypot(a, b);\n const h = C < 1e-9 ? 0 : ((Math.atan2(b, a) * 180) / Math.PI + 360) % 360;\n return { L, C, h };\n}\n\n/** OKLCH → OKLab (rectangular form). */\nexport function oklchToOklab({ L, C, h }: Oklch): Oklab {\n const rad = (h * Math.PI) / 180;\n return { L, a: C * Math.cos(rad), b: C * Math.sin(rad) };\n}\n\n/** Convenience: hex → OKLCH (throws like parseHex on bad input). */\nexport function hexToOklch(hex: string): Oklch {\n return oklabToOklch(rgbToOklab(parseHex(hex)));\n}\n\n/**\n * Convenience: OKLCH → lowercase `#rrggbb`. Out-of-gamut input is clipped\n * per channel by toHex; call {@link clampToGamut} first to reduce chroma\n * instead (preserving hue) when the input may be out of gamut.\n */\nexport function oklchToHex(lch: Oklch): string {\n return toHex(oklabToRgb(oklchToOklab(lch)));\n}\n\nconst GAMUT_EPS = 1e-6;\n\n/** True when every sRGB channel is within [0, 1] (tiny epsilon for float noise). */\nexport function inSrgbGamut({ r, g, b }: Rgb): boolean {\n const ok = (c: number): boolean => c >= -GAMUT_EPS && c <= 1 + GAMUT_EPS;\n return ok(r) && ok(g) && ok(b);\n}\n\n/**\n * Brings an OKLCH color into the sRGB gamut by reducing chroma only —\n * lightness and hue are preserved exactly (binary search, 24 iterations,\n * chroma precision well under one 8-bit quantum). L is clamped into [0, 1]\n * first; C = 0 (a pure gray) is always representable, so the search always\n * lands in gamut.\n */\nexport function clampToGamut(lch: Oklch): Oklch {\n const L = clamp01(lch.L);\n const h = lch.h;\n if (inSrgbGamut(oklabToRgb(oklchToOklab({ L, C: lch.C, h })))) return { L, C: lch.C, h };\n let lo = 0;\n let hi = lch.C;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (inSrgbGamut(oklabToRgb(oklchToOklab({ L, C: mid, h })))) lo = mid;\n else hi = mid;\n }\n return { L, C: lo, h };\n}\n","// WCAG 2.1 contrast — relative luminance, contrast ratio, and AA/AAA checks\n// per technique G18 and success criteria 1.4.3 / 1.4.6 / 1.4.11.\n//\n// relativeLuminance: Y = 0.2126·R + 0.7152·G + 0.0722·B over linear-light\n// sRGB channels. Channels are linearized with the IEC 61966-2-1 constant\n// (0.04045) rather than WCAG's 0.03928; the two never disagree for 8-bit\n// channel values (no n/255 falls between them) and CSS Color 4 standardizes\n// on 0.04045.\n// contrastRatio: (L1 + 0.05) / (L2 + 0.05) with the lighter luminance on\n// top — white on black is exactly 21:1, a color against itself 1:1.\n\nimport { parseHex } from \"./hex\";\nimport { srgbToLinear } from \"./convert\";\n\n/** Contrast contexts with distinct WCAG thresholds. */\nexport type ContrastKind = \"text\" | \"large-text\" | \"ui\";\n\n/** WCAG 2.1 relative luminance of a hex color: 0 = black, 1 = white. */\nexport function relativeLuminance(hex: string): number {\n const { r, g, b } = parseHex(hex);\n return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);\n}\n\n/** WCAG 2.1 contrast ratio between two hex colors, in [1, 21]; order-independent. */\nexport function contrastRatio(hexA: string, hexB: string): number {\n const la = relativeLuminance(hexA);\n const lb = relativeLuminance(hexB);\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\nconst AA: Record<ContrastKind, number> = { text: 4.5, \"large-text\": 3, ui: 3 };\nconst AAA: Record<Exclude<ContrastKind, \"ui\">, number> = { text: 7, \"large-text\": 4.5 };\n\n/**\n * WCAG 2.1 level-AA check for a contrast ratio: 4.5:1 for body text\n * (SC 1.4.3), 3:1 for large text, 3:1 for UI components and graphical\n * objects (SC 1.4.11).\n */\nexport function meetsAA(ratio: number, kind: ContrastKind = \"text\"): boolean {\n return ratio >= AA[kind];\n}\n\n/**\n * WCAG 2.1 level-AAA check for a contrast ratio (SC 1.4.6): 7:1 for body\n * text, 4.5:1 for large text. WCAG defines no AAA bar for non-text UI, so\n * \"ui\" is not an accepted kind here.\n */\nexport function meetsAAA(ratio: number, kind: Exclude<ContrastKind, \"ui\"> = \"text\"): boolean {\n return ratio >= AAA[kind];\n}\n\n/**\n * Default {@link pickTextOn} candidates: white and a near-black chosen so\n * that the better of the two clears 4.5:1 against ANY background. The worst\n * case is a mid-gray backdrop (luminance ≈ 0.18), where this pair still\n * yields ≈ 4.51:1; a softer near-black (e.g. #111111) would drop that floor\n * below 4.5.\n */\nexport const PICK_TEXT_DEFAULT_CANDIDATES: readonly string[] = [\"#ffffff\", \"#050505\"];\n\n/**\n * Picks the candidate with the highest contrast ratio against `bgHex`\n * (earliest candidate wins ties). With the default candidates the winner is\n * always ≥ 4.5:1 — see {@link PICK_TEXT_DEFAULT_CANDIDATES}.\n *\n * @throws RangeError when `candidates` is empty.\n */\nexport function pickTextOn(\n bgHex: string,\n candidates: readonly string[] = PICK_TEXT_DEFAULT_CANDIDATES,\n): string {\n if (candidates.length === 0) throw new RangeError(\"pickTextOn: candidates must be non-empty\");\n let best = candidates[0]!;\n let bestRatio = -1;\n for (const candidate of candidates) {\n const ratio = contrastRatio(bgHex, candidate);\n if (ratio > bestRatio) {\n best = candidate;\n bestRatio = ratio;\n }\n }\n return best;\n}\n","// Classic color-harmony companions, computed as OKLCH hue rotations at\n// constant lightness and chroma so companions keep the seed's perceived\n// lightness and vividness (the same rotations in HSL shift both wildly —\n// compare HSL yellow vs blue at \"50%\"). Results are chroma-clamped into the\n// sRGB gamut, which preserves hue and lightness exactly.\n//\n// Angles follow the traditional color-wheel definitions: complementary 180°,\n// analogous ±30°, triadic ±120°, split-complementary ±150°, tetradic\n// (square) +90°/180°/270°. Hue math per CSS Color 4 § 9.2 OKLCH.\n\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\n\n/**\n * Rotates a color's OKLCH hue by `degrees` (any sign/magnitude), keeping\n * lightness and chroma constant, then chroma-clamps into sRGB. Rotating an\n * achromatic color is a no-op up to 8-bit rounding (its chroma is ~0).\n */\nexport function rotateHue(hex: string, degrees: number): string {\n const { L, C, h } = hexToOklch(hex);\n return oklchToHex(clampToGamut({ L, C, h: (((h + degrees) % 360) + 360) % 360 }));\n}\n\n/** The 180° opposite on the OKLCH hue wheel. */\nexport function complementary(hex: string): string {\n return rotateHue(hex, 180);\n}\n\n/** The two neighbors at ±`angle` (default 30°), as [minus, plus]. */\nexport function analogous(hex: string, angle = 30): [string, string] {\n return [rotateHue(hex, -angle), rotateHue(hex, angle)];\n}\n\n/** The two colors completing an equilateral triad (±120°), as [minus, plus]. */\nexport function triadic(hex: string): [string, string] {\n return [rotateHue(hex, -120), rotateHue(hex, 120)];\n}\n\n/** The two colors flanking the complement (±150°), as [minus, plus]. */\nexport function splitComplementary(hex: string): [string, string] {\n return [rotateHue(hex, -150), rotateHue(hex, 150)];\n}\n\n/** The three colors completing a square (+90°, +180°, +270°). */\nexport function tetradic(hex: string): [string, string, string] {\n return [rotateHue(hex, 90), rotateHue(hex, 180), rotateHue(hex, 270)];\n}\n\n/**\n * A monochrome chroma scale: `steps` colors at the seed's lightness and hue,\n * fading chroma linearly from the seed's own chroma down to 0 (a pure gray).\n * The first entry is the seed itself (normalized).\n *\n * @throws RangeError when `steps` is not an integer ≥ 2.\n */\nexport function monochrome(hex: string, steps = 5): string[] {\n if (!Number.isInteger(steps) || steps < 2) {\n throw new RangeError(`monochrome: steps must be an integer >= 2, got ${steps}`);\n }\n const { L, C, h } = hexToOklch(hex);\n const out: string[] = [];\n for (let i = 0; i < steps; i++) {\n out.push(oklchToHex(clampToGamut({ L, C: C * (1 - i / (steps - 1)), h })));\n }\n return out;\n}\n","// Tint/shade ramps and predicate-driven lightness adjustment, both in OKLCH\n// so steps are perceptually even (equal OKLab ΔL per step; OKLab per Björn\n// Ottosson — see convert.ts for the matrices and citations).\n//\n// tintShadeRamp walks lightness from RAMP_L_MAX down to RAMP_L_MIN with a\n// chroma taper: full chroma mid-ramp, fading toward both ends. Very light\n// tints and very dark shades can't hold much chroma in sRGB anyway, and a\n// deliberate taper reads better than the hard cut the gamut clamp would\n// otherwise apply.\n//\n// adjustLightnessUntil binary-searches lightness (constant chroma and hue,\n// gamut-clamped) for the value nearest the input that satisfies a caller\n// predicate — the workhorse behind \"darken this accent until it clears\n// 4.5:1 on the page background\".\n\nimport { normalizeHex } from \"./hex\";\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\n\n/** Lightest OKLab L emitted by {@link tintShadeRamp} (first step). */\nexport const RAMP_L_MAX = 0.96;\n\n/** Darkest OKLab L emitted by {@link tintShadeRamp} (last step). */\nexport const RAMP_L_MIN = 0.27;\n\n/** Fraction of the seed's chroma kept at the ramp's endpoints. */\nconst CHROMA_FLOOR = 0.25;\n\n/**\n * A light-to-dark ramp of `steps` colors (default 9) built from the seed's\n * hue and chroma: OKLab lightness runs linearly from {@link RAMP_L_MAX} down\n * to {@link RAMP_L_MIN}, and chroma tapers from 100% of the seed's chroma at\n * mid-ramp to 25% at both ends (then gamut-clamps, preserving hue).\n *\n * @throws RangeError when `steps` is not an integer ≥ 2.\n */\nexport function tintShadeRamp(hex: string, steps = 9): string[] {\n if (!Number.isInteger(steps) || steps < 2) {\n throw new RangeError(`tintShadeRamp: steps must be an integer >= 2, got ${steps}`);\n }\n const { C, h } = hexToOklch(hex);\n const out: string[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = RAMP_L_MAX + (RAMP_L_MIN - RAMP_L_MAX) * t;\n const taper = CHROMA_FLOOR + (1 - CHROMA_FLOOR) * (1 - Math.abs(2 * t - 1));\n out.push(oklchToHex(clampToGamut({ L, C: C * taper, h })));\n }\n return out;\n}\n\n/** Direction {@link adjustLightnessUntil} may move lightness. */\nexport type LightnessDirection = \"lighten\" | \"darken\";\n\nconst SCAN_STEPS = 16;\nconst BISECT_STEPS = 22;\n\n/**\n * Moves a color's OKLCH lightness toward white (\"lighten\") or black\n * (\"darken\") until `predicate(hex)` holds, returning the passing color\n * nearest the input (chroma and hue constant, gamut-clamped per step).\n *\n * Returns the input itself (normalized) when it already passes, and null\n * when no lightness in that direction satisfies the predicate. Work is\n * bounded: a 16-step coarse scan plus 22 bisection rounds. The predicate is\n * always evaluated on exact 8-bit hex strings, including the returned one.\n */\nexport function adjustLightnessUntil(\n hex: string,\n predicate: (hex: string) => boolean,\n direction: LightnessDirection,\n): string | null {\n const start = normalizeHex(hex);\n if (predicate(start)) return start;\n const { L, C, h } = hexToOklch(start);\n const bound = direction === \"lighten\" ? 1 : 0;\n const at = (l: number): string => oklchToHex(clampToGamut({ L: l, C, h }));\n let lastFail = L;\n let firstPass = Number.NaN;\n for (let i = 1; i <= SCAN_STEPS; i++) {\n const l = L + ((bound - L) * i) / SCAN_STEPS;\n if (predicate(at(l))) {\n firstPass = l;\n break;\n }\n lastFail = l;\n }\n if (Number.isNaN(firstPass)) return null;\n for (let i = 0; i < BISECT_STEPS; i++) {\n const mid = (lastFail + firstPass) / 2;\n if (predicate(at(mid))) firstPass = mid;\n else lastFail = mid;\n }\n return at(firstPass);\n}\n","// ΔEOK — the OKLab color-difference metric adopted by CSS Color 4 (§ \"the\n// deltaEOK function\"): plain Euclidean distance in OKLab coordinates.\n// Scale intuition: ~0.02 is roughly one just-noticeable difference, and\n// white ↔ black is exactly 1.\n\nimport { parseHex } from \"./hex\";\nimport { rgbToOklab, type Oklab } from \"./convert\";\n\n/** Euclidean distance between two OKLab coordinates (CSS Color 4 ΔEOK). */\nexport function deltaEOKLab(x: Oklab, y: Oklab): number {\n return Math.hypot(x.L - y.L, x.a - y.a, x.b - y.b);\n}\n\n/**\n * ΔEOK between two hex colors. 0 = identical; ~0.02 ≈ one just-noticeable\n * difference; white ↔ black = 1. Symmetric in its arguments.\n *\n * @throws RangeError on malformed hex (see parseHex).\n */\nexport function deltaEOK(hexA: string, hexB: string): number {\n return deltaEOKLab(rgbToOklab(parseHex(hexA)), rgbToOklab(parseHex(hexB)));\n}\n","// The 148 CSS named colors — CSS Color 4 § 6.1 \"Named colors\" (the CSS3\n// keyword list plus rebeccapurple), with the spec's exact hex values —\n// and nearest-name lookup by ΔEOK (CSS Color 4's OKLab distance metric,\n// see delta.ts). Alphabetical order; gray/grey-style aliases are separate\n// entries sharing one hex.\n\nimport { parseHex } from \"./hex\";\nimport { rgbToOklab, type Oklab } from \"./convert\";\nimport { deltaEOKLab } from \"./delta\";\n\n/** One CSS named color: the keyword and its spec hex value. */\nexport interface NamedColor {\n /** The CSS keyword, e.g. \"rebeccapurple\". */\n name: string;\n /** The spec's `#rrggbb` value, lowercase. */\n hex: string;\n}\n\nconst TABLE: ReadonlyArray<readonly [string, string]> = [\n [\"aliceblue\", \"#f0f8ff\"],\n [\"antiquewhite\", \"#faebd7\"],\n [\"aqua\", \"#00ffff\"],\n [\"aquamarine\", \"#7fffd4\"],\n [\"azure\", \"#f0ffff\"],\n [\"beige\", \"#f5f5dc\"],\n [\"bisque\", \"#ffe4c4\"],\n [\"black\", \"#000000\"],\n [\"blanchedalmond\", \"#ffebcd\"],\n [\"blue\", \"#0000ff\"],\n [\"blueviolet\", \"#8a2be2\"],\n [\"brown\", \"#a52a2a\"],\n [\"burlywood\", \"#deb887\"],\n [\"cadetblue\", \"#5f9ea0\"],\n [\"chartreuse\", \"#7fff00\"],\n [\"chocolate\", \"#d2691e\"],\n [\"coral\", \"#ff7f50\"],\n [\"cornflowerblue\", \"#6495ed\"],\n [\"cornsilk\", \"#fff8dc\"],\n [\"crimson\", \"#dc143c\"],\n [\"cyan\", \"#00ffff\"],\n [\"darkblue\", \"#00008b\"],\n [\"darkcyan\", \"#008b8b\"],\n [\"darkgoldenrod\", \"#b8860b\"],\n [\"darkgray\", \"#a9a9a9\"],\n [\"darkgreen\", \"#006400\"],\n [\"darkgrey\", \"#a9a9a9\"],\n [\"darkkhaki\", \"#bdb76b\"],\n [\"darkmagenta\", \"#8b008b\"],\n [\"darkolivegreen\", \"#556b2f\"],\n [\"darkorange\", \"#ff8c00\"],\n [\"darkorchid\", \"#9932cc\"],\n [\"darkred\", \"#8b0000\"],\n [\"darksalmon\", \"#e9967a\"],\n [\"darkseagreen\", \"#8fbc8f\"],\n [\"darkslateblue\", \"#483d8b\"],\n [\"darkslategray\", \"#2f4f4f\"],\n [\"darkslategrey\", \"#2f4f4f\"],\n [\"darkturquoise\", \"#00ced1\"],\n [\"darkviolet\", \"#9400d3\"],\n [\"deeppink\", \"#ff1493\"],\n [\"deepskyblue\", \"#00bfff\"],\n [\"dimgray\", \"#696969\"],\n [\"dimgrey\", \"#696969\"],\n [\"dodgerblue\", \"#1e90ff\"],\n [\"firebrick\", \"#b22222\"],\n [\"floralwhite\", \"#fffaf0\"],\n [\"forestgreen\", \"#228b22\"],\n [\"fuchsia\", \"#ff00ff\"],\n [\"gainsboro\", \"#dcdcdc\"],\n [\"ghostwhite\", \"#f8f8ff\"],\n [\"gold\", \"#ffd700\"],\n [\"goldenrod\", \"#daa520\"],\n [\"gray\", \"#808080\"],\n [\"green\", \"#008000\"],\n [\"greenyellow\", \"#adff2f\"],\n [\"grey\", \"#808080\"],\n [\"honeydew\", \"#f0fff0\"],\n [\"hotpink\", \"#ff69b4\"],\n [\"indianred\", \"#cd5c5c\"],\n [\"indigo\", \"#4b0082\"],\n [\"ivory\", \"#fffff0\"],\n [\"khaki\", \"#f0e68c\"],\n [\"lavender\", \"#e6e6fa\"],\n [\"lavenderblush\", \"#fff0f5\"],\n [\"lawngreen\", \"#7cfc00\"],\n [\"lemonchiffon\", \"#fffacd\"],\n [\"lightblue\", \"#add8e6\"],\n [\"lightcoral\", \"#f08080\"],\n [\"lightcyan\", \"#e0ffff\"],\n [\"lightgoldenrodyellow\", \"#fafad2\"],\n [\"lightgray\", \"#d3d3d3\"],\n [\"lightgreen\", \"#90ee90\"],\n [\"lightgrey\", \"#d3d3d3\"],\n [\"lightpink\", \"#ffb6c1\"],\n [\"lightsalmon\", \"#ffa07a\"],\n [\"lightseagreen\", \"#20b2aa\"],\n [\"lightskyblue\", \"#87cefa\"],\n [\"lightslategray\", \"#778899\"],\n [\"lightslategrey\", \"#778899\"],\n [\"lightsteelblue\", \"#b0c4de\"],\n [\"lightyellow\", \"#ffffe0\"],\n [\"lime\", \"#00ff00\"],\n [\"limegreen\", \"#32cd32\"],\n [\"linen\", \"#faf0e6\"],\n [\"magenta\", \"#ff00ff\"],\n [\"maroon\", \"#800000\"],\n [\"mediumaquamarine\", \"#66cdaa\"],\n [\"mediumblue\", \"#0000cd\"],\n [\"mediumorchid\", \"#ba55d3\"],\n [\"mediumpurple\", \"#9370db\"],\n [\"mediumseagreen\", \"#3cb371\"],\n [\"mediumslateblue\", \"#7b68ee\"],\n [\"mediumspringgreen\", \"#00fa9a\"],\n [\"mediumturquoise\", \"#48d1cc\"],\n [\"mediumvioletred\", \"#c71585\"],\n [\"midnightblue\", \"#191970\"],\n [\"mintcream\", \"#f5fffa\"],\n [\"mistyrose\", \"#ffe4e1\"],\n [\"moccasin\", \"#ffe4b5\"],\n [\"navajowhite\", \"#ffdead\"],\n [\"navy\", \"#000080\"],\n [\"oldlace\", \"#fdf5e6\"],\n [\"olive\", \"#808000\"],\n [\"olivedrab\", \"#6b8e23\"],\n [\"orange\", \"#ffa500\"],\n [\"orangered\", \"#ff4500\"],\n [\"orchid\", \"#da70d6\"],\n [\"palegoldenrod\", \"#eee8aa\"],\n [\"palegreen\", \"#98fb98\"],\n [\"paleturquoise\", \"#afeeee\"],\n [\"palevioletred\", \"#db7093\"],\n [\"papayawhip\", \"#ffefd5\"],\n [\"peachpuff\", \"#ffdab9\"],\n [\"peru\", \"#cd853f\"],\n [\"pink\", \"#ffc0cb\"],\n [\"plum\", \"#dda0dd\"],\n [\"powderblue\", \"#b0e0e6\"],\n [\"purple\", \"#800080\"],\n [\"rebeccapurple\", \"#663399\"],\n [\"red\", \"#ff0000\"],\n [\"rosybrown\", \"#bc8f8f\"],\n [\"royalblue\", \"#4169e1\"],\n [\"saddlebrown\", \"#8b4513\"],\n [\"salmon\", \"#fa8072\"],\n [\"sandybrown\", \"#f4a460\"],\n [\"seagreen\", \"#2e8b57\"],\n [\"seashell\", \"#fff5ee\"],\n [\"sienna\", \"#a0522d\"],\n [\"silver\", \"#c0c0c0\"],\n [\"skyblue\", \"#87ceeb\"],\n [\"slateblue\", \"#6a5acd\"],\n [\"slategray\", \"#708090\"],\n [\"slategrey\", \"#708090\"],\n [\"snow\", \"#fffafa\"],\n [\"springgreen\", \"#00ff7f\"],\n [\"steelblue\", \"#4682b4\"],\n [\"tan\", \"#d2b48c\"],\n [\"teal\", \"#008080\"],\n [\"thistle\", \"#d8bfd8\"],\n [\"tomato\", \"#ff6347\"],\n [\"turquoise\", \"#40e0d0\"],\n [\"violet\", \"#ee82ee\"],\n [\"wheat\", \"#f5deb3\"],\n [\"white\", \"#ffffff\"],\n [\"whitesmoke\", \"#f5f5f5\"],\n [\"yellow\", \"#ffff00\"],\n [\"yellowgreen\", \"#9acd32\"],\n];\n\n/**\n * All 148 CSS named colors in alphabetical order. Aliases (aqua/cyan,\n * fuchsia/magenta, the gray/grey pairs) are separate entries sharing a hex.\n */\nexport const CSS_NAMED_COLORS: readonly NamedColor[] = TABLE.map(([name, hex]) => ({\n name,\n hex,\n}));\n\n/** A nearest-name match: the keyword, its spec hex, and the ΔEOK distance. */\nexport interface NearestNamedColor extends NamedColor {\n /** ΔEOK from the query color to this named color (0 = exact hit). */\n deltaEOK: number;\n}\n\nlet labCache: Oklab[] | null = null;\n\n/**\n * The CSS named color perceptually closest to `hex`, by ΔEOK in OKLab.\n * Exact hits return distance 0. Ties — including shared-hex aliases like\n * aqua/cyan — go to the alphabetically first keyword. As a rough guide,\n * distances ≲ 0.02 are visually indistinguishable and ≳ 0.1 is only a loose\n * \"same family\" match.\n *\n * @throws RangeError on malformed hex (see parseHex).\n */\nexport function nearestNamedColor(hex: string): NearestNamedColor {\n const target = rgbToOklab(parseHex(hex));\n labCache ??= TABLE.map(([, value]) => rgbToOklab(parseHex(value)));\n let bestIdx = 0;\n let bestD = Infinity;\n for (let i = 0; i < labCache.length; i++) {\n const d = deltaEOKLab(target, labCache[i]!);\n if (d < bestD) {\n bestD = d;\n bestIdx = i;\n }\n }\n const [name, value] = TABLE[bestIdx]!;\n return { name, hex: value, deltaEOK: bestD };\n}\n","// Full-palette derivation from a single seed color. All deterministic —\n// no randomness, no clock — so the same seed always yields the same\n// palette (proposals are reviewable and reproducible).\n//\n// Strategy:\n// - primary: the seed itself (normalized).\n// - secondary / highlight: classic harmony rotations of the seed in OKLCH\n// (complementary 180°, triadic ±120°, split-complementary ±150°).\n// secondary maximizes ΔEOK from the primary; highlight maximizes the\n// minimum ΔEOK to both, so the three accents spread apart. Near-achromatic\n// seeds (C < 0.02) have no usable hue, so rotations run from a synthetic\n// chromatic anchor at ANCHOR_HUE instead (a gray seed still deserves\n// real accents).\n// - good / warn / danger: hue-anchored at 145° / 85° / 25° OKLCH (green /\n// amber / red), darkened via adjustLightnessUntil until they clear WCAG's\n// 3:1 non-text bar (SC 1.4.11) against the derived background.\n// - chart set: hue rotations at a constant, gamut-safe (CHART_L, CHART_C)\n// chosen so every hue fits sRGB without chroma clamping. Adjacent 60°\n// hues then sit 2·C·sin(30°) = C apart in OKLab, so with C = 0.115 the\n// pairwise ΔEOK floor CHART_DELTA_MIN = 0.1 holds by construction.\n// - neutrals bg / surface / neutral / text: a near-achromatic ladder tinted\n// with the seed hue (C ≤ 0.012), L 0.985 → 0.24; text vs bg lands well\n// past 7:1 (AAA).\n\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { normalizeHex } from \"./hex\";\nimport { clampToGamut, hexToOklch, oklchToHex } from \"./convert\";\nimport { contrastRatio } from \"./contrast\";\nimport { rotateHue } from \"./harmony\";\nimport { adjustLightnessUntil } from \"./ramp\";\nimport { deltaEOK } from \"./delta\";\nimport { nearestNamedColor } from \"./names\";\n\n/**\n * Documented floor for pairwise ΔEOK between derived chart colors. The\n * default chart constants guarantee it by construction (see file header);\n * deriveChartColors also enforces it as a filter.\n */\nexport const CHART_DELTA_MIN = 0.1;\n\n/** Chart lightness: chosen with CHART_C so all hues are in-gamut (min max-chroma over hues ≈ 0.119 at L = 0.7). */\nconst CHART_L = 0.7;\n/** Chart chroma: gamut-safe at CHART_L for every hue, so no clamping ever shifts a chart color. */\nconst CHART_C = 0.115;\n/** Hue used when a seed is too gray to have one (a mid blue). */\nconst ANCHOR_HUE = 250;\n/** Below this OKLCH chroma a seed is treated as achromatic. */\nconst ACHROMATIC_C = 0.02;\n/** Status swatch anchors (OKLCH hue degrees): green / amber / red. */\nconst STATUS_HUES = { good: 145, warn: 85, danger: 25 } as const;\nconst STATUS_L = 0.7;\nconst STATUS_C = 0.14;\n/** Harmony rotations tried for secondary/highlight, in tie-break order. */\nconst ROTATIONS = [180, 120, -120, 150, -150] as const;\n\n/** Options for {@link deriveChartColors}. */\nexport interface DeriveChartOptions {\n /** How many colors to return, 1..12 (default 6). */\n count?: number;\n /** Pairwise ΔEOK floor (default {@link CHART_DELTA_MIN}). Best-effort above the default. */\n deltaMin?: number;\n}\n\n/**\n * Derives categorical chart colors from a seed: hue rotations (60° grid,\n * then 30° offsets) around the seed's hue at a constant, gamut-safe\n * lightness/chroma. Candidates are kept only if they stay at least\n * `deltaMin` ΔEOK from every accepted color; if the requested floor is\n * unattainable for `count` colors, remaining distinct candidates fill the\n * set in hue order so callers always get `count` colors back.\n *\n * @throws RangeError when `count` is not an integer in 1..12, or on\n * malformed hex.\n */\nexport function deriveChartColors(seedHex: string, opts: DeriveChartOptions = {}): string[] {\n const count = opts.count ?? 6;\n const deltaMin = opts.deltaMin ?? CHART_DELTA_MIN;\n if (!Number.isInteger(count) || count < 1 || count > 12) {\n throw new RangeError(`deriveChartColors: count must be an integer in 1..12, got ${count}`);\n }\n const lch = hexToOklch(normalizeHex(seedHex));\n const base = lch.C < ACHROMATIC_C ? ANCHOR_HUE : lch.h;\n const offsets = [0, 60, 120, 180, 240, 300, 30, 90, 150, 210, 270, 330];\n const candidates = offsets.map((deg) =>\n oklchToHex(clampToGamut({ L: CHART_L, C: CHART_C, h: (base + deg) % 360 })),\n );\n const picked: string[] = [];\n for (const hex of candidates) {\n if (picked.length >= count) break;\n if (picked.includes(hex)) continue;\n if (picked.every((p) => deltaEOK(p, hex) >= deltaMin)) picked.push(hex);\n }\n for (const hex of candidates) {\n if (picked.length >= count) break;\n if (!picked.includes(hex)) picked.push(hex);\n }\n return picked;\n}\n\n/** Options for {@link derivePalette}. */\nexport interface DerivePaletteOptions {\n /** Attach nearest-CSS-keyword `name`s to every swatch (default true). */\n names?: boolean;\n}\n\n/**\n * Derives a complete brand palette from one seed color: one swatch each for\n * primary, secondary, highlight, good, warn, danger, bg, surface, text and\n * neutral, plus six chart swatches (16 total) — see the file header for the\n * derivation strategy and its WCAG guarantees.\n *\n * @throws RangeError on malformed seed hex (see parseHex).\n */\nexport function derivePalette(seedHex: string, opts: DerivePaletteOptions = {}): Swatch[] {\n const withNames = opts.names !== false;\n const seed = normalizeHex(seedHex);\n const seedLch = hexToOklch(seed);\n const achromatic = seedLch.C < ACHROMATIC_C;\n const hue = achromatic ? ANCHOR_HUE : seedLch.h;\n\n const neutralAt = (L: number, C: number): string => oklchToHex(clampToGamut({ L, C, h: hue }));\n const bg = neutralAt(0.985, 0.005);\n const surface = neutralAt(0.955, 0.008);\n const text = neutralAt(0.24, 0.012);\n const neutral = neutralAt(0.62, 0.012);\n\n const accentBase = achromatic\n ? oklchToHex(\n clampToGamut({ L: Math.min(Math.max(seedLch.L, 0.45), 0.75), C: CHART_C, h: ANCHOR_HUE }),\n )\n : seed;\n const cands = ROTATIONS.map((deg) => {\n const hex = rotateHue(accentBase, deg);\n return { deg, hex, d: deltaEOK(seed, hex) };\n });\n let secondary = cands[0]!;\n for (const c of cands) if (c.d > secondary.d) secondary = c;\n let highlight = cands[0] === secondary ? cands[1]! : cands[0]!;\n let hiScore = Math.min(highlight.d, deltaEOK(highlight.hex, secondary.hex));\n for (const c of cands) {\n if (c === secondary || c === highlight) continue;\n const score = Math.min(c.d, deltaEOK(c.hex, secondary.hex));\n if (score > hiScore) {\n highlight = c;\n hiScore = score;\n }\n }\n\n const status = (anchor: number): string => {\n const start = oklchToHex(clampToGamut({ L: STATUS_L, C: STATUS_C, h: anchor }));\n return adjustLightnessUntil(start, (c) => contrastRatio(c, bg) >= 3, \"darken\") ?? text;\n };\n\n const sw = (role: SwatchRole, hex: string, rationale: string): Swatch => ({\n role,\n hex,\n rationale,\n });\n const swatches: Swatch[] = [\n sw(\"primary\", seed, \"seed color\"),\n sw(\"secondary\", secondary.hex, `harmony rotation ${secondary.deg}°, ΔEOK ${secondary.d.toFixed(3)} from primary`),\n sw(\"highlight\", highlight.hex, `harmony rotation ${highlight.deg}°, spread from primary and secondary`),\n sw(\"good\", status(STATUS_HUES.good), \"green anchor 145°, ≥3:1 on bg\"),\n sw(\"warn\", status(STATUS_HUES.warn), \"amber anchor 85°, ≥3:1 on bg\"),\n sw(\"danger\", status(STATUS_HUES.danger), \"red anchor 25°, ≥3:1 on bg\"),\n sw(\"bg\", bg, \"near-white tinted with the seed hue\"),\n sw(\"surface\", surface, \"raised surface, one step below bg\"),\n sw(\"text\", text, \"near-black tinted with the seed hue\"),\n sw(\"neutral\", neutral, \"mid neutral for borders and muted marks\"),\n ...deriveChartColors(seed).map((hex, i) => sw(\"chart\", hex, `chart series ${i + 1}`)),\n ];\n return withNames\n ? swatches.map((s) => ({ ...s, name: nearestNamedColor(s.hex).name }))\n : swatches;\n}\n","// Palette → light-mode @odla-ai/ui tokens.\n//\n// Every name in BRAND_EMITTED_TOKENS is always emitted. Real swatches map\n// directly; missing roles fall back to derivePalette() output seeded from\n// the accent (with a warning); derived/composed roles use the EXACT\n// var()/color-mix() composition strings @odla-ai/ui css/tokens.css uses as\n// defaults, so the object works as a scoped override-island payload (the\n// compositions recompute at the declaring element — see roles.ts).\n//\n// Contrast guarantees (WCAG 2.1, enforced with adjustLightnessUntil and\n// recorded as warnings with `adjustedFrom` whenever a color had to move):\n// --ui-text ≥ 4.5:1 and --ui-text-muted ≥ 4.5:1 on --ui-bg (SC 1.4.3),\n// --ui-accent-strong ≥ 4.5:1 on --ui-bg (darkened on a light bg),\n// --ui-good/warn/danger ≥ 3:1 on --ui-bg (SC 1.4.11), and --ui-on-accent\n// via pickTextOn (≥ 4.5:1 with the default white/near-black candidates).\n\nimport type { Swatch, SwatchRole } from \"../types\";\nimport {\n adjustLightnessUntil,\n clamp01,\n clampToGamut,\n contrastRatio,\n deriveChartColors,\n derivePalette,\n hexToOklch,\n normalizeHex,\n oklchToHex,\n parseHex,\n pickTextOn,\n relativeLuminance,\n type LightnessDirection,\n} from \"../color\";\nimport type { BrandTokens, CompileInput, TokenWarning } from \"./types\";\n\n/**\n * Seed used when the palette has no usable chromatic swatch at all — the\n * @odla-ai/ui neutral default accent (css/tokens.css restrained blue).\n */\nexport const DEFAULT_ACCENT_SEED = \"#3b5e8c\";\n\n/** Below this OKLCH chroma a swatch is too gray for accent/chart duty. */\nconst CHROMATIC_C = 0.02;\n\n// System font stacks, verbatim from @odla-ai/ui css/tokens.css.\nconst SANS_STACK = `ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif`;\nconst SERIF_STACK = `\"Iowan Old Style\", \"Palatino Linotype\", Palatino, Georgia, serif`;\nconst MONO_STACK = `ui-monospace, \"SF Mono\", Menlo, Consolas, monospace`;\nconst DISPLAY_STACK = `ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif`;\n\n// ui css/tokens.css chart defaults — emitted when the palette lacks ≥3\n// chromatic chart swatches, so an override island never keeps root values.\nconst UI_CHART_DEFAULTS = [\n \"var(--ui-accent)\",\n \"var(--ui-good)\",\n \"var(--ui-warn)\",\n \"var(--ui-danger)\",\n \"color-mix(in srgb, var(--ui-accent) 45%, var(--ui-text))\",\n \"var(--ui-text-faint)\",\n] as const;\n\n/**\n * The token a missing swatch role is reported against — and the canonical\n * role → `--ui-*` correspondence. Exported so the design decompiler can\n * invert exactly this map rather than restating it (see\n * `design/decompile.ts`); a round-trip test pins the two together.\n */\nexport const ROLE_TOKEN: Partial<Record<SwatchRole, string>> = {\n primary: \"--ui-accent\",\n secondary: \"--ui-accent-2\",\n highlight: \"--ui-highlight\",\n bg: \"--ui-bg\",\n surface: \"--ui-surface\",\n text: \"--ui-text\",\n neutral: \"--ui-border-strong\",\n good: \"--ui-good\",\n warn: \"--ui-warn\",\n danger: \"--ui-danger\",\n chart: \"--ui-chart-1\",\n};\n\nconst mixVar = (name: string, pct: number): string =>\n `color-mix(in srgb, var(${name}) ${pct}%, transparent)`;\n\n/** Shift OKLab lightness by dL, constant chroma/hue, gamut-clamped. */\nfunction shiftL(hex: string, dL: number): string {\n const { L, C, h } = hexToOklch(hex);\n return oklchToHex(clampToGamut({ L: clamp01(L + dL), C, h }));\n}\n\n/** Move `fromHex` a fraction `t` of the way to `toHex` in OKLab lightness only. */\nfunction lerpL(fromHex: string, toHex: string, t: number): string {\n const a = hexToOklch(fromHex);\n const b = hexToOklch(toHex);\n return oklchToHex(clampToGamut({ L: a.L + (b.L - a.L) * t, C: a.C, h: a.h }));\n}\n\n/**\n * Push `hex` away from `bg` in lightness until it clears `min`:1. Tries the\n * away-from-bg direction (darken on a light bg), then the other direction,\n * then falls back to pickTextOn(bg) — which always clears 4.5:1.\n */\nfunction ensureOnBg(hex: string, bg: string, min: number): string {\n const pred = (c: string): boolean => contrastRatio(c, bg) >= min;\n const away: LightnessDirection =\n relativeLuminance(bg) >= relativeLuminance(hex) ? \"darken\" : \"lighten\";\n return (\n adjustLightnessUntil(hex, pred, away) ??\n adjustLightnessUntil(hex, pred, away === \"darken\" ? \"lighten\" : \"darken\") ??\n pickTextOn(bg)\n );\n}\n\nconst rgbaOf = (hex: string, alpha: number): string => {\n const { r, g, b } = parseHex(hex);\n const c = (v: number): number => Math.round(v * 255);\n return `rgba(${c(r)}, ${c(g)}, ${c(b)}, ${alpha})`;\n};\n\n/** Brand family + system stack; quotes a single family name when needed. */\nfunction fontValue(family: string | undefined, stack: string): string {\n const f = family?.trim() ?? \"\";\n if (f === \"\") return stack;\n if (f.includes(\",\") || /^[\"']/.test(f) || /^[a-zA-Z][a-zA-Z0-9-]*$/.test(f))\n return `${f}, ${stack}`;\n return `\"${f.replaceAll('\"', \"\")}\", ${stack}`;\n}\n\ninterface Collected {\n byRole: Partial<Record<SwatchRole, string>>;\n charts: string[];\n}\n\n/** First-wins role → hex map + ordered chart swatches; bad hexes dropped. */\nfunction collect(swatches: unknown, warnings: TokenWarning[]): Collected {\n const byRole: Partial<Record<SwatchRole, string>> = {};\n const charts: string[] = [];\n if (!Array.isArray(swatches)) {\n warnings.push({ token: \"--ui-accent\", message: \"swatches is not an array; compiling from defaults\" });\n return { byRole, charts };\n }\n (swatches as Array<Swatch | null>).forEach((s, i) => {\n let hex: string;\n try {\n hex = normalizeHex(String(s?.hex));\n } catch {\n warnings.push({\n token: (s?.role !== undefined && ROLE_TOKEN[s.role]) || \"--ui-accent\",\n message: `swatches[${i}] dropped: invalid hex ${String(s?.hex)}`,\n });\n return;\n }\n const role = s?.role;\n if (role === \"chart\") charts.push(hex);\n else if (role !== undefined && role !== \"custom\" && byRole[role] === undefined) byRole[role] = hex;\n });\n return { byRole, charts };\n}\n\n/** What {@link mapPaletteToTokens} returns. */\nexport interface MapResult {\n /** The light-mode token map — every name in BRAND_EMITTED_TOKENS. */\n tokens: BrandTokens;\n /** Fallbacks taken and contrast adjustments made. */\n warnings: TokenWarning[];\n}\n\n/**\n * Maps a palette (+ optional typography) onto the full light-mode\n * @odla-ai/ui token set. Never throws on bad palettes: invalid swatches are\n * dropped, missing roles derive from the accent via derivePalette, and every\n * degradation is recorded as a {@link TokenWarning}.\n */\nexport function mapPaletteToTokens(input: CompileInput): MapResult {\n const warnings: TokenWarning[] = [];\n const { byRole, charts } = collect(input?.swatches, warnings);\n\n let accent = byRole.primary;\n if (accent === undefined) {\n const chromatic = [...Object.values(byRole), ...charts].find(\n (h) => h !== undefined && hexToOklch(h).C >= CHROMATIC_C,\n );\n accent = chromatic ?? DEFAULT_ACCENT_SEED;\n warnings.push({\n token: \"--ui-accent\",\n message: `no primary swatch; using ${chromatic !== undefined ? \"the first chromatic swatch\" : \"the neutral default seed\"} ${accent}`,\n });\n }\n\n const fb = new Map<SwatchRole, string>();\n for (const s of derivePalette(accent, { names: false })) if (!fb.has(s.role)) fb.set(s.role, s.hex);\n const pick = (role: SwatchRole): string => {\n const own = byRole[role];\n if (own !== undefined) return own;\n const derived = fb.get(role)!;\n warnings.push({ token: ROLE_TOKEN[role]!, message: `no ${role} swatch; derived ${derived} from ${accent}` });\n return derived;\n };\n\n const bg = pick(\"bg\");\n const surface = pick(\"surface\");\n const neutral = pick(\"neutral\");\n const surface2 = shiftL(surface, -0.035);\n\n const rawText = pick(\"text\");\n const text = ensureOnBg(rawText, bg, 4.5);\n if (text !== rawText)\n warnings.push({ token: \"--ui-text\", message: \"adjusted to reach 4.5:1 on --ui-bg\", adjustedFrom: rawText });\n\n const accentStrong = ensureOnBg(accent, bg, 4.5);\n if (accentStrong !== accent)\n warnings.push({\n token: \"--ui-accent-strong\",\n message: \"moved --ui-accent in lightness to reach 4.5:1 on --ui-bg\",\n adjustedFrom: accent,\n });\n\n const status = (role: \"good\" | \"warn\" | \"danger\"): string => {\n const own = pick(role);\n const fixed = ensureOnBg(own, bg, 3);\n if (fixed !== own)\n warnings.push({ token: ROLE_TOKEN[role]!, message: \"adjusted to reach 3:1 on --ui-bg\", adjustedFrom: own });\n return fixed;\n };\n\n const chromaticCharts = charts.filter((h) => hexToOklch(h).C >= CHROMATIC_C);\n let chartValues: readonly string[];\n if (chromaticCharts.length >= 3) {\n const picked = chromaticCharts.slice(0, 6);\n for (const c of deriveChartColors(accent, { count: 12 })) {\n if (picked.length >= 6) break;\n if (!picked.includes(c)) picked.push(c);\n }\n chartValues = picked;\n } else {\n warnings.push({\n token: \"--ui-chart-1\",\n message: `fewer than 3 chromatic chart swatches (${chromaticCharts.length}); using the ui derived chart defaults`,\n });\n chartValues = UI_CHART_DEFAULTS;\n }\n\n const secondary = byRole.secondary;\n if (secondary === undefined)\n warnings.push({ token: \"--ui-accent-2\", message: \"no secondary swatch; --ui-accent-2 collapses onto var(--ui-accent) (ui default)\" });\n const highlight = byRole.highlight;\n if (highlight === undefined)\n warnings.push({ token: \"--ui-highlight\", message: \"no highlight swatch; --ui-highlight aliases var(--ui-accent-strong) (ui default)\" });\n\n const t = input?.typography ?? {};\n const tokens: BrandTokens = {\n \"--ui-bg\": bg,\n \"--ui-surface\": surface,\n \"--ui-surface-2\": surface2,\n \"--ui-text\": text,\n \"--ui-text-muted\": ensureOnBg(lerpL(text, bg, 0.35), bg, 4.5),\n \"--ui-text-faint\": lerpL(text, bg, 0.58),\n \"--ui-border\": lerpL(neutral, bg, 0.55),\n \"--ui-border-strong\": neutral,\n \"--ui-accent\": accent,\n \"--ui-accent-strong\": accentStrong,\n \"--ui-accent-soft\": mixVar(\"--ui-accent\", 10),\n \"--ui-on-accent\": pickTextOn(accent),\n \"--ui-good\": status(\"good\"),\n \"--ui-good-soft\": mixVar(\"--ui-good\", 12),\n \"--ui-warn\": status(\"warn\"),\n \"--ui-warn-soft\": mixVar(\"--ui-warn\", 12),\n \"--ui-danger\": status(\"danger\"),\n \"--ui-danger-soft\": mixVar(\"--ui-danger\", 10),\n \"--ui-code-bg\": surface2,\n \"--ui-code-text\": text,\n \"--ui-shadow\": `0 1px 2px ${rgbaOf(text, 0.04)}, 0 8px 24px ${rgbaOf(text, 0.06)}`,\n \"--ui-font-sans\": fontValue(t.fontBody, SANS_STACK),\n \"--ui-font-serif\": SERIF_STACK,\n \"--ui-font-mono\": fontValue(t.fontMono, MONO_STACK),\n \"--ui-font-display\": fontValue(t.fontDisplay ?? t.fontBody, DISPLAY_STACK),\n \"--ui-accent-glow\": mixVar(\"--ui-accent\", 16),\n \"--ui-accent-2\": secondary ?? \"var(--ui-accent)\",\n \"--ui-accent-2-soft\": mixVar(\"--ui-accent-2\", 10),\n \"--ui-highlight\": highlight ?? \"var(--ui-accent-strong)\",\n \"--ui-focus\": \"0 0 0 3px var(--ui-accent-soft)\",\n \"--ui-shadow-strong\": \"var(--ui-shadow)\",\n \"--ui-chart-1\": chartValues[0]!,\n \"--ui-chart-2\": chartValues[1]!,\n \"--ui-chart-3\": chartValues[2]!,\n \"--ui-chart-4\": chartValues[3]!,\n \"--ui-chart-5\": chartValues[4]!,\n \"--ui-chart-6\": chartValues[5]!,\n \"--ui-chart-band\": mixVar(\"--ui-accent\", 10),\n \"--ui-chart-band-strong\": mixVar(\"--ui-accent\", 22),\n \"--ui-chart-flow\": \"var(--ui-accent)\",\n \"--ui-chart-glow\": \"var(--ui-accent-strong)\",\n \"--ui-chat-user-bg\": \"var(--ui-accent-soft)\",\n \"--ui-chat-user-text\": \"var(--ui-text)\",\n \"--ui-chat-assistant-bg\": \"var(--ui-surface)\",\n \"--ui-chat-thinking-bg\": \"var(--ui-surface-2)\",\n \"--ui-chat-thinking-text\": \"var(--ui-text-muted)\",\n \"--ui-chat-tool-accent\": \"var(--ui-accent)\",\n };\n return { tokens, warnings };\n}\n","// The reverse token compiler: a design's `--ui-*` declarations → brand\n// swatches.\n//\n// `mapPaletteToTokens` runs brand book → tokens. A Claude design authored on\n// the @odla-ai/ui contract arrives with the OUTPUT of that mapping already\n// filled in, so reading it back is how a design becomes a brand book instead\n// of a one-off page. The inverse is built from the forward map's own\n// ROLE_TOKEN table, so the two cannot drift apart.\n//\n// Only opaque, literal colours convert. A token left as `color-mix(…)`,\n// `rgba(…, 0.13)`, or an unresolved `var(…)` is REPORTED, not guessed at:\n// swatches feed contrast math and a fabricated hex would quietly poison it.\nimport { ROLE_TOKEN } from \"../tokens/map\";\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { assertHex } from \"../validate\";\nimport type { DesignTokenSets } from \"./types\";\n\n/** The chart-series tokens read back as repeated `chart` swatches. */\nconst CHART_TOKENS = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n] as const;\n\n/** One token that could not become a swatch, and why. */\nexport interface DesignTokenSkip {\n token: string;\n value: string;\n reason: string;\n}\n\n/** What {@link swatchesFromDesignTokens} produced. */\nexport interface DesignDecompilation {\n swatches: Swatch[];\n /** Tokens present but not literal opaque colours. */\n skipped: DesignTokenSkip[];\n /** Roles the design declared no token for at all. */\n missing: SwatchRole[];\n}\n\n/** Parse one CSS colour value to `#rrggbb`, or null when it is not a literal\n * opaque colour. Accepts hex and `rgb()`/`rgba()` with alpha exactly 1. */\nexport function cssColorToHex(value: string): string | null {\n const text = value.trim();\n if (text.startsWith(\"#\")) {\n try {\n return assertHex(text);\n } catch {\n return null;\n }\n }\n const fn = /^rgba?\\(([^)]*)\\)$/i.exec(text);\n if (!fn) return null;\n const parts = (fn[1] ?? \"\").split(/[,/\\s]+/).filter((p) => p !== \"\");\n if (parts.length < 3 || parts.length > 4) return null;\n if (parts.length === 4) {\n const alpha = parts[3]!.endsWith(\"%\")\n ? Number.parseFloat(parts[3]!) / 100\n : Number.parseFloat(parts[3]!);\n if (!Number.isFinite(alpha) || alpha < 1) return null;\n }\n const channels = parts.slice(0, 3).map((part) => {\n const n = Number.parseFloat(part);\n if (!Number.isFinite(n)) return Number.NaN;\n return Math.round(part.endsWith(\"%\") ? (n / 100) * 255 : n);\n });\n if (channels.some((c) => !Number.isFinite(c) || c < 0 || c > 255)) return null;\n return `#${channels.map((c) => c.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nconst skipReason = (value: string): string =>\n value.includes(\"var(\")\n ? \"unresolved var() reference\"\n : value.includes(\"color-mix(\")\n ? \"composed with color-mix()\"\n : /rgba?\\(/i.test(value)\n ? \"not fully opaque\"\n : \"not a literal color\";\n\n/**\n * Read a design's declared `--ui-*` tokens back into brand swatches.\n *\n * Reads the LIGHT set: brand palettes are authored light-first and\n * `deriveDarkTokens` regenerates dark on compile, so importing a design's\n * dark values would be overwritten anyway. The design's dark tokens stay\n * visible in the digest for reference.\n */\nexport function swatchesFromDesignTokens(tokens: DesignTokenSets): DesignDecompilation {\n const light = tokens.light;\n const swatches: Swatch[] = [];\n const skipped: DesignTokenSkip[] = [];\n const missing: SwatchRole[] = [];\n\n for (const [role, token] of Object.entries(ROLE_TOKEN) as [SwatchRole, string][]) {\n // `chart` is the series head; the whole series is read below instead.\n if (role === \"chart\") continue;\n const value = light[token];\n if (value === undefined) {\n missing.push(role);\n continue;\n }\n const hex = cssColorToHex(value);\n if (hex === null) {\n skipped.push({ token, value, reason: skipReason(value) });\n continue;\n }\n swatches.push({ role, hex, rationale: `declared by the design as ${token}` });\n }\n\n let anyChart = false;\n for (const token of CHART_TOKENS) {\n const value = light[token];\n if (value === undefined) continue;\n const hex = cssColorToHex(value);\n if (hex === null) {\n skipped.push({ token, value, reason: skipReason(value) });\n continue;\n }\n anyChart = true;\n swatches.push({ role: \"chart\", hex, rationale: `declared by the design as ${token}` });\n }\n if (!anyChart) missing.push(\"chart\");\n\n return { swatches, skipped, missing };\n}\n","// Minimal HTML text helpers shared by the design extractors: entity decoding,\n// tag stripping, and whitespace collapsing.\n//\n// These exist because a design digest quotes human-readable text (headings,\n// prop defaults) that must survive into a model prompt or a JSON file\n// looking like what a person wrote — `&amp;` and `&#39;` in a heading are\n// noise an agent would otherwise reproduce in the site it builds.\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: \"&\",\n lt: \"<\",\n gt: \">\",\n quot: '\"',\n apos: \"'\",\n nbsp: \" \",\n mdash: \"—\",\n ndash: \"–\",\n hellip: \"…\",\n rsquo: \"’\",\n lsquo: \"‘\",\n ldquo: \"“\",\n rdquo: \"”\",\n};\n\n/** Decode the named and numeric HTML entities that appear in real markup. */\nexport function decodeEntities(text: string): string {\n return text.replace(/&(#x[0-9a-fA-F]+|#\\d+|[a-zA-Z][a-zA-Z0-9]{1,31});/g, (whole, body: string) => {\n if (body.startsWith(\"#x\") || body.startsWith(\"#X\")) {\n const code = Number.parseInt(body.slice(2), 16);\n return Number.isFinite(code) && code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : whole;\n }\n if (body.startsWith(\"#\")) {\n const code = Number.parseInt(body.slice(1), 10);\n return Number.isFinite(code) && code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : whole;\n }\n return NAMED_ENTITIES[body.toLowerCase()] ?? whole;\n });\n}\n\n/** Collapse every run of whitespace to a single space and trim. */\nexport const collapseWhitespace = (text: string): string => text.replace(/\\s+/g, \" \").trim();\n\n/**\n * Strip tags and decode entities, yielding the visible text of a markup\n * fragment. Script and style element contents are dropped whole — a heading\n * containing an inline `<style>` would otherwise contribute CSS as prose.\n */\nexport function htmlToText(fragment: string): string {\n const withoutCode = fragment\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script\\s*>/gi, \" \")\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style\\s*>/gi, \" \");\n return collapseWhitespace(decodeEntities(withoutCode.replace(/<[^>]*>/g, \" \")));\n}\n","// The design's information architecture: its title and its heading outline.\n//\n// This is the part of a digest a building agent reads first — it is the site\n// map and the real copy, in document order, at a size that fits in a prompt\n// while the 150 KB template stays on disk.\nimport { htmlToText } from \"./html-text\";\nimport type { DesignOutlineEntry } from \"./types\";\n\n/** Most headings carried into a digest. */\nexport const MAX_OUTLINE_ENTRIES = 120;\n/** Longest single heading kept, in characters. */\nexport const MAX_HEADING_CHARS = 200;\n\n/** The document `<title>`, decoded and collapsed; undefined when unset. */\nexport function extractTitle(html: string): string | undefined {\n const match = /<title\\b[^>]*>([\\s\\S]{0,2000}?)<\\/title\\s*>/i.exec(html);\n if (!match) return undefined;\n const text = htmlToText(match[1] ?? \"\");\n return text === \"\" ? undefined : text.slice(0, MAX_HEADING_CHARS);\n}\n\n/**\n * Headings (`<h1>`…`<h6>`) in document order, as level + visible text.\n *\n * Empty headings — icon-only or decorative — are skipped rather than emitted\n * as blanks. The scan stops at {@link MAX_OUTLINE_ENTRIES}; the caller\n * reports the truncation in the digest.\n */\nexport function extractOutline(html: string): { entries: DesignOutlineEntry[]; truncated: boolean } {\n const pattern = /<h([1-6])\\b[^>]*>([\\s\\S]{0,4000}?)<\\/h\\1\\s*>/gi;\n const entries: DesignOutlineEntry[] = [];\n for (;;) {\n const match = pattern.exec(html);\n if (match === null) break;\n const text = htmlToText(match[2] ?? \"\");\n if (text === \"\") continue;\n if (entries.length >= MAX_OUTLINE_ENTRIES) return { entries, truncated: true };\n entries.push({ level: Number(match[1]), text: text.slice(0, MAX_HEADING_CHARS) });\n }\n return { entries, truncated: false };\n}\n","// The design's declared configuration surface.\n//\n// Claude Design attaches a `data-props` map to the component's logic script:\n// each entry names an editor (text, boolean, enum, …), a default, a\n// TypeScript type, and the panel section it groups under. That map is the\n// design's own statement of WHAT IS MEANT TO VARY — which copy is a\n// placeholder, which layout choices are switches, which values are enums\n// with a fixed set. A building agent that reads it stops guessing which\n// strings are real content and which are stand-ins.\nimport { decodeEntities } from \"./html-text\";\nimport type { DesignProp } from \"./types\";\n\n/** Most props carried into a digest. */\nexport const MAX_PROPS = 60;\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Read one HTML attribute's raw (still-escaped) value from a tag soup. */\nfunction attributeValue(html: string, attr: string): string | null {\n const at = html.indexOf(`${attr}=\"`);\n if (at >= 0) {\n const from = at + attr.length + 2;\n const end = html.indexOf('\"', from);\n return end < 0 ? null : html.slice(from, end);\n }\n const single = html.indexOf(`${attr}='`);\n if (single < 0) return null;\n const from = single + attr.length + 2;\n const end = html.indexOf(\"'\", from);\n return end < 0 ? null : html.slice(from, end);\n}\n\n/** Stringify a declared default without inventing a representation. */\nfunction defaultText(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return value.slice(0, 400);\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value).slice(0, 400);\n } catch {\n return undefined;\n }\n}\n\nfunction toProp(name: string, spec: Record<string, unknown>): DesignProp {\n const options = Array.isArray(spec.options)\n ? spec.options.filter((v): v is string => typeof v === \"string\").slice(0, 24)\n : undefined;\n const declared = defaultText(spec.default);\n return {\n name: name.slice(0, 80),\n editor: typeof spec.editor === \"string\" ? spec.editor.slice(0, 40) : \"unknown\",\n ...(options && options.length > 0 ? { options } : {}),\n ...(declared !== undefined ? { default: declared } : {}),\n ...(typeof spec.section === \"string\" ? { section: spec.section.slice(0, 80) } : {}),\n ...(typeof spec.tsType === \"string\" ? { tsType: spec.tsType.slice(0, 200) } : {}),\n };\n}\n\n/**\n * Extract the design's declared props, in declaration order.\n *\n * Returns an empty list — never throws — when the design declares none or\n * the attribute is unparseable: props are a bonus signal, and a design\n * without them is still perfectly usable.\n */\nexport function extractProps(html: string): { props: DesignProp[]; truncated: boolean } {\n const at = html.indexOf(\"data-props=\");\n if (at < 0) return { props: [], truncated: false };\n const raw = attributeValue(html.slice(at), \"data-props\");\n if (raw === null) return { props: [], truncated: false };\n let parsed: unknown;\n try {\n parsed = JSON.parse(decodeEntities(raw));\n } catch {\n return { props: [], truncated: false };\n }\n if (!isRecord(parsed)) return { props: [], truncated: false };\n const entries = Object.entries(parsed).filter((entry): entry is [string, Record<string, unknown>] =>\n isRecord(entry[1]),\n );\n return {\n props: entries.slice(0, MAX_PROPS).map(([name, spec]) => toProp(name, spec)),\n truncated: entries.length > MAX_PROPS,\n };\n}\n","// Typeface and colour facts read out of a design's stylesheets.\n//\n// Fonts come from `@font-face` first, on purpose: those are the families the\n// bundle actually SHIPS webfont bytes for, which is a precise answer, where\n// scanning `font-family` stacks yields every system fallback the design ever\n// names. Stacks are only the fallback when a design links its fonts instead\n// of embedding them.\nimport { stripCssComments, styleSheetText } from \"./css-scan\";\nimport type { DesignColorUse } from \"./types\";\n\n/** Most typeface families reported. */\nexport const MAX_FONTS = 16;\n/** Most distinct literal colours reported. */\nexport const MAX_COLORS = 24;\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"inherit\",\n \"initial\",\n \"revert\",\n \"unset\",\n \"currentcolor\",\n]);\n\n/** Strip quotes from one family name and normalize its whitespace. */\nconst familyName = (raw: string): string => raw.trim().replace(/^[\"']|[\"']$/g, \"\").trim();\n\n/** Families the document embeds webfont bytes for, in first-seen order. */\nfunction fontFaceFamilies(css: string): string[] {\n const seen = new Set<string>();\n const blocks = /@font-face\\s*\\{([^}]{0,4000})\\}/gi;\n for (;;) {\n const block = blocks.exec(css);\n if (block === null) break;\n const declared = /font-family\\s*:\\s*([^;]{1,200})/i.exec(block[1] ?? \"\");\n if (!declared) continue;\n const name = familyName(declared[1] ?? \"\");\n if (name !== \"\" && !GENERIC_FAMILIES.has(name.toLowerCase())) seen.add(name);\n }\n return [...seen];\n}\n\n/** Quoted families named anywhere in a `font-family` stack, most-used first. */\nfunction stackFamilies(css: string): string[] {\n const counts = new Map<string, number>();\n const stacks = /font-family\\s*:\\s*([^;{}]{1,400})/gi;\n for (;;) {\n const stack = stacks.exec(css);\n if (stack === null) break;\n for (const part of (stack[1] ?? \"\").split(\",\")) {\n if (!/[\"']/.test(part)) continue;\n const name = familyName(part);\n if (name === \"\" || GENERIC_FAMILIES.has(name.toLowerCase()) || name.includes(\"var(\")) continue;\n counts.set(name, (counts.get(name) ?? 0) + 1);\n }\n }\n return [...counts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1)).map(([name]) => name);\n}\n\n/**\n * The typeface families a design uses: the ones it embeds when it embeds\n * any, otherwise the quoted families its font stacks name, ranked by how\n * often they appear.\n */\nexport function extractFonts(templateHtml: string): string[] {\n const css = stripCssComments(styleSheetText(templateHtml));\n const embedded = fontFaceFamilies(css);\n return (embedded.length > 0 ? embedded : stackFamilies(css)).slice(0, MAX_FONTS);\n}\n\n/**\n * Literal `#rrggbb`/`#rgb` colours in the design's CSS, most-used first.\n *\n * Complements the token extractor rather than duplicating it: tokens say\n * what the design DECLARES as its contract, this says what its stylesheets\n * actually paint with — including one-off colours never promoted to a token.\n * Function-syntax colours (`rgba()`, `color-mix()`, `oklch()`) are not\n * counted; they carry alpha or composition that a flat hex tally would\n * misrepresent.\n */\nexport function extractColors(templateHtml: string): DesignColorUse[] {\n const css = stripCssComments(styleSheetText(templateHtml));\n const counts = new Map<string, number>();\n const hexes = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})\\b/g;\n for (;;) {\n const found = hexes.exec(css);\n if (found === null) break;\n const raw = (found[1] ?? \"\").toLowerCase();\n const hex =\n raw.length === 3 ? `#${raw[0]}${raw[0]}${raw[1]}${raw[1]}${raw[2]}${raw[2]}` : `#${raw}`;\n counts.set(hex, (counts.get(hex) ?? 0) + 1);\n }\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : 1))\n .slice(0, MAX_COLORS)\n .map(([hex, count]): DesignColorUse => ({ hex, count }));\n}\n","// Read a design's effective `--ui-*` design tokens out of its stylesheets.\n//\n// Why resolution is needed rather than a grep: a design authored on the\n// @odla-ai/ui contract typically VENDORS the ui token sheet and then re-keys\n// it, so the final `:root` declares `--ui-accent: var(--accent)` while the\n// brand's own block declares `--accent: #e2562e` several blocks later. The\n// literal declaration is a var() reference; the useful answer is the colour.\n// So the extractor collects every custom property (not just `--ui-*`), folds\n// them in cascade order, and then resolves var() chains — including\n// `var(--x, fallback)` — against that table.\nimport { scanCustomProperties, styleSheetText } from \"./css-scan\";\nimport type { DesignTokenSets } from \"./types\";\n\n/** Deepest var() chain resolved before giving up (cycle guard). */\nconst MAX_VAR_DEPTH = 8;\n\n/** Selectors whose declarations count as document-level tokens. */\nconst DOC_SELECTOR = /(^|,)\\s*(:root|html)\\b|\\[data-theme\\s*=|\\.ui-invert\\b/;\n/** Selectors or at-rule preludes that put a declaration in the dark theme. */\nconst DARK_SELECTOR = /data-theme\\s*=\\s*[\"']?dark|prefers-color-scheme\\s*:\\s*dark|\\.ui-invert\\b/;\n\n/** Split `var(` arguments at the first top-level comma: name, fallback. */\nfunction splitVarArgs(inner: string): { name: string; fallback?: string } {\n let paren = 0;\n for (let i = 0; i < inner.length; i++) {\n const ch = inner[i];\n if (ch === \"(\") paren++;\n else if (ch === \")\") paren--;\n else if (ch === \",\" && paren === 0)\n return { name: inner.slice(0, i).trim(), fallback: inner.slice(i + 1).trim() };\n }\n return { name: inner.trim() };\n}\n\n/**\n * Substitute every `var(--name[, fallback])` in `value` using `table`,\n * recursively. An unresolvable reference falls back to its declared fallback\n * when it has one, and is otherwise left literal so the caller can see that\n * the value did not resolve.\n */\nexport function resolveVarRefs(\n value: string,\n table: ReadonlyMap<string, string>,\n depth = 0,\n): string {\n if (depth >= MAX_VAR_DEPTH || !value.includes(\"var(\")) return value;\n let out = \"\";\n let i = 0;\n for (;;) {\n const at = value.indexOf(\"var(\", i);\n if (at < 0) return out + value.slice(i);\n out += value.slice(i, at);\n let paren = 1;\n let j = at + \"var(\".length;\n for (; j < value.length && paren > 0; j++) {\n if (value[j] === \"(\") paren++;\n else if (value[j] === \")\") paren--;\n }\n // Unbalanced: emit the rest verbatim rather than losing it.\n if (paren > 0) return out + value.slice(at);\n const { name, fallback } = splitVarArgs(value.slice(at + \"var(\".length, j - 1));\n const referenced = table.get(name);\n const replacement =\n referenced !== undefined\n ? resolveVarRefs(referenced, table, depth + 1)\n : fallback !== undefined\n ? resolveVarRefs(fallback, table, depth + 1)\n : `var(${name})`;\n out += replacement;\n i = j;\n }\n}\n\n/** Fold declarations into light/dark custom-property tables (last wins). */\nfunction foldDeclarations(html: string): { light: Map<string, string>; dark: Map<string, string> } {\n const light = new Map<string, string>();\n const darkOverrides: [string, string][] = [];\n for (const decl of scanCustomProperties(styleSheetText(html))) {\n const innermost = decl.selectors[decl.selectors.length - 1] ?? \"\";\n if (!DOC_SELECTOR.test(innermost)) continue;\n if (decl.selectors.some((sel) => DARK_SELECTOR.test(sel))) darkOverrides.push([decl.name, decl.value]);\n else light.set(decl.name, decl.value);\n }\n const dark = new Map(light);\n for (const [name, value] of darkOverrides) dark.set(name, value);\n return { light, dark };\n}\n\n/** Resolve one table's `--ui-*` entries into a plain, var-free record. */\nfunction resolveUiTokens(table: ReadonlyMap<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [name, value] of table) {\n if (!name.startsWith(\"--ui-\")) continue;\n out[name] = resolveVarRefs(value, table);\n }\n return out;\n}\n\n/**\n * Extract the `--ui-*` tokens a design effectively declares, per theme, with\n * var() chains resolved to their computed text.\n *\n * Declarations are read from document-level selectors only (`:root`, `html`,\n * `[data-theme=…]`, `.ui-invert`); component-scoped custom properties are\n * ignored. Dark inherits every light token it does not override, mirroring\n * how theme sheets are written.\n */\nexport function extractDesignTokens(templateHtml: string): DesignTokenSets {\n const { light, dark } = foldDeclarations(templateHtml);\n return { light: resolveUiTokens(light), dark: resolveUiTokens(dark) };\n}\n","// Assemble the stored, shareable summary of a design.\n//\n// A digest is what everything downstream reads: the preview header, the\n// agent tools, the CLI's `digest.json`, and the palette decompiler. It is\n// deterministic — the same bundle always digests identically — so a stored\n// digest can be compared, diffed, and regenerated without surprises.\n//\n// Every list here is capped, and every cap that actually bit is named in\n// `truncated`. Silently shortening a heading outline would read to an agent\n// as \"that is the whole site\".\nimport { parseDesignBundle } from \"./bundle\";\nimport { extractOutline, extractTitle } from \"./outline\";\nimport { extractProps } from \"./props\";\nimport { extractColors, extractFonts } from \"./styles\";\nimport { extractDesignTokens } from \"./tokens\";\nimport type { DesignAssetGroup, DesignBundle, DesignDigest } from \"./types\";\n\n/** Most external-resource URLs carried into a digest. */\nexport const MAX_EXTERNALS = 24;\n\n/** Group manifest assets by MIME type, heaviest group first. */\nexport function groupAssets(bundle: DesignBundle): DesignAssetGroup[] {\n const groups = new Map<string, DesignAssetGroup>();\n for (const asset of bundle.assets) {\n const group = groups.get(asset.mime) ?? { mime: asset.mime, count: 0, bytes: 0 };\n group.count += 1;\n group.bytes += asset.bytes;\n groups.set(asset.mime, group);\n }\n return [...groups.values()].sort((a, b) => b.bytes - a.bytes || (a.mime < b.mime ? -1 : 1));\n}\n\n/**\n * Build the digest for an already-parsed bundle.\n *\n * `templateBytes` is measured in UTF-8 bytes, not characters, so it matches\n * what the CLI writes to disk for a template full of typographic quotes.\n */\nexport function digestDesignBundle(bundle: DesignBundle): DesignDigest {\n const template = bundle.template;\n const outline = extractOutline(template);\n const props = extractProps(template);\n const assetGroups = groupAssets(bundle);\n const title = extractTitle(template);\n const truncated: string[] = [];\n if (outline.truncated) truncated.push(\"outline\");\n if (props.truncated) truncated.push(\"props\");\n if (bundle.externals.length > MAX_EXTERNALS) truncated.push(\"externals\");\n\n return {\n format: \"claude-design-bundle/1\",\n ...(title ? { title } : {}),\n templateBytes: new TextEncoder().encode(template).byteLength,\n assetBytes: bundle.assets.reduce((total, asset) => total + asset.bytes, 0),\n assetCount: bundle.assets.length,\n assetGroups,\n externals: bundle.externals.slice(0, MAX_EXTERNALS),\n pageCount: bundle.pageOrder.length,\n tokens: extractDesignTokens(template),\n fonts: extractFonts(template),\n colors: extractColors(template),\n props: props.props,\n outline: outline.entries,\n ...(bundle.thumbnailSvg ? { thumbnailSvg: bundle.thumbnailSvg } : {}),\n truncated,\n };\n}\n\n/**\n * Parse a Claude Design standalone-HTML export and digest it in one step.\n * Throws {@link import(\"../errors\").BrandInputError} when the file is not a\n * design bundle.\n */\nexport function digestDesignHtml(html: string): DesignDigest {\n return digestDesignBundle(parseDesignBundle(html));\n}\n","// The WCAG contrast report attached to every palette proposal.\n//\n// Shared by `propose_palette` (colors the agent reasoned its way to) and\n// `propose_palette_from_design` (colors read back out of a design), so a\n// human reviews the same numbers whichever door a palette came through.\nimport { contrastRatio, pickTextOn } from \"./color/index\";\nimport type { Swatch, SwatchRole } from \"./types\";\n\nconst round2 = (n: number): number => Math.round(n * 100) / 100;\n\n/**\n * WCAG contrast ratios (2 dp) for a palette's key role pairs, stored\n * verbatim in the proposal payload so review is numbers, not vibes.\n *\n * Every foreground is measured against the palette's own `bg` (white when\n * it declares none), plus the readability of text placed on `primary`.\n */\nexport function contrastReport(swatches: Swatch[]): Record<string, number> {\n const byRole = (role: SwatchRole): string | undefined =>\n swatches.find((s) => s.role === role)?.hex;\n const bg = byRole(\"bg\") ?? \"#ffffff\";\n const report: Record<string, number> = {};\n const put = (label: string, fg?: string): void => {\n if (fg) report[label] = round2(contrastRatio(fg, bg));\n };\n put(\"text-on-bg\", byRole(\"text\"));\n put(\"primary-on-bg\", byRole(\"primary\"));\n put(\"good-on-bg\", byRole(\"good\"));\n put(\"warn-on-bg\", byRole(\"warn\"));\n put(\"danger-on-bg\", byRole(\"danger\"));\n const primary = byRole(\"primary\");\n if (primary) report[\"text-on-primary\"] = round2(contrastRatio(pickTextOn(primary), primary));\n return report;\n}\n","// The --ui-* custom-property names @odla-ai/brand emits, as data.\n//\n// PROVENANCE: mirrors @odla-ai/ui — the REQUIRED_TOKENS / ACCENT_TOKENS /\n// CHART_TOKENS / CHAT_TOKENS tiers in js/tokens.js, and the\n// :where([data-ui-accent]) re-declaration block in css/tokens.css.\n//\n// Why more than the required tier: a compiled token object doubles as a\n// runtime override-island payload, and CSS custom properties substitute\n// var() at computed-value time ON THE DECLARING ELEMENT. An island that\n// overrides --ui-accent alone would keep the :root-computed --ui-chart-1,\n// --ui-accent-glow, … stale. So besides the required tier the compiler\n// re-declares the whole accent-composing derived family — everything the\n// ui root's :where([data-ui-accent]) block re-declares, plus the remaining\n// chart series and chat roles so charts and chat surfaces recompute against\n// the brand palette too. test/tokens/map.test.ts cross-checks these lists\n// against the real @odla-ai/ui export, so they cannot drift silently.\n\n/**\n * The @odla-ai/ui required tier (js/tokens.js REQUIRED_TOKENS), in the ui\n * contract's order. The compiler always emits a concrete value for every\n * one of these.\n */\nexport const BRAND_REQUIRED_TOKENS = [\n \"--ui-bg\",\n \"--ui-surface\",\n \"--ui-surface-2\",\n \"--ui-text\",\n \"--ui-text-muted\",\n \"--ui-text-faint\",\n \"--ui-border\",\n \"--ui-border-strong\",\n \"--ui-accent\",\n \"--ui-accent-strong\",\n \"--ui-accent-soft\",\n \"--ui-on-accent\",\n \"--ui-good\",\n \"--ui-good-soft\",\n \"--ui-warn\",\n \"--ui-warn-soft\",\n \"--ui-danger\",\n \"--ui-danger-soft\",\n \"--ui-code-bg\",\n \"--ui-code-text\",\n \"--ui-shadow\",\n \"--ui-font-sans\",\n \"--ui-font-serif\",\n \"--ui-font-mono\",\n \"--ui-font-display\",\n] as const;\n\n/**\n * Accent-composing derived roles from the ui defaulted tier. All five\n * accent-family members of the :where([data-ui-accent]) re-declaration set\n * (--ui-accent-glow, --ui-accent-2, --ui-accent-2-soft, --ui-highlight,\n * --ui-focus) plus --ui-shadow-strong, which composes var(--ui-shadow) —\n * a token this compiler re-declares, so the island rule applies to it too.\n */\nexport const BRAND_DERIVED_TOKENS = [\n \"--ui-accent-glow\",\n \"--ui-accent-2\",\n \"--ui-accent-2-soft\",\n \"--ui-highlight\",\n \"--ui-focus\",\n \"--ui-shadow-strong\",\n] as const;\n\n/**\n * Chart roles the compiler emits: the six series slots (real palette\n * swatches when the palette carries them, ui var() compositions otherwise)\n * and the four accent-composing chart roles the :where([data-ui-accent])\n * block re-declares (band, band-strong, flow, glow).\n */\nexport const BRAND_CHART_TOKENS = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n \"--ui-chart-band\",\n \"--ui-chart-band-strong\",\n \"--ui-chart-flow\",\n \"--ui-chart-glow\",\n] as const;\n\n/**\n * Chat surface roles (js/tokens.js CHAT_TOKENS, complete). Two are in the\n * accent-swap set (user-bg, tool-accent); the other four compose surface /\n * text tokens the compiler also re-declares, so an island stays coherent.\n */\nexport const BRAND_CHAT_TOKENS = [\n \"--ui-chat-user-bg\",\n \"--ui-chat-user-text\",\n \"--ui-chat-assistant-bg\",\n \"--ui-chat-thinking-bg\",\n \"--ui-chat-thinking-text\",\n \"--ui-chat-tool-accent\",\n] as const;\n\n/**\n * Every token the compiler emits, in emission order — also the deterministic\n * declaration order renderTokensCss uses, so golden CSS fixtures are stable.\n */\nexport const BRAND_EMITTED_TOKENS: readonly string[] = [\n ...BRAND_REQUIRED_TOKENS,\n ...BRAND_DERIVED_TOKENS,\n ...BRAND_CHART_TOKENS,\n ...BRAND_CHAT_TOKENS,\n];\n","// Light → dark token derivation.\n//\n// Neutrals (bg / text ladder / borders / code text) flip around OKLab L 0.5:\n// L' = 1 − L reflected, then squeezed into [DARK_FLIP_L_MIN,\n// DARK_FLIP_L_MAX] so the background lands dark but never black and text\n// lands light but never pure white. Chroma and hue are untouched, so tinted\n// neutrals keep their brand tint.\n//\n// Surfaces are the one place a mirror is wrong: light surfaces sit ABOVE\n// the light bg (lighter), so mirroring would drop them BELOW the dark bg —\n// inverted elevation. Instead the surface ladder is rebuilt upward from the\n// derived dark bg (the @odla-ai/ui dark-neutral pattern: bg < surface <\n// surface-2), reusing the light ladder's own lightness gaps as rung heights\n// (with a small minimum so equal-ish inputs still separate).\n//\n// Accents (accent family, statuses) and chart series keep their hue/chroma\n// and are re-lightened with adjustLightnessUntil until they clear WCAG bars\n// against the derived dark bg: 4.5:1 for the accent family and statuses\n// (SC 1.4.3), 3:1 for chart series (SC 1.4.11 graphics). --ui-on-accent is\n// re-picked against the dark accent. Everything else — var()/color-mix()\n// compositions, font stacks, focus ring — passes through unchanged and\n// recomputes in CSS against the dark values (--ui-shadow is the one literal\n// that gets the ui dark shadow instead).\n\nimport {\n adjustLightnessUntil,\n clampToGamut,\n contrastRatio,\n hexToOklch,\n oklchToHex,\n pickTextOn,\n} from \"../color\";\nimport type { BrandTokens } from \"./types\";\n\n/** Darkest OKLab L a flipped neutral may take — the dark bg floor (never black). */\nexport const DARK_FLIP_L_MIN = 0.2;\n\n/** Lightest OKLab L a flipped neutral may take — keeps flipped text off pure white. */\nexport const DARK_FLIP_L_MAX = 0.95;\n\n/** The ui neutral dark shadow (css/tokens.css `[data-theme=\"dark\"]` value). */\nconst DARK_SHADOW = \"0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.35)\";\n\nconst HEX6 = /^#[0-9a-f]{6}$/;\n\n/** Neutral ladder: flipped around L 0.5 with the floor/ceiling squeeze.\n * Surfaces/code-bg are here only as a fallback — with a hex bg present they\n * are rebuilt upward from the dark bg instead (see file header). */\nconst NEUTRAL_FLIP = new Set([\n \"--ui-bg\",\n \"--ui-surface\",\n \"--ui-surface-2\",\n \"--ui-text\",\n \"--ui-text-muted\",\n \"--ui-text-faint\",\n \"--ui-border\",\n \"--ui-border-strong\",\n \"--ui-code-bg\",\n \"--ui-code-text\",\n]);\n\n/** Minimum OKLab ΔL between dark surface rungs, so elevation always reads. */\nconst MIN_RUNG = 0.02;\n\n/** Re-lightened until ≥ 4.5:1 on the dark bg (readable as text). */\nconst ACCENT_AA = [\n \"--ui-accent\",\n \"--ui-accent-strong\",\n \"--ui-accent-2\",\n \"--ui-highlight\",\n \"--ui-good\",\n \"--ui-warn\",\n \"--ui-danger\",\n] as const;\n\n/** Re-lightened until ≥ 3:1 on the dark bg (graphics bar). */\nconst CHART_UI = [\n \"--ui-chart-1\",\n \"--ui-chart-2\",\n \"--ui-chart-3\",\n \"--ui-chart-4\",\n \"--ui-chart-5\",\n \"--ui-chart-6\",\n] as const;\n\nfunction flipNeutral(hex: string): string {\n const { L, C, h } = hexToOklch(hex);\n const flipped = DARK_FLIP_L_MIN + (1 - L) * (DARK_FLIP_L_MAX - DARK_FLIP_L_MIN);\n return oklchToHex(clampToGamut({ L: flipped, C, h }));\n}\n\n/**\n * Rebuild bg < surface < surface-2 upward from the dark bg, using the light\n * ladder's own |ΔL| gaps as rung heights (floored at MIN_RUNG). code-bg\n * follows surface-2 when the light map aliased them, else takes its own\n * bg-relative rung. Mutates `out`; skips any token that is absent/non-hex.\n */\nfunction rebuildSurfaces(out: BrandTokens, light: BrandTokens, lightBgL: number, darkBgL: number): void {\n const lightSurface = light[\"--ui-surface\"];\n const lightSurface2 = light[\"--ui-surface-2\"];\n let surfaceDarkL: number | undefined;\n let surfaceLightL = lightBgL;\n if (lightSurface !== undefined && HEX6.test(lightSurface)) {\n const { L, C, h } = hexToOklch(lightSurface);\n surfaceLightL = L;\n surfaceDarkL = darkBgL + Math.max(Math.abs(L - lightBgL), MIN_RUNG);\n out[\"--ui-surface\"] = oklchToHex(clampToGamut({ L: surfaceDarkL, C, h }));\n }\n if (lightSurface2 !== undefined && HEX6.test(lightSurface2)) {\n const { L, C, h } = hexToOklch(lightSurface2);\n const base = surfaceDarkL ?? darkBgL + MIN_RUNG;\n const L2 = base + Math.max(Math.abs(L - surfaceLightL), MIN_RUNG);\n out[\"--ui-surface-2\"] = oklchToHex(clampToGamut({ L: L2, C, h }));\n }\n const lightCodeBg = light[\"--ui-code-bg\"];\n if (lightCodeBg !== undefined && HEX6.test(lightCodeBg)) {\n if (lightCodeBg === lightSurface2 && out[\"--ui-surface-2\"] !== undefined) {\n out[\"--ui-code-bg\"] = out[\"--ui-surface-2\"];\n } else {\n const { L, C, h } = hexToOklch(lightCodeBg);\n const codeL = darkBgL + Math.max(Math.abs(L - lightBgL), MIN_RUNG);\n out[\"--ui-code-bg\"] = oklchToHex(clampToGamut({ L: codeL, C, h }));\n }\n }\n}\n\n/** Lighten (else darken; else pickTextOn) until ≥ `min`:1 on `bg`. */\nfunction relight(hex: string, bg: string, min: number): string {\n const pred = (c: string): boolean => contrastRatio(c, bg) >= min;\n return (\n adjustLightnessUntil(hex, pred, \"lighten\") ??\n adjustLightnessUntil(hex, pred, \"darken\") ??\n pickTextOn(bg)\n );\n}\n\n/**\n * Derives the dark-mode token map from a light one (see the file header for\n * the flip / re-lighten / passthrough rules). Pure and total: tokens the\n * rules don't recognize — including non-hex values in recognized slots —\n * pass through unchanged, and the result always has exactly the input's\n * key set. Deterministic, never throws.\n */\nexport function deriveDarkTokens(light: BrandTokens): BrandTokens {\n const out: BrandTokens = {};\n for (const [name, value] of Object.entries(light)) {\n if (name === \"--ui-shadow\") out[name] = DARK_SHADOW;\n else if (NEUTRAL_FLIP.has(name) && HEX6.test(value)) out[name] = flipNeutral(value);\n else out[name] = value;\n }\n\n const bg = out[\"--ui-bg\"];\n const lightBg = light[\"--ui-bg\"];\n if (bg === undefined || !HEX6.test(bg) || lightBg === undefined || !HEX6.test(lightBg)) return out;\n\n rebuildSurfaces(out, light, hexToOklch(lightBg).L, hexToOklch(bg).L);\n\n for (const name of [\"--ui-text\", \"--ui-text-muted\"]) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 4.5);\n }\n const codeBg = out[\"--ui-code-bg\"];\n const codeText = out[\"--ui-code-text\"];\n if (codeText !== undefined && HEX6.test(codeText))\n out[\"--ui-code-text\"] = relight(codeText, codeBg !== undefined && HEX6.test(codeBg) ? codeBg : bg, 4.5);\n\n for (const name of ACCENT_AA) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 4.5);\n }\n for (const name of CHART_UI) {\n const v = out[name];\n if (v !== undefined && HEX6.test(v)) out[name] = relight(v, bg, 3);\n }\n\n const accent = out[\"--ui-accent\"];\n const onAccent = out[\"--ui-on-accent\"];\n if (accent !== undefined && HEX6.test(accent) && onAccent !== undefined && HEX6.test(onAccent))\n out[\"--ui-on-accent\"] = pickTextOn(accent);\n\n return out;\n}\n","// Compiled tokens → theme CSS text.\n//\n// The output's shape mirrors a real @odla-ai/ui theme tokens file\n// (themes/juniper/tokens.css): a light block, a `[data-theme=\"dark\"]`\n// attribute block, the same dark values repeated under\n// `@media (prefers-color-scheme: dark)` guarded by\n// `:root:not([data-theme=\"light\"])` (so an explicit light preference beats\n// the system's dark scheme), and optionally a `.ui-invert` island block.\n// The attribute/media blocks carry only the tokens that CHANGE in dark —\n// the ui convention, since var()/color-mix() compositions declared in the\n// light block recompute on the same element. The `.ui-invert` island gets\n// the FULL dark payload: on an island, root-computed composites would be\n// stale (see roles.ts).\n//\n// Declarations render in BRAND_EMITTED_TOKENS order (unknown tokens last,\n// alphabetically), so output is deterministic and golden-testable.\n\nimport { BRAND_EMITTED_TOKENS } from \"./roles\";\nimport type { BrandTokens } from \"./types\";\n\n/** Options for {@link renderTokensCss}. */\nexport interface RenderTokensCssOptions {\n /** Dark-mode tokens (deriveDarkTokens output). Omit for a light-only sheet. */\n dark?: BrandTokens;\n /**\n * Selector the light block declares on (default \":root\"). A scoped\n * selector (e.g. `[data-brand=\"acme\"]`) gets its dark blocks nested under\n * the document-level theme guards instead of replacing them.\n */\n selector?: string;\n /**\n * Also emit a `.ui-invert` block carrying the full dark payload, so the\n * subtree renders dark regardless of the global mode. Requires `dark`.\n */\n includeInvert?: boolean;\n}\n\nconst HEADER =\n \"/* Generated by @odla-ai/brand — @odla-ai/ui token overrides; pair with @odla-ai/ui css/tokens.css. */\";\n\nconst ORDER = new Map<string, number>(\n BRAND_EMITTED_TOKENS.map((name, i): [string, number] => [name, i]),\n);\n\n/** Emission order: BRAND_EMITTED_TOKENS index, then unknown names A→Z. */\nfunction orderedNames(tokens: BrandTokens): string[] {\n return Object.keys(tokens).sort((a, b) => {\n const ia = ORDER.get(a);\n const ib = ORDER.get(b);\n if (ia !== undefined && ib !== undefined) return ia - ib;\n if (ia !== undefined) return -1;\n if (ib !== undefined) return 1;\n return a < b ? -1 : a > b ? 1 : 0;\n });\n}\n\nfunction renderBlock(\n selector: string,\n tokens: BrandTokens,\n names: readonly string[],\n indent: string,\n lead?: string,\n): string {\n const lines: string[] = [];\n if (lead !== undefined) lines.push(`${indent} ${lead}`);\n for (const name of names) lines.push(`${indent} ${name}: ${tokens[name]};`);\n if (lines.length === 0) return `${indent}${selector} {\\n${indent}}`;\n return `${indent}${selector} {\\n${lines.join(\"\\n\")}\\n${indent}}`;\n}\n\n/**\n * Renders a compiled token map (plus optional dark map) as CSS text shaped\n * like an @odla-ai/ui theme tokens file — see the file header for the block\n * structure and ordering guarantees. Deterministic for a given input.\n */\nexport function renderTokensCss(light: BrandTokens, opts: RenderTokensCssOptions = {}): string {\n const selector = opts.selector ?? \":root\";\n const scoped = selector !== \":root\";\n const parts: string[] = [HEADER, renderBlock(selector, light, orderedNames(light), \"\")];\n\n const dark = opts.dark;\n if (dark !== undefined) {\n const diffNames = orderedNames(dark).filter((name) => light[name] !== dark[name]);\n if (diffNames.length > 0) {\n const attrSelector = scoped\n ? `[data-theme=\"dark\"] ${selector}, ${selector}[data-theme=\"dark\"]`\n : `[data-theme=\"dark\"]`;\n const mediaSelector = scoped\n ? `:root:not([data-theme=\"light\"]) ${selector}`\n : `:root:not([data-theme=\"light\"])`;\n parts.push(renderBlock(attrSelector, dark, diffNames, \"\"));\n parts.push(\n `@media (prefers-color-scheme: dark) {\\n${renderBlock(mediaSelector, dark, diffNames, \" \")}\\n}`,\n );\n }\n if (opts.includeInvert === true) {\n parts.push(renderBlock(\".ui-invert\", dark, orderedNames(dark), \"\", \"color-scheme: dark;\"));\n }\n }\n return `${parts.join(\"\\n\\n\")}\\n`;\n}\n","// The compiler facade: palette + typography (+ author overrides) →\n// { light, dark, warnings }. Light comes from mapPaletteToTokens, overrides\n// are layered on last (so authors can pin any token, including ones this\n// compiler doesn't own, like --ui-radius-md), and dark derives from the\n// FINAL light map — an overridden accent flows into the dark derivation.\n//\n// Never throws on bad palettes: map.ts drops invalid swatches and derives\n// missing roles (each degradation becomes a TokenWarning), and malformed\n// overrides are skipped with a warning rather than rejected.\n\nimport { deriveDarkTokens } from \"./dark\";\nimport { mapPaletteToTokens } from \"./map\";\nimport type { CompiledBrandTokens, CompileInput, TokenWarning } from \"./types\";\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\n\n/** Layer `overrides` onto `light` in place; malformed entries warn + skip. */\nfunction applyOverrides(\n light: Record<string, string>,\n overrides: unknown,\n warnings: TokenWarning[],\n): void {\n if (overrides === undefined) return;\n if (!isRecord(overrides)) {\n warnings.push({ token: \"--ui-accent\", message: \"overrides ignored: not an object\" });\n return;\n }\n for (const [name, value] of Object.entries(overrides)) {\n if (!name.startsWith(\"--\")) {\n warnings.push({ token: name, message: \"override ignored: token names must start with --\" });\n continue;\n }\n if (typeof value !== \"string\" || value.trim() === \"\") {\n warnings.push({ token: name, message: \"override ignored: value must be a non-empty string\" });\n continue;\n }\n light[name] = value.trim();\n }\n}\n\n/**\n * Compiles a brand palette into @odla-ai/ui design tokens: a light map\n * covering every name in BRAND_EMITTED_TOKENS (plus overrides), a dark map\n * derived from it (same key set), and the warnings accumulated along the\n * way — missing-role fallbacks and contrast adjustments (`adjustedFrom`).\n *\n * Both maps double as runtime override-island payloads: every derived\n * default that composes the accent family is re-declared, so applying the\n * map on any element recomputes charts, softs, focus and chat roles against\n * the brand palette (see roles.ts). Deterministic; never throws on bad\n * palettes.\n */\nexport function compileBrandTokens(input: CompileInput): CompiledBrandTokens {\n const { tokens: light, warnings } = mapPaletteToTokens(input);\n applyOverrides(light, input?.overrides, warnings);\n const dark = deriveDarkTokens(light);\n return { light, dark, warnings };\n}\n","// Asset tools: view_asset feeds real uploaded bytes to the model as an\n// image/document block inside the tool result (the vision path), and\n// record_asset_analysis persists what the model saw through the validated\n// ops layer. view_asset output is model-visible content fetched from\n// storage, so the tool declares `tool_untrusted:view_asset` taint.\n// @odla-ai/ai is imported for types only.\nimport type { DocumentBlock, ImageBlock, ImageMediaType, TextBlock, ToolDef, ToolOutput } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset } from \"../types\";\nimport { assertAnalysis } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Byte cap for in-conversation asset viewing (4.5 MiB — providers reject\n * larger inline payloads well before context does). */\nexport const MAX_VIEW_BYTES = 4_718_592;\n\nconst IMAGE_TYPES: ReadonlySet<string> = new Set([\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]);\n\n/**\n * Base64-encode bytes without assuming a platform: `btoa` over a chunked\n * binary string where available (workerd, browsers, Node ≥ 16), `Buffer`\n * otherwise. Chunking keeps `String.fromCharCode` off the argument-count\n * cliff for multi-megabyte assets.\n */\nexport function base64FromBytes(bytes: Uint8Array): string {\n if (typeof btoa === \"function\") {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x2000) {\n binary += String.fromCharCode(...bytes.subarray(i, i + 0x2000));\n }\n return btoa(binary);\n }\n return Buffer.from(bytes).toString(\"base64\");\n}\n\nconst bareType = (ct: string): string => (ct.split(\";\")[0] ?? \"\").trim().toLowerCase();\n\nfunction viewOutput(asset: BrandAsset, bytes: Uint8Array, contentType: string): ToolOutput {\n const caption: TextBlock = {\n type: \"text\",\n text: `Asset ${asset.id} (${asset.kind}, ${contentType}, ${bytes.byteLength} bytes${asset.title ? `, \"${asset.title}\"` : \"\"}):`,\n };\n if (IMAGE_TYPES.has(contentType)) {\n const image: ImageBlock = {\n type: \"image\",\n source: { type: \"base64\", mediaType: contentType as ImageMediaType, data: base64FromBytes(bytes) },\n };\n return { content: [caption, image] };\n }\n const document: DocumentBlock = {\n type: \"document\",\n source: { type: \"base64\", mediaType: \"application/pdf\", data: base64FromBytes(bytes) },\n };\n return { content: [caption, document] };\n}\n\n/**\n * The asset tools, scoped to the context's book: `view_asset` (fetch the\n * stored bytes and return them as an image/PDF block, with size and type\n * gates) and `record_asset_analysis` (persist the model's description,\n * dominant colors, and tags onto the asset row).\n */\nexport function assetTools(ctx: BrandToolCtx): ToolDef[] {\n const loadAsset = async (assetId: string): Promise<BrandAsset> => {\n const book = await ctx.loadBook();\n const res = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: assetId, bookId: ctx.bookId } },\n book: {},\n },\n });\n const row = (res[BRAND_NS.asset] ?? [])[0] as\n | (BrandAsset & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n row.status !== \"live\" ||\n row.deletedAt ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== book.id\n ) throw new BrandNotFoundError(`asset ${assetId}`);\n return row;\n };\n\n const viewAsset: ToolDef = {\n name: \"view_asset\",\n description:\n \"Look at an uploaded asset: fetches its bytes and returns the image (png/jpeg/gif/webp) or PDF for you to view. Other types cannot be viewed in-conversation.\",\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: { assetId: { type: \"string\", description: \"The asset row id from list_assets.\" } },\n },\n outputTaint: [\"tool_untrusted:view_asset\"],\n handler: ctx.guard(async (input) => {\n const asset = await loadAsset(String(input.assetId));\n if (!ctx.visionInToolResults) {\n return {\n content:\n `This model cannot take images inside tool results. Asset ${asset.id} must be attached ` +\n \"as a pre-turn image by the host instead — ask the human to re-send their message \" +\n \"referencing the asset (the dispatcher attaches it up front), or describe it from \" +\n \"what they tell you.\",\n };\n }\n const read = await ctx.authority(\"brand.read\");\n const fetched = await ctx.readAssetContent(asset.id);\n if (fetched.bytes.byteLength > MAX_VIEW_BYTES) {\n return {\n content:\n `Asset ${asset.id} is ${fetched.bytes.byteLength} bytes — over the ${MAX_VIEW_BYTES}-byte ` +\n \"(4.5 MB) in-conversation viewing cap. Ask the human for a smaller export of this file.\",\n };\n }\n const served = bareType(fetched.contentType);\n const effective = IMAGE_TYPES.has(served) || served === \"application/pdf\" ? served : bareType(asset.contentType);\n if (!IMAGE_TYPES.has(effective) && effective !== \"application/pdf\") {\n return {\n content:\n `Asset ${asset.id} is ${effective} — stored but not viewable in-conversation. ` +\n \"Ask the human to describe it, or to upload a PNG/JPEG export you can view.\",\n };\n }\n return viewOutput(asset, fetched.bytes, effective);\n }),\n };\n\n const recordAnalysis: ToolDef = {\n name: \"record_asset_analysis\",\n description:\n \"Record what you observed in an asset you viewed. Uses guarded analysis revisions so concurrent agents cannot overwrite each other silently.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\", \"description\", \"dominantColors\", \"tags\"],\n properties: {\n assetId: { type: \"string\" },\n description: { type: \"string\", description: \"What the asset shows (max 2000 chars).\" },\n dominantColors: { type: \"array\", items: { type: \"string\" }, maxItems: 12, description: \"Dominant colors as hex.\" },\n tags: { type: \"array\", items: { type: \"string\" }, maxItems: 24 },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadAsset(String(input.assetId));\n await ctx.authority(\"brand.edit\");\n const analysis = assertAnalysis({\n description: input.description,\n dominantColors: input.dominantColors,\n tags: input.tags,\n });\n const updated = await ctx.recordAssetAnalysis({\n mutationId: ctx.newId(),\n assetId: asset.id,\n analysis,\n expectedAnalysisRevision: asset.analysisRevision,\n });\n if (\n updated.id !== asset.id ||\n updated.bookId !== ctx.bookId ||\n updated.status !== \"live\" ||\n updated.analysisRevision !== asset.analysisRevision + 1 ||\n updated.analyzedBy !== ctx.self.selfId\n ) throw new BrandNotFoundError(\"asset analysis bridge returned invalid state\");\n return {\n content: `Recorded analysis for asset ${asset.id}: ${analysis.dominantColors.length} dominant color(s), ${analysis.tags.length} tag(s).`,\n };\n }),\n };\n\n return [viewAsset, recordAnalysis];\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandBook } from \"../types\";\nimport { capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Validate an optional proposal source against the exact live linked book. */\nexport async function proposalSourceAssetId(\n ctx: BrandToolCtx,\n book: BrandBook,\n value: unknown,\n): Promise<string | undefined> {\n if (value === undefined) return undefined;\n const sourceAssetId = capString(value, \"sourceAssetId\", 200);\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: {\n where: { id: sourceAssetId, bookId: book.id, status: \"live\" },\n limit: 2,\n },\n book: { $: { limit: 2 } },\n },\n });\n const rows = result[BRAND_NS.asset] ?? [];\n const asset = rows.length === 1\n ? rows[0] as {\n id?: string;\n bookId?: string;\n status?: string;\n deletedAt?: number;\n book?: Array<{ id: string }>;\n }\n : undefined;\n if (\n !asset ||\n asset.id !== sourceAssetId ||\n asset.bookId !== book.id ||\n asset.status !== \"live\" ||\n asset.deletedAt !== undefined ||\n !Array.isArray(asset.book) ||\n asset.book.length !== 1 ||\n asset.book[0]?.id !== book.id\n ) throw new BrandInputError(\n \"sourceAssetId must be a live asset in this brand book\",\n );\n return sourceAssetId;\n}\n","// Non-palette brand-facet proposal tool. Agent-authored changes never touch\n// the live natural-key section; a human decision route applies accepted\n// content as an approved section with a durable receipt.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport {\n SECTION_KINDS,\n type SectionKind,\n} from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { assertSectionContent, capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\nimport { proposalSourceAssetId } from \"./source-asset\";\n\nconst PROPOSABLE = SECTION_KINDS.filter((kind) => kind !== \"palette\");\n\n/** `update_section` validates a draft and parks it as an OPEN proposal. */\nexport function bookTools(ctx: BrandToolCtx): ToolDef[] {\n return [{\n name: \"update_section\",\n description:\n \"Propose a typography, voice, logo, or imagery section revision for human approval. This never overwrites the live approved section.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"kind\", \"content\", \"rationale\"],\n properties: {\n kind: { type: \"string\", enum: PROPOSABLE },\n content: { type: \"object\", description: \"The complete proposed section payload.\" },\n rationale: { type: \"string\", description: \"Why this revision should replace the live section.\" },\n sourceAssetId: {\n type: \"string\",\n description: \"Optional exact live Brand asset that grounds this revision.\",\n },\n },\n },\n handler: ctx.guard(async (input) => {\n const allowed = new Set([\"kind\", \"content\", \"rationale\", \"sourceAssetId\"]);\n if (Object.keys(input).some((key) => !allowed.has(key)))\n throw new BrandInputError(\"section proposal has unknown fields\");\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const kind = input.kind as SectionKind;\n if (kind === \"palette\" || !PROPOSABLE.includes(kind))\n throw new BrandInputError(`kind must be one of: ${PROPOSABLE.join(\", \")}`);\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const sourceAssetId = await proposalSourceAssetId(\n ctx,\n book,\n input.sourceAssetId,\n );\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind,\n payload: {\n content: assertSectionContent(kind, input.content),\n },\n rationale,\n ...(sourceAssetId ? { sourceAssetId } : {}),\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== kind ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n return {\n content:\n `Parked ${kind} section proposal ${proposal.id}. The live section is unchanged; ` +\n \"a human must approve this exact revision.\",\n };\n }),\n }];\n}\n","// Color-exploration + proposal tools. analyze_color / evaluate_contrast are\n// pure math over the color engine (the agent's grounding for every hex it\n// suggests); propose_palette PARKS a proposal for human review — it never\n// activates anything. Proposal resolution is intentionally absent from the\n// agent skill; a human uses createBrandRoutes' guarded approval endpoint.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport {\n analogous,\n complementary,\n contrastRatio,\n derivePalette,\n hexToOklch,\n meetsAA,\n meetsAAA,\n monochrome,\n nearestNamedColor,\n pickTextOn,\n relativeLuminance,\n splitComplementary,\n tetradic,\n tintShadeRamp,\n triadic,\n} from \"../color/index\";\nimport { BrandInputError } from \"../errors\";\nimport { contrastReport } from \"../palette-report\";\nimport type { Swatch, SwatchRole } from \"../types\";\nimport { assertHex, assertSwatches, capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\nimport { proposalSourceAssetId } from \"./source-asset\";\n\nconst r2 = (n: number): string => n.toFixed(2);\nconst pf = (ok: boolean): string => (ok ? \"pass\" : \"FAIL\");\n\nconst verdict = (ratio: number): string =>\n `${r2(ratio)}:1 — AA text ${pf(meetsAA(ratio))}, AA large/ui ${pf(meetsAA(ratio, \"large-text\"))}, AAA text ${pf(meetsAAA(ratio))}`;\n\n/** Harmony strategies propose_palette accepts, mapped to the seed companions\n * that replace the derived secondary/highlight (in that order). */\nconst HARMONY_COMPANIONS: Record<string, (seed: string) => string[]> = {\n complementary: (s) => [complementary(s)],\n analogous: (s) => [...analogous(s)],\n triadic: (s) => [...triadic(s)],\n split: (s) => [...splitComplementary(s)],\n tetradic: (s) => tetradic(s).slice(0, 2),\n monochrome: (s) => monochrome(s, 4).slice(1, 3),\n};\n\nfunction applyHarmony(swatches: Swatch[], seedHex: string, harmony: unknown): Swatch[] {\n if (typeof harmony !== \"string\" || !(harmony in HARMONY_COMPANIONS)) {\n throw new BrandInputError(`harmony must be one of: ${Object.keys(HARMONY_COMPANIONS).join(\", \")}`);\n }\n const [secondary, highlight] = HARMONY_COMPANIONS[harmony]!(seedHex);\n return swatches.map((s) => {\n const hex = s.role === \"secondary\" ? secondary : s.role === \"highlight\" ? highlight : undefined;\n if (!hex) return s;\n return { ...s, hex, name: nearestNamedColor(hex).name, rationale: `${harmony} companion of the seed` };\n });\n}\n\nconst INCLUDE_SECTIONS = [\"harmony\", \"ramp\"] as const;\n\nfunction analyzeLines(hex: string, include: string[]): string[] {\n const lch = hexToOklch(hex);\n const named = nearestNamedColor(hex);\n const lines = [\n `${hex} — nearest CSS name: ${named.name} (ΔEOK ${named.deltaEOK.toFixed(3)})`,\n `OKLCH: L ${lch.L.toFixed(3)}, C ${lch.C.toFixed(3)}, h ${lch.h.toFixed(1)}°`,\n `relative luminance ${relativeLuminance(hex).toFixed(3)}; contrast ${r2(contrastRatio(hex, \"#ffffff\"))}:1 on white, ${r2(contrastRatio(hex, \"#000000\"))}:1 on black`,\n `readable text on it: ${pickTextOn(hex)}`,\n ];\n if (include.includes(\"harmony\")) {\n const [aMinus, aPlus] = analogous(hex);\n const [tMinus, tPlus] = triadic(hex);\n const [sMinus, sPlus] = splitComplementary(hex);\n lines.push(\n `harmony — complementary ${complementary(hex)}; analogous ${aMinus} ${aPlus}; triadic ${tMinus} ${tPlus}; split ${sMinus} ${sPlus}`,\n );\n }\n if (include.includes(\"ramp\")) lines.push(`ramp — ${tintShadeRamp(hex).join(\" \")}`);\n return lines;\n}\n\n/**\n * The palette tools: `analyze_color`, `evaluate_contrast` (pure math),\n * `propose_palette` (writes an OPEN proposal with an automatic contrast\n * report). Resolution is deliberately not an agent tool.\n */\nexport function paletteTools(ctx: BrandToolCtx): ToolDef[] {\n const analyzeColor: ToolDef = {\n name: \"analyze_color\",\n description:\n \"Analyze one color: nearest CSS name, OKLCH coordinates, luminance, contrast on white/black. Optionally include harmony companions and a tint/shade ramp.\",\n inputSchema: {\n type: \"object\",\n required: [\"hex\"],\n properties: {\n hex: { type: \"string\", description: \"#rgb or #rrggbb\" },\n include: { type: \"array\", items: { type: \"string\", enum: [...INCLUDE_SECTIONS] } },\n },\n },\n handler: ctx.guard(async (input) => {\n const hex = assertHex(input.hex, \"hex\");\n const include = input.include === undefined ? [] : input.include;\n if (!Array.isArray(include) || include.some((s) => !(INCLUDE_SECTIONS as readonly unknown[]).includes(s))) {\n throw new BrandInputError(`include entries must be one of: ${INCLUDE_SECTIONS.join(\", \")}`);\n }\n return { content: analyzeLines(hex, include as string[]).join(\"\\n\") };\n }),\n };\n\n const evaluateContrast: ToolDef = {\n name: \"evaluate_contrast\",\n description:\n \"WCAG 2.1 contrast: pass pairs ([{fg,bg}]) for specific combinations, or hexes ([…]) for every pairwise ratio. Reports AA/AAA verdicts.\",\n inputSchema: {\n type: \"object\",\n properties: {\n pairs: {\n type: \"array\",\n maxItems: 20,\n items: { type: \"object\", required: [\"fg\", \"bg\"], properties: { fg: { type: \"string\" }, bg: { type: \"string\" } } },\n },\n hexes: { type: \"array\", minItems: 2, maxItems: 8, items: { type: \"string\" } },\n },\n },\n handler: ctx.guard(async (input) => {\n if (Array.isArray(input.pairs) && input.pairs.length > 0) {\n if (input.pairs.length > 20) throw new BrandInputError(\"pairs must have at most 20 entries\");\n const lines = input.pairs.map((raw, i) => {\n const p = (raw ?? {}) as Record<string, unknown>;\n const fg = assertHex(p.fg, `pairs[${i}].fg`);\n const bg = assertHex(p.bg, `pairs[${i}].bg`);\n return `${fg} on ${bg}: ${verdict(contrastRatio(fg, bg))}`;\n });\n return { content: lines.join(\"\\n\") };\n }\n if (Array.isArray(input.hexes)) {\n if (input.hexes.length < 2 || input.hexes.length > 8) {\n throw new BrandInputError(\"hexes must have 2 to 8 entries\");\n }\n const hexes = input.hexes.map((h, i) => assertHex(h, `hexes[${i}]`));\n const lines: string[] = [];\n for (let i = 0; i < hexes.length; i++) {\n for (let j = i + 1; j < hexes.length; j++) {\n lines.push(`${hexes[i]} vs ${hexes[j]}: ${verdict(contrastRatio(hexes[i]!, hexes[j]!))}`);\n }\n }\n return { content: lines.join(\"\\n\") };\n }\n throw new BrandInputError(\"provide pairs ([{fg,bg}, …]) or hexes ([#rrggbb, …])\");\n }),\n };\n\n const proposePalette: ToolDef = {\n name: \"propose_palette\",\n description:\n \"Park a palette proposal for human review (does NOT change the brand). Pass explicit swatches, or a seedHex (and optional harmony) to derive a full palette. A WCAG contrast report is attached automatically.\",\n acceptsTaint: [\"tool_untrusted:view_asset\"],\n inputSchema: {\n type: \"object\",\n required: [\"name\", \"rationale\"],\n properties: {\n name: { type: \"string\" },\n rationale: { type: \"string\", description: \"Why these colors — cite assets, harmony, contrast.\" },\n seedHex: { type: \"string\" },\n harmony: { type: \"string\", enum: Object.keys(HARMONY_COMPANIONS) },\n sourceAssetId: {\n type: \"string\",\n description: \"Optional exact asset id that grounded this palette.\",\n },\n swatches: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"role\", \"hex\"],\n properties: {\n role: { type: \"string\" },\n hex: { type: \"string\" },\n name: { type: \"string\" },\n rationale: { type: \"string\" },\n },\n },\n },\n },\n },\n handler: ctx.guard(async (input, toolCtx) => {\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const name = capString(input.name, \"name\", 120);\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const sourceAssetId = await proposalSourceAssetId(\n ctx,\n book,\n input.sourceAssetId,\n );\n const seedHex = input.seedHex === undefined ? undefined : assertHex(input.seedHex, \"seedHex\");\n let swatches: Swatch[];\n if (input.swatches !== undefined) {\n swatches = assertSwatches(input.swatches);\n } else {\n if (!seedHex) throw new BrandInputError(\"provide swatches, or a seedHex to derive a palette from\");\n swatches = derivePalette(seedHex);\n if (input.harmony !== undefined) swatches = applyHarmony(swatches, seedHex, input.harmony);\n }\n const report = contrastReport(swatches);\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind: \"palette\",\n payload: {\n name,\n swatches,\n ...(seedHex ? { seedHex } : {}),\n contrastReport: report,\n },\n rationale,\n ...(sourceAssetId ? { sourceAssetId } : {}),\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== \"palette\" ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n const reportText = Object.entries(report).map(([k, v]) => `${k} ${r2(v)}:1`).join(\", \");\n return {\n content:\n `Parked palette proposal ${proposal.id} (\"${name}\", ${swatches.length} swatches` +\n `${seedHex ? `, seeded from ${seedHex}` : \"\"}). Contrast: ${reportText}. ` +\n \"Awaiting a human decision in the brand approval surface.\",\n };\n }),\n };\n\n return [analyzeColor, evaluateContrast, proposePalette];\n}\n","// Design tools: how an agent reads a Claude Design without eating it.\n//\n// A bundle is megabytes of base64 and its template is ~150 KB of markup —\n// neither belongs in a context window. So the tools serve three different\n// resolutions of the same design, and the model picks:\n//\n// read_design the digest: tokens, fonts, props, heading outline.\n// Kilobytes. Enough to plan a build.\n// read_design_source a WINDOW of the real template, by offset or by\n// search term. For porting exact markup.\n// propose_palette_from_design\n// the design's own --ui-* declarations, read back as\n// brand swatches and parked as a proposal.\n//\n// The third is the one that changes anything, and it changes nothing on its\n// own: it parks a proposal a human resolves, exactly like propose_palette.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport { BRAND_NS, DESIGN_ASSET_KIND } from \"../constants\";\nimport { swatchesFromDesignTokens } from \"../design/decompile\";\nimport type { DesignDigest } from \"../design/types\";\nimport { BrandInputError, BrandNotFoundError } from \"../errors\";\nimport { contrastReport } from \"../palette-report\";\nimport type { BrandAsset } from \"../types\";\nimport { capString } from \"../validate\";\nimport type { BrandToolCtx } from \"./skill\";\n\n/** Largest template window one read_design_source call returns. */\nexport const MAX_SOURCE_WINDOW = 12_000;\n\n/** Render a digest as compact, readable text — cheaper and easier for a\n * model to act on than raw JSON, and it keeps the caps visible. */\nexport function describeDigest(asset: BrandAsset, digest: DesignDigest): string {\n const lines: string[] = [\n `Design ${asset.id}${digest.title ? ` — \"${digest.title}\"` : \"\"}${asset.title ? ` (uploaded as \"${asset.title}\")` : \"\"}`,\n `Template ${digest.templateBytes} bytes; ${digest.assetCount} embedded assets (${digest.assetBytes} bytes); ${digest.pageCount} nested pages.`,\n ];\n if (digest.assetGroups.length > 0)\n lines.push(\n `Assets: ${digest.assetGroups.map((g) => `${g.count}× ${g.mime} (${g.bytes} B)`).join(\", \")}`,\n );\n if (digest.externals.length > 0) lines.push(`Built against: ${digest.externals.join(\", \")}`);\n if (digest.fonts.length > 0) lines.push(`Typefaces: ${digest.fonts.join(\", \")}`);\n const tokenNames = Object.keys(digest.tokens.light);\n lines.push(\n tokenNames.length > 0\n ? `Declares ${tokenNames.length} --ui-* tokens (light) and ${Object.keys(digest.tokens.dark).length} (dark). ` +\n `Key values: ${[\"--ui-bg\", \"--ui-text\", \"--ui-accent\", \"--ui-accent-strong\", \"--ui-surface\"]\n .filter((n) => digest.tokens.light[n])\n .map((n) => `${n}=${digest.tokens.light[n]}`)\n .join(\", \")}`\n : \"Declares no --ui-* tokens; it was not authored on the @odla-ai/ui contract.\",\n );\n if (digest.colors.length > 0)\n lines.push(`Literal colors: ${digest.colors.map((c) => `${c.hex}×${c.count}`).join(\", \")}`);\n if (digest.props.length > 0)\n lines.push(\n \"Configurable props:\\n\" +\n digest.props\n .map(\n (p) =>\n ` ${p.name} (${p.editor}${p.options ? `: ${p.options.join(\"|\")}` : \"\"})` +\n `${p.default === undefined ? \"\" : ` default ${p.default}`}${p.section ? ` [${p.section}]` : \"\"}`,\n )\n .join(\"\\n\"),\n );\n if (digest.outline.length > 0)\n lines.push(\n \"Outline:\\n\" +\n digest.outline.map((h) => `${\" \".repeat(h.level - 1)}h${h.level} ${h.text}`).join(\"\\n\"),\n );\n if (digest.truncated.length > 0)\n lines.push(`NOTE: truncated to fit digest caps: ${digest.truncated.join(\", \")}.`);\n return lines.join(\"\\n\");\n}\n\n/** Locate the requested window of the template. */\nexport function sourceWindow(\n template: string,\n input: { find?: string; offset?: number; length?: number },\n): { text: string; start: number; end: number } {\n const length = Math.min(\n MAX_SOURCE_WINDOW,\n Math.max(1, typeof input.length === \"number\" ? input.length : MAX_SOURCE_WINDOW),\n );\n let start: number;\n if (input.find !== undefined && input.find !== \"\") {\n const at = template.indexOf(input.find);\n if (at < 0) throw new BrandNotFoundError(`\"${input.find}\" in the design source`);\n // Show a little of what precedes the match, so the opening tag of the\n // enclosing element is usually in frame.\n start = Math.max(0, at - 400);\n } else {\n start = Math.max(0, Math.min(template.length, Math.trunc(input.offset ?? 0)));\n }\n const end = Math.min(template.length, start + length);\n return { text: template.slice(start, end), start, end };\n}\n\n/**\n * The design tools, scoped to the context's book. All three refuse any asset\n * that is not a live `design` with a stored digest.\n */\nexport function designTools(ctx: BrandToolCtx): ToolDef[] {\n const loadDesign = async (assetId: string): Promise<BrandAsset> => {\n await ctx.authority(\"brand.read\");\n const res = await ctx.db.query({\n [BRAND_NS.asset]: { $: { where: { id: assetId, bookId: ctx.bookId, status: \"live\" } } },\n });\n const row = (res[BRAND_NS.asset] ?? [])[0] as BrandAsset | undefined;\n if (!row || row.kind !== DESIGN_ASSET_KIND || !row.design)\n throw new BrandNotFoundError(`design asset ${assetId}`);\n return row;\n };\n\n const readDesign: ToolDef = {\n name: \"read_design\",\n description:\n \"Read an uploaded Claude Design: its design tokens, typefaces, colors, configurable props, and heading outline. Start here before building anything from a design — it is the whole design at a size you can reason about.\",\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: {\n assetId: { type: \"string\", description: \"A design asset id from list_assets.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n return { content: describeDigest(asset, asset.design!) };\n }),\n };\n\n const readDesignSource: ToolDef = {\n name: \"read_design_source\",\n description:\n \"Read a window of a design's actual HTML source, to port exact markup or styles. Pass `find` to jump to the first occurrence of a string (a heading, a class name), or `offset` to page through. Returns at most 12000 characters.\",\n // The template is author-supplied content, not instructions.\n outputTaint: [\"tool_untrusted:read_design_source\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\"],\n properties: {\n assetId: { type: \"string\" },\n find: { type: \"string\", description: \"Jump to the first occurrence of this string.\" },\n offset: { type: \"number\", description: \"Character offset to read from (ignored with find).\" },\n length: { type: \"number\", description: `Characters to return (max ${MAX_SOURCE_WINDOW}).` },\n },\n },\n handler: ctx.guard(async (input) => {\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n const template = await ctx.readDesignTemplate(asset.id);\n const found = sourceWindow(template, {\n ...(typeof input.find === \"string\" ? { find: input.find } : {}),\n ...(typeof input.offset === \"number\" ? { offset: input.offset } : {}),\n ...(typeof input.length === \"number\" ? { length: input.length } : {}),\n });\n return {\n content:\n `Design ${asset.id} source, characters ${found.start}–${found.end} of ${template.length}:\\n` +\n found.text,\n };\n }),\n };\n\n const proposeFromDesign: ToolDef = {\n name: \"propose_palette_from_design\",\n description:\n \"Read a design's own --ui-* token declarations back into a brand palette and park it as a proposal for human review. Use when a design already carries the brand's colors and they should become the brand book's palette. Does NOT change the brand.\",\n acceptsTaint: [\"tool_untrusted:read_design_source\"],\n inputSchema: {\n type: \"object\",\n required: [\"assetId\", \"rationale\"],\n properties: {\n assetId: { type: \"string\" },\n name: { type: \"string\", description: \"Palette name; defaults to the design's title.\" },\n rationale: { type: \"string\", description: \"Why this design's palette should become the brand's.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n const book = await ctx.loadBook();\n await ctx.authority(\"brand.edit\");\n const asset = await loadDesign(capString(input.assetId, \"assetId\", 200));\n const digest = asset.design!;\n const rationale = capString(input.rationale, \"rationale\", 2_000);\n const name = capString(\n input.name ?? digest.title ?? asset.title ?? \"Design palette\",\n \"name\",\n 120,\n );\n const { swatches, skipped, missing } = swatchesFromDesignTokens(digest.tokens);\n if (swatches.length === 0)\n throw new BrandInputError(\n `design ${asset.id} declares no --ui-* tokens that resolve to opaque colors; ` +\n \"propose a palette explicitly instead.\",\n );\n const report = contrastReport(swatches);\n const proposal = await ctx.createProposal({\n mutationId: ctx.newId(),\n kind: \"palette\",\n payload: { name, swatches, contrastReport: report, source: \"design\", designAssetId: asset.id },\n rationale,\n sourceAssetId: asset.id,\n });\n if (\n proposal.bookId !== book.id ||\n proposal.createdBy !== ctx.self.selfId ||\n proposal.kind !== \"palette\" ||\n proposal.status !== \"open\"\n ) throw new BrandInputError(\"brand proposal bridge returned an invalid proposal\");\n const notes = [\n skipped.length > 0\n ? `Not imported (not literal opaque colors): ${skipped.map((s) => `${s.token} — ${s.reason}`).join(\"; \")}.`\n : \"\",\n missing.length > 0 ? `Roles the design declares no token for: ${missing.join(\", \")}.` : \"\",\n ].filter((n) => n !== \"\");\n return {\n content:\n `Parked palette proposal ${proposal.id} (\"${name}\") from design ${asset.id}: ` +\n `${swatches.length} swatches read back from its --ui-* declarations. ` +\n `Contrast: ${Object.entries(report).map(([k, v]) => `${k} ${v.toFixed(2)}:1`).join(\", \")}. ` +\n `${notes.join(\" \")} Awaiting a human decision in the brand approval surface.`.trim(),\n };\n }),\n };\n\n return [readDesign, readDesignSource, proposeFromDesign];\n}\n","// Read-only brand tools: a compact structured-text snapshot of the book\n// (read_brand_book) and the live asset list (list_assets). Deterministic, no\n// AI calls, no writes — the agent's orientation step before it proposes\n// anything. @odla-ai/ai is imported for types only.\nimport type { ToolDef } from \"@odla-ai/ai\";\nimport { ASSET_KINDS, BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport type { BrandAsset, BrandBook, BrandPalette, BrandProposal, BrandSection } from \"../types\";\nimport type { BrandToolCtx } from \"./skill\";\nimport type { BrandPrincipalProjection } from \"./skill\";\n\nconst iso = (ms: number): string => new Date(ms).toISOString();\n\nconst shortId = (id: string): string =>\n id.length <= 12 ? id : `${id.slice(0, 6)}…${id.slice(-4)}`;\nconst principalLabel = (\n id: string,\n directory: Map<string, BrandPrincipalProjection>,\n): string => {\n const value = directory.get(id);\n return value\n ? `${value.displayName} [${value.kind} · ${shortId(id)}]`\n : `Unknown principal [${shortId(id)}]`;\n};\n\nfunction bookLines(\n book: BrandBook,\n directory: Map<string, BrandPrincipalProjection>,\n): string[] {\n const lines = [\n `brand book \"${book.name}\" (${book.slug}) — ${book.status}`,\n `members: ${book.memberIds.map((id) => principalLabel(id, directory)).join(\", \")}`,\n `active palette: ${book.activePaletteId ?? \"(none accepted yet)\"}`,\n book.tokens\n ? `tokens: compiled ${iso(book.tokens.compiledAt)} with ${book.tokens.warnings.length} warning(s)`\n : \"tokens: (not compiled)\",\n ];\n if (book.summary) lines.push(`summary: ${book.summary}`);\n return lines;\n}\n\nfunction childLines(\n sections: BrandSection[],\n palettes: BrandPalette[],\n proposals: BrandProposal[],\n directory: Map<string, BrandPrincipalProjection>,\n): string[] {\n return [\n \"sections:\",\n ...(sections.length\n ? sections.map((s) =>\n `- ${s.kind}: ${s.status}, updated ${iso(s.updatedAt)} by ` +\n principalLabel(s.updatedBy, directory))\n : [\"- (none)\"]),\n \"palettes:\",\n ...(palettes.length\n ? palettes.map((p) => `- ${p.id} \"${p.name}\" (${p.status}, ${p.source}, ${p.swatches.length} swatches)`)\n : [\"- (none)\"]),\n \"open proposals:\",\n ...(proposals.length\n ? proposals.map((p) =>\n `- ${p.id} (${p.kind}) by ${principalLabel(p.createdBy, directory)}: ${p.rationale}`)\n : [\"- (none)\"]),\n ];\n}\n\n/**\n * The two read-only tools, scoped to the context's book:\n * `read_brand_book` (book + sections + palettes + open proposals as compact\n * text) and `list_assets` (live, non-tombstoned asset rows, optionally\n * filtered by kind).\n */\nexport function readTools(ctx: BrandToolCtx): ToolDef[] {\n const readBrandBook: ToolDef = {\n name: \"read_brand_book\",\n description:\n \"Read the current brand book: status, members, active palette, compiled tokens, sections, palettes, and open proposals.\",\n inputSchema: { type: \"object\", properties: {} },\n handler: ctx.guard(async () => {\n const authorizedBook = await ctx.loadBook();\n const res = await ctx.db.query({\n [BRAND_NS.section]: {\n $: { where: { bookId: ctx.bookId }, order: { updatedAt: \"asc\" } },\n book: {},\n },\n [BRAND_NS.palette]: {\n $: { where: { bookId: ctx.bookId }, order: { createdAt: \"asc\" } },\n book: {},\n },\n [BRAND_NS.proposal]: {\n $: {\n where: { bookId: ctx.bookId, status: \"open\" },\n order: { createdAt: \"asc\" },\n },\n book: {},\n },\n });\n const linked = <T extends { bookId: string; book?: Array<{ id: string }> }>(\n rows: unknown[],\n ): T[] => (rows as T[]).filter((row) =>\n row.bookId === authorizedBook.id &&\n Array.isArray(row.book) &&\n row.book.length === 1 &&\n row.book[0]?.id === authorizedBook.id);\n const sections = linked<BrandSection & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.section] ?? [],\n );\n const palettes = linked<BrandPalette & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.palette] ?? [],\n );\n const proposals = linked<BrandProposal & { book?: Array<{ id: string }> }>(\n res[BRAND_NS.proposal] ?? [],\n );\n const ids = [\n ...authorizedBook.memberIds,\n ...sections.map((section) => section.updatedBy),\n ...proposals.map((proposal) => proposal.createdBy),\n ];\n const directory = new Map(\n (await ctx.resolvePrincipals(ids)).map((principal) => [principal.id, principal]),\n );\n return {\n content: [\n ...bookLines(authorizedBook, directory),\n ...childLines(sections, palettes, proposals, directory),\n ].join(\"\\n\"),\n };\n }),\n };\n\n const listAssets: ToolDef = {\n name: \"list_assets\",\n description:\n \"List the book's uploaded assets (id, kind, content type, size, title, analysis state). Tombstoned assets are excluded.\",\n inputSchema: {\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...ASSET_KINDS], description: \"Only assets of this kind.\" },\n },\n },\n handler: ctx.guard(async (input) => {\n await ctx.loadBook();\n const where: Record<string, unknown> = { bookId: ctx.bookId, status: \"live\" };\n if (input.kind !== undefined) {\n if (typeof input.kind !== \"string\" || !(ASSET_KINDS as readonly string[]).includes(input.kind)) {\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n }\n where.kind = input.kind;\n }\n const res = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where, order: { createdAt: \"asc\" } },\n book: {},\n },\n });\n const rows = ((res[BRAND_NS.asset] ?? []) as Array<\n BrandAsset & { book?: Array<{ id: string }> }\n >).filter((asset) =>\n asset.bookId === ctx.bookId &&\n Array.isArray(asset.book) &&\n asset.book.length === 1 &&\n asset.book[0]?.id === ctx.bookId);\n if (rows.length === 0) {\n return { content: input.kind ? `(no ${String(input.kind)} assets uploaded yet)` : \"(no assets uploaded yet)\" };\n }\n const lines = rows.map(\n (a) =>\n `${a.id} — ${a.kind}, ${a.contentType}, ${a.size} bytes` +\n `${a.title ? `, \"${a.title}\"` : \"\"}${a.analysis ? \" (analyzed)\" : \" (not analyzed)\"}`,\n );\n return { content: lines.join(\"\\n\") };\n }),\n };\n\n return [readBrandBook, listAssets];\n}\n","// The @odla-ai/ai Skill assembly for a brand book: one shared tool context\n// (injected db + identity + defaults), the workflow instructions, and the\n// tools from the five tool modules. @odla-ai/ai is an optional peer imported\n// for TYPES ONLY (chat's pattern) — the package works without it installed.\n//\n// Error contract with the agent loop: runAgent converts a handler throw into\n// a SANITIZED error tool_result (`Tool \"x\" failed.`) because arbitrary\n// handler messages may carry credentials. Brand's own validation errors are\n// crafted, secret-free, and actionable, so `guard` catches BrandInputError /\n// BrandNotFoundError and returns the message as an error output the model can\n// act on; anything unexpected still propagates into the loop's sanitizer.\nimport type { Skill, ToolHandler } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"../constants\";\nimport { resolveDeps, type BrandFetchedBytes } from \"../deps\";\nimport { BrandForbiddenError, BrandInputError, BrandNotFoundError } from \"../errors\";\nimport type {\n AssetAnalysis,\n BrandAsset,\n BrandBook,\n BrandDb,\n BrandProposal,\n} from \"../types\";\nimport type { ProposalKind } from \"../constants\";\nimport { parseDesignBundle } from \"../design/bundle\";\nimport { assetTools } from \"./asset-tools\";\nimport { designTools } from \"./design-tools\";\nimport { bookTools } from \"./book-tools\";\nimport { paletteTools } from \"./palette-tools\";\nimport { readTools } from \"./read-tools\";\nimport type {\n BrandCapability,\n BrandCapabilityAuthority,\n BrandPrincipalProjection,\n} from \"./agent-types\";\n\nexport type {\n BrandCapability,\n BrandCapabilityAuthority,\n BrandPrincipalProjection,\n} from \"./agent-types\";\n\n/** The bot identity the skill writes as (`selfId` = the agent id carried in\n * the book's `memberIds` roster and every audience snapshot). */\nexport interface BrandSkillSelf {\n selfId: string;\n kind: \"bot\";\n displayName?: string;\n}\n\n/** Server-enforced semantic bridge. Raw agent credentials must be denied all\n * Brand namespace writes and raw file operations. */\nexport interface BrandAgentBridge {\n createProposal(input: {\n jobId: string;\n bookId: string;\n mutationId: string;\n kind: ProposalKind;\n payload: Record<string, unknown>;\n rationale: string;\n sourceAssetId?: string;\n }): Promise<BrandProposal>;\n recordAssetAnalysis(input: {\n jobId: string;\n mutationId: string;\n bookId: string;\n assetId: string;\n analysis: AssetAnalysis;\n expectedAnalysisRevision: number;\n }): Promise<BrandAsset>;\n readAssetContent(input: {\n jobId: string;\n bookId: string;\n assetId: string;\n }): Promise<BrandFetchedBytes>;\n}\n\n/** Options for {@link brandSkill}. */\nexport interface BrandSkillOpts {\n /** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */\n db: BrandDb;\n /** The one brand book this skill instance is scoped to. */\n bookId: string;\n /** The bot identity acting through these tools. */\n self: BrandSkillSelf;\n /** Host attestation for the rules-scoped credential behind `db`. */\n agentDbBinding: { principalId: string; credentialRef: string };\n /** Active verified agent job; the bridge derives message/turn provenance. */\n agentJobId: string;\n agentBridge: BrandAgentBridge;\n /** Host verification against the live principal grant. Missing/denied hooks\n * fail closed; roster membership is visibility, not authority. */\n authorizeCapability: (input: {\n agentId: string;\n bookId: string;\n capability: BrandCapability;\n }) => Promise<BrandCapabilityAuthority | null> | BrandCapabilityAuthority | null;\n /** Bounded host directory projection for conversational display only. */\n resolvePrincipals: (input: {\n requesterAgentId: string;\n bookId: string;\n principalIds: string[];\n }) => Promise<BrandPrincipalProjection[]>;\n /** False when the model cannot take image/document blocks inside a\n * tool_result — view_asset then steers to the pre-turn attachment path. */\n visionInToolResults?: boolean;\n /** Clock override (tests). */\n now?: () => number;\n /** Id factory override (tests). */\n newId?: () => string;\n}\n\n/** The resolved context every brand tool module builds its tools from. */\nexport interface BrandToolCtx {\n db: BrandDb;\n bookId: string;\n self: BrandSkillSelf;\n /** Whether image/document blocks may be returned inside tool results. */\n visionInToolResults: boolean;\n now: () => number;\n newId: () => string;\n agentJobId: string;\n createProposal(input: {\n mutationId: string;\n kind: ProposalKind;\n payload: Record<string, unknown>;\n rationale: string;\n sourceAssetId?: string;\n }): Promise<BrandProposal>;\n recordAssetAnalysis(input: {\n mutationId: string;\n assetId: string;\n analysis: AssetAnalysis;\n expectedAnalysisRevision: number;\n }): Promise<BrandAsset>;\n readAssetContent(assetId: string): Promise<BrandFetchedBytes>;\n /** The decoded template document of a `design` asset. Memoized per skill\n * instance: a bundle is megabytes, and `read_design_source` is designed to\n * be called repeatedly while an agent ports markup. */\n readDesignTemplate(assetId: string): Promise<string>;\n resolvePrincipals(ids: string[]): Promise<BrandPrincipalProjection[]>;\n authority(capability: BrandCapability): Promise<BrandCapabilityAuthority>;\n /** Load the scoped book row; throws BrandNotFoundError when missing. */\n loadBook(): Promise<BrandBook>;\n /** Wrap a handler so Brand validation errors come back as actionable\n * error text instead of the loop's sanitized generic failure. */\n guard(handler: ToolHandler): ToolHandler;\n}\n\n/** Workflow guidance appended to the persona's system prompt as the skill's\n * instruction section. */\nexport const BRAND_INSTRUCTIONS =\n \"You help build and maintain ONE brand book. Workflow, in order:\\n\" +\n \"1. Understand the brand first: read_brand_book and list_assets before proposing anything.\\n\" +\n \"2. Look at the real material: view_asset on logos and inspiration, then record what you \" +\n \"saw with record_asset_analysis (description, dominant colors as hex, tags).\\n\" +\n \"3. Explore with the math tools: analyze_color and evaluate_contrast. Never invent a hex \" +\n \"without a rationale — ground every color in an asset's dominant color, a harmony \" +\n \"companion, or a contrast fix, and say which.\\n\" +\n \"4. When a Claude Design has been uploaded, read_design is the fastest way to learn the \" +\n \"brand: it reports the design tokens, typefaces, props, and page outline. read_design_source \" +\n \"reads exact markup when you need it. If the design already carries the brand colors, \" +\n \"propose_palette_from_design reads its --ui-* declarations back into a palette proposal.\\n\" +\n \"5. propose_palette parks a proposal for review. It does NOT change the brand.\\n\" +\n \"6. You cannot approve or resolve a proposal. Direct the human to the brand approval \" +\n \"surface, which records a guarded receipt for their decision.\\n\" +\n \"7. update_section parks a proposal; it never overwrites an approved facet. Bind \" +\n \"sourceAssetId when a real Brand asset grounds typography, voice, logo, or imagery. Human \" +\n \"acceptance applies the exact reviewed change and automatically recompiles dependent tokens.\\n\" +\n \"8. Re-read the book after a decision and explain any compiler warnings conversationally.\";\n\n/**\n * Build the brand Skill: read/asset/design/palette/book tools scoped to one book,\n * acting as one bot identity, plus {@link BRAND_INSTRUCTIONS}. Attach it to\n * a Persona (or use `createBrandPersona`).\n */\nexport function brandSkill(opts: BrandSkillOpts): Skill {\n if (\n opts.agentDbBinding.principalId !== opts.self.selfId ||\n !opts.agentDbBinding.credentialRef\n ) throw new BrandForbiddenError(\"brand db is not bound to the acting agent\");\n const deps = resolveDeps({ db: opts.db, now: opts.now, newId: opts.newId });\n const designTemplates = new Map<string, Promise<string>>();\n const authority = (capability: BrandCapability): Promise<BrandCapabilityAuthority> =>\n Promise.resolve(opts.authorizeCapability({\n agentId: opts.self.selfId,\n bookId: opts.bookId,\n capability,\n }) ?? null).then((result) => {\n if (!result || result.capability !== capability || !result.authorityRef)\n throw new BrandForbiddenError(`agent lacks ${capability} for brand book ${opts.bookId}`);\n return result;\n });\n const ctx: BrandToolCtx = {\n db: deps.db,\n bookId: opts.bookId,\n self: opts.self,\n visionInToolResults: opts.visionInToolResults !== false,\n now: deps.now,\n newId: deps.newId,\n agentJobId: opts.agentJobId,\n createProposal: (input) => opts.agentBridge.createProposal({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n ...input,\n }),\n recordAssetAnalysis: (input) => opts.agentBridge.recordAssetAnalysis({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n ...input,\n }),\n readAssetContent: (assetId) => opts.agentBridge.readAssetContent({\n jobId: opts.agentJobId,\n bookId: opts.bookId,\n assetId,\n }),\n readDesignTemplate: (assetId) => {\n const cached = designTemplates.get(assetId);\n if (cached) return cached;\n const pending = opts.agentBridge\n .readAssetContent({ jobId: opts.agentJobId, bookId: opts.bookId, assetId })\n .then((fetched) =>\n parseDesignBundle(new TextDecoder().decode(fetched.bytes)).template,\n );\n // A failed read must not be memoized as a permanent failure.\n pending.catch(() => designTemplates.delete(assetId));\n designTemplates.set(assetId, pending);\n return pending;\n },\n resolvePrincipals: (principalIds) => {\n const ids = [...new Set(principalIds)].slice(0, 100);\n return opts.resolvePrincipals({\n requesterAgentId: opts.self.selfId,\n bookId: opts.bookId,\n principalIds: ids,\n });\n },\n authority,\n loadBook: async () => {\n await authority(\"brand.read\");\n const res = await deps.db.query({ [BRAND_NS.book]: { $: { where: { id: opts.bookId } } } });\n const row = (res[BRAND_NS.book] ?? [])[0] as BrandBook | undefined;\n if (!row || !row.memberIds.includes(opts.self.selfId))\n throw new BrandNotFoundError(`brand book ${opts.bookId}`);\n return row;\n },\n guard: (handler) => async (input, toolCtx) => {\n try {\n return await handler(input, toolCtx);\n } catch (error) {\n if (\n error instanceof BrandInputError ||\n error instanceof BrandNotFoundError ||\n error instanceof BrandForbiddenError\n ) {\n return { content: error.message, isError: true };\n }\n throw error;\n }\n },\n };\n return {\n name: \"brand\",\n instructions: BRAND_INSTRUCTIONS,\n tools: [\n ...readTools(ctx),\n ...assetTools(ctx),\n ...designTools(ctx),\n ...paletteTools(ctx),\n ...bookTools(ctx),\n ],\n };\n}\n","// The brand-director Persona: the brand skill pre-attached, a default system\n// prompt encoding the explore → propose → human approves → compile loop, and\n// the capability probe hosts use to decide whether asset bytes can ride\n// inside tool results or must be attached pre-turn. @odla-ai/ai types only.\nimport type { Persona, Skill } from \"@odla-ai/ai\";\nimport { brandSkill, type BrandSkillOpts } from \"./skill\";\n\n/** The default brand-director system prompt (override via `system`). */\nexport const DEFAULT_BRAND_SYSTEM =\n \"You are a meticulous brand director for one brand book. You study the real material \" +\n \"before forming opinions, you justify every color with math (harmony, ΔEOK, WCAG \" +\n \"contrast) or provenance (an asset's dominant colors), and you present options rather \" +\n \"than dictating. Proposals and drafts are yours to make; decisions are the human's — \" +\n \"you have no proposal-resolution or section-approval tool. When \" +\n \"tokens compile with warnings, explain each adjustment in plain language.\";\n\n/** Options for {@link createBrandPersona}. */\nexport interface CreateBrandPersonaOpts {\n /** Canonical model id the persona runs on. */\n model: string;\n /** System prompt override (default {@link DEFAULT_BRAND_SYSTEM}). */\n system?: string;\n /** Provider web-search server tool (default true — brand research). */\n webSearch?: boolean;\n /** Max model turns per run (default 10 — the workflow is multi-step). */\n maxSteps?: number;\n /** Extra skills appended after the brand skill (e.g. a chat skill). */\n skills?: Skill[];\n /** Options for the attached {@link brandSkill}. */\n brand: BrandSkillOpts;\n}\n\n/** Build the brand-director Persona: {@link brandSkill} first, extra skills\n * after, defaults per the option JSDoc above. */\nexport function createBrandPersona(opts: CreateBrandPersonaOpts): Persona {\n return {\n name: \"brand-director\",\n model: opts.model,\n system: opts.system ?? DEFAULT_BRAND_SYSTEM,\n webSearch: opts.webSearch ?? true,\n maxSteps: opts.maxSteps ?? 10,\n skills: [brandSkill(opts.brand), ...(opts.skills ?? [])],\n };\n}\n\n/** The capability flags {@link supportsBrandVision} inspects. */\nexport interface BrandVisionCapabilities {\n toolResultBlocks?: boolean;\n imageIn?: boolean;\n documentIn?: boolean;\n}\n\n/** The (structural) slice of an @odla-ai/ai ModelSpec the probe reads. */\nexport interface BrandVisionSpec {\n capabilities?: BrandVisionCapabilities;\n}\n\n/**\n * Whether a model can view assets THROUGH view_asset — i.e. take image and\n * document blocks inside tool results. Pure capabilities-metadata check\n * (`toolResultBlocks && imageIn && documentIn`), never provider names; when\n * false, hosts attach asset bytes as pre-turn input blocks instead and pass\n * `visionInToolResults: false` to the skill.\n */\nexport function supportsBrandVision(spec: BrandVisionSpec | null | undefined): boolean {\n const caps = spec?.capabilities;\n return !!(caps?.toolResultBlocks && caps.imageIn && caps.documentIn);\n}\n","import { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport { BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport type { BrandRouteCtx } from \"./http\";\n\nexport async function linkedAsset(\n ctx: BrandRouteCtx,\n book: BrandBook,\n assetId: string,\n allowDeleting = false,\n): Promise<BrandAsset> {\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: assetId, bookId: book.id } },\n book: {},\n },\n });\n const row = rowAsWritten(BRAND_NS.asset, (result[BRAND_NS.asset] ?? [])[0]) as\n | (BrandAsset & { book?: BrandBook[] })\n | undefined;\n const links = row?.book;\n if (\n !row ||\n row.bookId !== book.id ||\n !Array.isArray(links) ||\n links.length !== 1 ||\n links[0]?.id !== book.id ||\n (row.status !== \"live\" && !(allowDeleting && row.status === \"deleting\"))\n ) throw new BrandNotFoundError(`asset ${assetId}`);\n return row;\n}\n","// HTTP plumbing for the brand route factory (crm's http.ts contract): option\n// shapes, JSON helpers, the error → status mapping (BrandInputError → 400,\n// BrandNotFoundError → 404, anything else an OPAQUE 500), body-field\n// extractors, and the shared book loaders.\n//\n// Access parity note: routes run on the host's ADMIN db credential, which\n// bypasses odla-db rules — so the loaders re-enforce what the CEL rules would:\n// a book you are not in `memberIds` of answers 404, the same as one that does\n// not exist (a non-member cannot probe for existence).\nimport { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandGoneError,\n BrandInputError,\n BrandNotFoundError,\n BrandReviewStateChangedError,\n} from \"../errors\";\nimport type {\n BrandActor,\n BrandBook,\n BrandDb,\n BrandHumanAuthorityConsumption,\n BrandSourceAssetSnapshot,\n} from \"../types\";\n\nexport type BrandRouteCapability = \"brand.edit\" | \"app.manage\";\nexport type BrandRouteEffect = \"internal\" | \"destructive\";\nexport interface BrandRouteAuthority {\n authorityRef: string;\n actorPrincipalId: string;\n capability: BrandRouteCapability;\n effect: BrandRouteEffect;\n}\n\n/** Everything {@link import(\"./index\").createBrandRoutes} needs from the host worker. */\nexport interface BrandRouteOpts {\n /** The injected odla client (a real @odla-ai/db AdminDb satisfies it). */\n db: BrandDb;\n /** Registry app that owns the book rows and central authority records. */\n appId: string;\n /** Host-owned auth: resolve the request to an actor or null (→ 401). The\n * tokens routes skip this only when `publicTokens` is true. */\n authorize: (req: Request) => Promise<BrandActor | null> | BrandActor | null;\n /** Optional host-owned authority seam for read-only Discussion reference\n * lookup. Verify exact Brand product, brand.read capability, canonical\n * audience, principal, current app lifetime/environment, and agent grant\n * provenance here; when omitted, the ordinary request authorizer is used. */\n authorizeDiscussionReferences?: (\n req: Request,\n ) => Promise<BrandActor | null> | BrandActor | null;\n /** Live host verification for worker-mediated effects. The callback must\n * verify the direct human credential, current app owner/co-owner status,\n * exact capability/effect/resource, and return null on any uncertainty. */\n authorizeCapability: (input: {\n req: Request;\n actor: BrandActor;\n appId: string;\n bookId?: string;\n capability: BrandRouteCapability;\n effect: BrandRouteEffect;\n }) => Promise<BrandRouteAuthority | null> | BrandRouteAuthority | null;\n /** Consume or idempotently replay one registry `human_exact` authority use,\n * then reload and authenticate its immutable central receipt. Missing,\n * synthetic, cached, or unverifiable authority must return null. */\n consumeHumanExact: (input: {\n req: Request;\n actor: BrandActor;\n appId: string;\n capability: \"brand.proposal.resolve\";\n projectCapability: \"brand.approve\";\n effect: \"internal\";\n resource: { bookId: string; proposalId: string };\n actionDigest: string;\n consumptionIdempotencyKey: string;\n }) => Promise<BrandHumanAuthorityConsumption | null> | BrandHumanAuthorityConsumption | null;\n /** Re-read the private object and authenticate the exact snapshot captured\n * by the agent bridge. This must verify path, ETag, size, and SHA-256 bytes;\n * returning false prevents authority consumption and the local effect. */\n verifySourceAssetSnapshot: (input: {\n req: Request;\n appId: string;\n bookId: string;\n assetId: string;\n path: string;\n snapshot: BrandSourceAssetSnapshot;\n }) => Promise<boolean> | boolean;\n /** Mount point. Default \"/api/brand\". */\n basePath?: string;\n /** Native UI mount used by returned Discussion deep links. Default \"/\". */\n discussionBasePath?: string;\n /**\n * Product-owned fetch used only for a short-lived URL minted from a linked\n * private Brand asset. Callers never provide this URL or receive it back.\n */\n fetchPrivateAsset?: typeof fetch;\n /** `frame-ancestors` for the design preview response — who may embed a\n * design. Default `[\"'self'\"]`. Widen only to origins you control: the\n * preview renders untrusted design HTML. */\n previewFrameAncestors?: string[];\n /** Upload size cap in bytes (checked against `File.size`). Default 8 MiB. */\n maxUploadBytes?: number;\n /** Serve `GET /books/:id/tokens.css` and `tokens.json` without authorize —\n * compiled tokens only; every other route always authorizes. Default false. */\n publicTokens?: boolean;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n /** Injectable id factory (tests). Default `crypto.randomUUID`. */\n newId?: () => string;\n}\n\n/** Per-request context handed to the authorized route handlers. */\nexport interface BrandRouteCtx {\n db: BrandDb;\n appId: string;\n actor: BrandActor;\n authorizeCapability: BrandRouteOpts[\"authorizeCapability\"];\n consumeHumanExact: BrandRouteOpts[\"consumeHumanExact\"];\n verifySourceAssetSnapshot: BrandRouteOpts[\"verifySourceAssetSnapshot\"];\n now: () => number;\n newId: () => string;\n maxUploadBytes: number;\n discussionBasePath: string;\n fetchPrivateAsset: typeof fetch;\n previewFrameAncestors: string[];\n}\n\n/** Revalidate one direct-human route effect immediately before its write. */\nexport async function requireRouteAuthority(\n ctx: BrandRouteCtx,\n req: Request,\n capability: BrandRouteCapability,\n effect: BrandRouteEffect,\n bookId?: string,\n): Promise<BrandRouteAuthority> {\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"this brand effect requires a directly authenticated human\");\n const result = await ctx.authorizeCapability({\n req,\n actor: ctx.actor,\n appId: ctx.appId,\n ...(bookId ? { bookId } : {}),\n capability,\n effect,\n });\n if (\n !result ||\n result.actorPrincipalId !== ctx.actor.id ||\n result.capability !== capability ||\n result.effect !== effect ||\n typeof result.authorityRef !== \"string\" ||\n result.authorityRef.length < 1 ||\n result.authorityRef.length > 200\n ) throw new BrandForbiddenError(`human lacks ${capability} ${effect} authority`);\n return result;\n}\n\n/** JSON response helper (`content-type: application/json`). */\nexport const json = (body: unknown, status = 200, headers: Record<string, string> = {}): Response =>\n new Response(JSON.stringify(body), {\n status,\n headers: { \"content-type\": \"application/json\", ...headers },\n });\n\n/** Map a thrown error to its response: 400 input, 403 principal kind, 404\n * missing/membership parity, 409 stale review, otherwise opaque 500. */\nexport const errorResponse = (error: unknown): Response => {\n if (error instanceof BrandInputError)\n return json({ error: error.message, ...(error.fields ? { fields: error.fields } : {}) }, 400);\n if (error instanceof BrandForbiddenError) return json({ error: error.message }, 403);\n if (error instanceof BrandNotFoundError) return json({ error: error.message }, 404);\n if (error instanceof BrandGoneError) return json({ error: error.message }, 410);\n if (error instanceof BrandReviewStateChangedError)\n return json({ error: error.message, code: error.code }, 409);\n if (error instanceof BrandConflictError) return json({ error: error.message }, 409);\n return json({ error: \"internal error\" }, 500);\n};\n\n/** The uniform 405 for a known path hit with the wrong method. */\nexport const methodNotAllowed = (): Response => json({ error: \"method not allowed\" }, 405);\n\n/** Parse a JSON object body; {@link BrandInputError} (→ 400) on anything else. */\nexport async function readJson(req: Request): Promise<Record<string, unknown>> {\n let body: unknown;\n try {\n body = await req.json();\n } catch {\n throw new BrandInputError(\"invalid JSON body\");\n }\n if (typeof body !== \"object\" || body === null || Array.isArray(body))\n throw new BrandInputError(\"body must be a JSON object\");\n return body as Record<string, unknown>;\n}\n\n/** Required non-empty string body field. */\nexport function str(body: Record<string, unknown>, key: string): string {\n const value = body[key];\n if (typeof value !== \"string\" || value === \"\")\n throw new BrandInputError(`\"${key}\" must be a non-empty string`);\n return value;\n}\n\n/** Optional string body field (absent/null → undefined). */\nexport function optStr(body: Record<string, unknown>, key: string): string | undefined {\n const value = body[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") throw new BrandInputError(`\"${key}\" must be a string`);\n return value;\n}\n\n/** Optional string-array body field (absent/null → undefined). */\nexport function optStrArray(body: Record<string, unknown>, key: string): string[] | undefined {\n const value = body[key];\n if (value === undefined || value === null) return undefined;\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\"))\n throw new BrandInputError(`\"${key}\" must be an array of strings`);\n return value as string[];\n}\n\n/** Whether `actorId` is on the book's auth roster. */\nexport function isMember(book: BrandBook, actorId: string): boolean {\n return Array.isArray(book.memberIds) && book.memberIds.includes(actorId);\n}\n\n/** Load a book by id; {@link BrandNotFoundError} (→ 404) when missing. */\nexport async function loadBook(db: BrandDb, bookId: string): Promise<BrandBook> {\n const res = await db.query({ [BRAND_NS.book]: { $: { where: { id: bookId } } } });\n const row = (res[BRAND_NS.book] ?? [])[0] as BrandBook | undefined;\n if (!row) throw new BrandNotFoundError(`brand book ${bookId}`);\n // BrandBook.createdAt is declared `number` and that is the published\n // contract; the store's ISO read shape is an implementation detail that must\n // not reach a consumer.\n return rowAsWritten(BRAND_NS.book, row);\n}\n\n/** {@link loadBook}, plus the rules-parity membership gate: a non-member gets\n * the same 404 a missing book gets (see the header note). */\nexport async function loadMemberBook(db: BrandDb, bookId: string, actorId: string): Promise<BrandBook> {\n const book = await loadBook(db, bookId);\n if (!isMember(book, actorId)) throw new BrandNotFoundError(`brand book ${bookId}`);\n return book;\n}\n","import { ASSET_KINDS, BRAND_NS, DESIGN_ASSET_KIND, type AssetKind } from \"../constants\";\nimport { digestDesignHtml } from \"../design/digest\";\nimport { BrandConflictError, BrandInputError } from \"../errors\";\nimport { createAssetOps } from \"../ops/assets\";\nimport { assertAssetContentType, capString, safeFileName } from \"../validate\";\nimport { linkedAsset } from \"./asset-query\";\nimport {\n json,\n loadMemberBook,\n requireRouteAuthority,\n type BrandRouteCtx,\n} from \"./http\";\n\nasync function readForm(req: Request): Promise<FormData> {\n try {\n return await req.formData();\n } catch {\n throw new BrandInputError(\n 'expected multipart/form-data with a \"file\" field',\n );\n }\n}\n\nasync function contentDigest(file: File): Promise<string> {\n const hash = await crypto.subtle.digest(\"SHA-256\", await file.arrayBuffer());\n return `sha256:${[...new Uint8Array(hash)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n\nexport async function uploadAsset(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const form = await readForm(req);\n const file = form.get(\"file\");\n if (!(file instanceof File))\n throw new BrandInputError('\"file\" must be an uploaded file field');\n // Kind is resolved BEFORE the content-type check: the allowlist is\n // per-kind (design accepts text/html and nothing else; every other kind\n // accepts images/PDF and never HTML).\n const kindRaw = form.get(\"kind\");\n const kind = typeof kindRaw === \"string\" && kindRaw ? kindRaw : \"other\";\n if (!(ASSET_KINDS as readonly string[]).includes(kind))\n throw new BrandInputError(`kind must be one of: ${ASSET_KINDS.join(\", \")}`);\n let contentType: string;\n try {\n contentType = assertAssetContentType(file.type, kind);\n } catch (error) {\n if (error instanceof BrandInputError)\n return json({ error: error.message }, 415);\n throw error;\n }\n if (file.size > ctx.maxUploadBytes)\n return json({ error: `file exceeds ${ctx.maxUploadBytes} bytes` }, 413);\n // Parse before touching storage, so an unreadable bundle is a clean 400\n // and never strands an object (the ordering invariant this file keeps for\n // every other check too).\n const design =\n kind === DESIGN_ASSET_KIND ? digestDesignHtml(await file.text()) : undefined;\n const titleRaw = form.get(\"title\");\n const title = typeof titleRaw === \"string\" && titleRaw\n ? capString(titleRaw, \"title\", 160)\n : undefined;\n const fileName = safeFileName(file.name);\n const id = ctx.newId();\n const path = `brand/${book.id}/assets/${id}/${fileName}`;\n const authority = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"internal\", book.id,\n );\n const record = await ctx.db.storage.upload(\n path,\n file,\n contentType,\n { private: true },\n );\n if (record.path !== path) {\n await ctx.db.storage.delete(record.path);\n throw new BrandConflictError(\n \"private storage returned an unexpected asset path\",\n );\n }\n try {\n const current = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"internal\", book.id,\n );\n if (current.authorityRef !== authority.authorityRef)\n throw new BrandConflictError(\"brand edit authority changed during upload\");\n await ctx.db.transact(createAssetOps({\n id,\n bookId: book.id,\n kind: kind as AssetKind,\n path: record.path,\n storageObjectId: record.id,\n contentDigest: await contentDigest(file),\n contentType,\n size: record.size,\n uploadedBy: ctx.actor.id,\n uploadedAuthorityRef: authority.authorityRef,\n audience: book.memberIds,\n title,\n ...(design ? { design } : {}),\n now: ctx.now(),\n }), {\n mutationId: `brand:asset-upload:v1:${id}`,\n guards: [\n { ns: BRAND_NS.asset, id, exists: false },\n {\n ns: BRAND_NS.book,\n id: book.id,\n exists: true,\n equals: {\n version: book.version,\n activationRevision: book.activationRevision,\n memberIds: book.memberIds,\n },\n },\n ],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n } catch (error) {\n await ctx.db.storage.delete(record.path);\n throw error;\n }\n return json(await linkedAsset(ctx, book, id), 201);\n}\n","// Private Brand asset upload, listing, short-lived download signing, and\n// deletion saga. Rows are linked to books and privileged reads validate both\n// the scalar bookId and the actual schema link.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandConflictError } from \"../errors\";\nimport {\n beginAssetDeleteOps,\n finishAssetDeleteOps,\n} from \"../ops/assets\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport { linkedAsset } from \"./asset-query\";\nimport { uploadAsset } from \"./asset-upload\";\nimport {\n json,\n loadMemberBook,\n methodNotAllowed,\n requireRouteAuthority,\n type BrandRouteCtx,\n} from \"./http\";\n\n/** List or upload assets. Only live rows are returned; every upload is\n * private and its expiring signed URL is never persisted. */\nexport async function handleAssetsRoot(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n if (req.method === \"POST\") return uploadAsset(ctx, req, bookId);\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { bookId: book.id, status: \"live\" }, order: { createdAt: \"asc\" } },\n book: {},\n },\n });\n const assets = (result[BRAND_NS.asset] ?? []).filter((value) => {\n const row = value as BrandAsset & { book?: BrandBook[] };\n return row.bookId === book.id &&\n Array.isArray(row.book) &&\n row.book.length === 1 &&\n row.book[0]?.id === book.id;\n });\n return json({ assets });\n}\n\n/** Mint a five-minute private URL after current membership + exact link\n * validation. The response itself is non-cacheable. */\nexport async function handleAssetContent(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n const expiresInSeconds = 300;\n const url = await ctx.db.storage.sign(asset.path, expiresInSeconds);\n return json(\n { assetId, url, expiresInSeconds },\n 200,\n { \"cache-control\": \"private, no-store\", \"x-content-type-options\": \"nosniff\" },\n );\n}\n\n/** Guarded deleting → storage tombstone → deleted saga. A retry resumes a\n * deleting row; list/sign paths reject it from the first committed step. */\nexport async function handleAssetItem(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"DELETE\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n let asset = await linkedAsset(ctx, book, assetId, true);\n const authority = await requireRouteAuthority(\n ctx, req, \"brand.edit\", \"destructive\", book.id,\n );\n const mutationBase = `brand:asset-delete:v1:${book.id}:${asset.id}`;\n if (asset.status === \"live\") {\n const deletedAt = ctx.now();\n try {\n await ctx.db.transact(beginAssetDeleteOps(\n asset.id,\n deletedAt,\n ctx.actor.id,\n authority.authorityRef,\n ), {\n mutationId: `${mutationBase}:begin`,\n guards: [\n {\n ns: BRAND_NS.asset,\n id: asset.id,\n exists: true,\n equals: {\n bookId: book.id,\n path: asset.path,\n storageObjectId: asset.storageObjectId,\n contentDigest: asset.contentDigest,\n status: \"live\",\n },\n },\n {\n ns: BRAND_NS.book,\n id: book.id,\n exists: true,\n equals: { version: book.version, memberIds: book.memberIds },\n },\n ],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n } catch (error) {\n if (\n typeof error === \"object\" &&\n error !== null &&\n (error as { code?: unknown }).code === \"transact_guard_failed\"\n ) throw new BrandConflictError(\"asset changed before deletion\");\n throw error;\n }\n asset = { ...asset, status: \"deleting\", deletedAt };\n }\n await ctx.db.storage.delete(asset.path);\n await ctx.db.transact(finishAssetDeleteOps(asset.id), {\n mutationId: `${mutationBase}:finish`,\n guards: [{\n ns: BRAND_NS.asset,\n id: asset.id,\n exists: true,\n equals: {\n bookId: book.id,\n path: asset.path,\n storageObjectId: asset.storageObjectId,\n contentDigest: asset.contentDigest,\n status: \"deleting\",\n deletedBy: asset.deletedBy ?? ctx.actor.id,\n deletedAuthorityRef: asset.deletedAuthorityRef ?? authority.authorityRef,\n },\n }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n return json({ id: asset.id, status: \"deleted\", deletedAt: asset.deletedAt });\n}\n","// /books handlers: create, member-filtered list, and detail.\n//\n// List filtering note: odla-db's query where-clauses have no \"roster array\n// CONTAINS value\" operator (`$in` tests a scalar column against a candidate\n// list, the inverse), so membership on the json `memberIds` roster is not\n// expressible as a where. The handler fetches the namespace and filters in\n// code — exactly the visibility the `brand_book.view` CEL rule\n// (`auth.id in data.memberIds`) enforces for rules-scoped credentials; the\n// admin-key route path just re-applies it server-side.\nimport { BRAND_NS } from \"../constants\";\nimport { rowAsWritten } from \"../review\";\nimport { BrandConflictError, BrandForbiddenError, BrandInputError } from \"../errors\";\nimport { createBookOps } from \"../ops/books\";\nimport type { BrandBook } from \"../types\";\nimport { capString } from \"../validate\";\nimport {\n isMember,\n json,\n loadBook,\n loadMemberBook,\n methodNotAllowed,\n optStr,\n optStrArray,\n readJson,\n requireRouteAuthority,\n str,\n type BrandRouteCtx,\n} from \"./http\";\n\n/**\n * `GET /books` — every book whose `memberIds` roster contains the actor,\n * oldest first, as `{ books }`. `POST /books` — create a draft book owned by\n * the actor (`slug`, `name`, optional `memberIds` roster and `channelId`);\n * answers 201 with the created row. Other methods: 405.\n */\nexport async function handleBooksRoot(ctx: BrandRouteCtx, req: Request): Promise<Response> {\n if (req.method === \"GET\") {\n const res = await ctx.db.query({ [BRAND_NS.book]: { $: { order: { createdAt: \"asc\" } } } });\n const books = ((res[BRAND_NS.book] ?? []) as unknown as BrandBook[])\n .map((b) => rowAsWritten(BRAND_NS.book, b))\n .filter((b) =>\n isMember(b, ctx.actor.id),\n );\n return json({ books });\n }\n if (req.method === \"POST\") {\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a human can create a brand book\");\n const body = await readJson(req);\n const id = ctx.newId();\n const authority = await requireRouteAuthority(\n ctx,\n req,\n \"brand.edit\",\n \"internal\",\n );\n const ops = createBookOps({\n id,\n slug: str(body, \"slug\"),\n name: str(body, \"name\"),\n ownerId: ctx.actor.id,\n createdAuthorityRef: authority.authorityRef,\n memberIds: optStrArray(body, \"memberIds\") ?? [],\n channelId: optStr(body, \"channelId\"),\n now: ctx.now(),\n });\n await ctx.db.transact(ops, {\n mutationId: id,\n guards: [{ ns: BRAND_NS.book, id, exists: false }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n return json(await loadBook(ctx.db, id), 201);\n }\n return methodNotAllowed();\n}\n\nconst sameStrings = (left: string[], right: string[]): boolean =>\n left.length === right.length && left.every((value, index) => value === right[index]);\nconst guardFailure = (error: unknown): boolean =>\n typeof error === \"object\" && error !== null &&\n (error as { code?: unknown }).code === \"transact_guard_failed\";\n\n/** `PATCH /books/:id/members` — owner-only atomic roster update. Child CEL\n * reads follow schema links to this current roster, so no fan-out is needed. */\nexport async function handleBookMembers(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n): Promise<Response> {\n if (req.method !== \"PATCH\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a human app owner can change members\");\n const body = await readJson(req);\n const rawMembers = optStrArray(body, \"memberIds\");\n const rawExpected = optStrArray(body, \"expectedMemberIds\");\n if (!rawMembers || !rawExpected)\n throw new BrandInputError('\"memberIds\" and \"expectedMemberIds\" are required string arrays');\n const memberIds = Array.from(new Set([\n book.ownerId,\n ...rawMembers.map((id, index) => capString(id, `memberIds[${index}]`, 160)),\n ]));\n if (memberIds.length > 100)\n throw new BrandInputError(\"a brand book supports at most 100 members\");\n const expectedMemberIds = rawExpected.map((id, index) =>\n capString(id, `expectedMemberIds[${index}]`, 160));\n if (!sameStrings(book.memberIds, expectedMemberIds) && !sameStrings(book.memberIds, memberIds))\n throw new BrandConflictError(\"brand book membership changed since review\");\n\n const mutationId = capString(str(body, \"mutationId\"), \"mutationId\", 200);\n const mutationKey = `brand:book-members:v1:${bookId}:${mutationId}`;\n const authority = await requireRouteAuthority(\n ctx,\n req,\n \"app.manage\",\n \"internal\",\n bookId,\n );\n try {\n const tx = await ctx.db.transact(\n [{\n t: \"update\",\n ns: BRAND_NS.book,\n id: bookId,\n attrs: {\n memberIds,\n version: book.version + 1,\n updatedAt: ctx.now(),\n rosterAuthorityRef: authority.authorityRef,\n },\n }],\n {\n mutationId: mutationKey,\n guards: [{\n ns: BRAND_NS.book,\n id: bookId,\n exists: true,\n equals: { memberIds: expectedMemberIds, version: book.version },\n }],\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n },\n );\n return json({ bookId, memberIds, duplicate: tx.duplicate === true });\n } catch (error) {\n if (guardFailure(error))\n throw new BrandConflictError(\"brand book membership changed since review\");\n throw error;\n }\n}\n\n/** `GET /books/:id` — the book row, members only (404 otherwise, matching the\n * view rule — see http.ts). Other methods: 405. */\nexport async function handleBookItem(ctx: BrandRouteCtx, req: Request, bookId: string): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n return json(await loadMemberBook(ctx.db, bookId, ctx.actor.id));\n}\n","// Serving a design so a person can look at it.\n//\n// A Claude Design bundle is a self-contained document that MUST run its own\n// JavaScript to render — the loader inflates its assets into blob: URLs and\n// swaps the document root. So there is no safe way to show one by extracting\n// markup; it has to execute. The question is only where.\n//\n// It executes in a CSP `sandbox` with no `allow-same-origin`, which puts the\n// document in a unique OPAQUE origin: scripts run, but they cannot read the\n// host app's cookies, storage, or DOM, and cannot act as the signed-in user.\n// This is the same posture an artifact host takes, and the bundle loader is\n// explicitly written to work in opaque origins (it handles the file://\n// case), so nothing is lost by denying same-origin.\n//\n// Two related choices:\n// - The bytes are PROXIED, not redirected to the signed storage URL. A\n// redirect would run the design on the storage origin, under whatever\n// headers that origin sets, next to every other app's stored objects.\n// Proxying is what makes the sandbox header ours to set.\n// - Only `design`-kind assets are served this way, and `design` is the\n// only kind whose content type may be text/html. An image can never\n// reach this route, and HTML can never reach a non-design kind.\nimport { DESIGN_ASSET_KIND } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport { linkedAsset } from \"./asset-query\";\nimport { json, loadMemberBook, methodNotAllowed, type BrandRouteCtx } from \"./http\";\n\n/** How long the internal signed read URL lives. Seconds, not minutes: it is\n * fetched immediately and never handed to a client. */\nconst SIGNED_READ_TTL_SECONDS = 60;\n\n/**\n * Headers that make an untrusted HTML document safe to render.\n *\n * `sandbox allow-scripts` (WITHOUT `allow-same-origin`) is the load-bearing\n * one — it grants an opaque origin. `allow-scripts` alone is what the bundle\n * needs; forms, popups, top-navigation, and modals stay denied, so a\n * prototype's form cannot post anywhere and a link cannot navigate the\n * embedder away.\n */\nexport function designPreviewHeaders(frameAncestors: string[]): Record<string, string> {\n return {\n \"content-type\": \"text/html; charset=utf-8\",\n \"content-security-policy\": [\n \"sandbox allow-scripts\",\n `frame-ancestors ${frameAncestors.join(\" \")}`,\n ].join(\"; \"),\n \"x-content-type-options\": \"nosniff\",\n \"referrer-policy\": \"no-referrer\",\n \"cache-control\": \"private, no-store\",\n };\n}\n\n/**\n * `GET /books/:id/assets/:assetId/preview` — the design bundle itself,\n * proxied under the sandbox headers above. Members only; a non-design asset\n * answers 404 (the same answer a missing one gets — the route does not\n * confirm that some other kind of asset exists at that id).\n */\nexport async function handleDesignPreview(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n if (asset.kind !== DESIGN_ASSET_KIND) throw new BrandNotFoundError(`design ${assetId}`);\n const signed = await ctx.db.storage.sign(asset.path, SIGNED_READ_TTL_SECONDS);\n // The signed URL is internal: fetched through the product-owned seam, never\n // handed to the client and never redirected to (see the header note).\n // Through a local: a property call would hand `ctx` to fetch as its receiver.\n const fetchPrivateAsset = ctx.fetchPrivateAsset;\n const fetched = await fetchPrivateAsset(signed, {\n headers: { accept: \"text/html\" },\n redirect: \"manual\",\n signal: req.signal,\n });\n if (!fetched.ok || fetched.type === \"opaqueredirect\")\n throw new BrandNotFoundError(`design ${assetId}`);\n return new Response(new Uint8Array(await fetched.arrayBuffer()), {\n status: 200,\n headers: designPreviewHeaders(ctx.previewFrameAncestors),\n });\n}\n\n/**\n * `GET /books/:id/assets/:assetId/design` — the stored {@link\n * import(\"../design/types\").DesignDigest} as JSON: tokens, fonts, colours,\n * props, and heading outline, without the megabytes. This is what a UI\n * header and a building agent read.\n */\nexport async function handleDesignDigest(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n assetId: string,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n const asset = await linkedAsset(ctx, book, assetId);\n if (asset.kind !== DESIGN_ASSET_KIND || !asset.design)\n throw new BrandNotFoundError(`design ${assetId}`);\n return json(\n { assetId: asset.id, title: asset.title, digest: asset.design },\n 200,\n { \"cache-control\": \"private, no-store\" },\n );\n}\n","import { PROPOSAL_KINDS } from \"../constants\";\nimport { BrandConflictError, BrandInputError } from \"../errors\";\nimport { isBoundedBrandJson } from \"../review\";\nimport type { BrandProposal, BrandProposalReviewSnapshot } from \"../types\";\nimport { capString } from \"../validate\";\nimport { optStr, str } from \"./http\";\n\nconst SNAPSHOT_KEYS = [\n \"audience\",\n \"bookId\",\n \"createdAt\",\n \"createdAuthorityRef\",\n \"createdBy\",\n \"id\",\n \"kind\",\n \"payload\",\n \"provenance\",\n \"rationale\",\n \"reviewDigest\",\n \"status\",\n] as const;\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport interface ProposalResolutionRequest {\n mutationId: string;\n resolution: \"accepted\" | \"rejected\";\n reviewed: BrandProposalReviewSnapshot;\n resolutionNote?: string;\n}\n\nexport function parseProposalResolutionRequest(\n body: Record<string, unknown>,\n bookId: string,\n proposalId: string,\n): ProposalResolutionRequest {\n const allowed = new Set([\n \"mutationId\",\n \"resolution\",\n \"reviewedProposal\",\n \"note\",\n ]);\n if (Object.keys(body).some((key) => !allowed.has(key)))\n throw new BrandInputError(\"proposal resolution body has unknown fields\");\n const mutationId = capString(str(body, \"mutationId\"), \"mutationId\", 200);\n const rawResolution = str(body, \"resolution\");\n if (rawResolution !== \"accepted\" && rawResolution !== \"rejected\")\n throw new BrandInputError('\"resolution\" must be \"accepted\" or \"rejected\"');\n const rawNote = optStr(body, \"note\");\n const resolutionNote = rawNote?.trim()\n ? capString(rawNote, \"note\", 1_000)\n : undefined;\n return {\n mutationId,\n resolution: rawResolution,\n reviewed: parseReviewedProposal(body.reviewedProposal, bookId, proposalId),\n ...(resolutionNote ? { resolutionNote } : {}),\n };\n}\n\n/** Freeze the exact OPEN proposal fields a reviewer sees. */\nexport function proposalReviewSnapshot(proposal: BrandProposal): BrandProposalReviewSnapshot {\n if (proposal.status !== \"open\")\n throw new BrandConflictError(`proposal ${proposal.id} is ${proposal.status}, not open`);\n return {\n id: proposal.id,\n bookId: proposal.bookId,\n kind: proposal.kind,\n status: \"open\",\n payload: proposal.payload,\n rationale: proposal.rationale,\n provenance: proposal.provenance,\n reviewDigest: proposal.reviewDigest,\n audience: proposal.audience,\n createdBy: proposal.createdBy,\n createdAuthorityRef: proposal.createdAuthorityRef,\n createdAt: proposal.createdAt,\n };\n}\n\n/** Strict, bounded request parser: no extra hydration/resolution fields. */\nexport function parseReviewedProposal(\n value: unknown,\n bookId: string,\n proposalId: string,\n): BrandProposalReviewSnapshot {\n // The server bounds the entire guards array. Reserve ample room for guard\n // wrappers and the independent book/palette/receipt guards.\n if (!isBoundedBrandJson(value, { maxDepth: 12, maxNodes: 1_500, maxBytes: 32 * 1024 }))\n throw new BrandInputError('\"reviewedProposal\" is too deeply nested, complex, or large');\n if (!record(value)) throw new BrandInputError('\"reviewedProposal\" must be an object');\n const keys = Object.keys(value).sort();\n if (\n keys.length !== SNAPSHOT_KEYS.length ||\n !SNAPSHOT_KEYS.every((key, index) => key === keys[index])\n ) throw new BrandInputError('\"reviewedProposal\" has an invalid shape');\n if (value.id !== proposalId || value.bookId !== bookId || value.status !== \"open\")\n throw new BrandInputError('\"reviewedProposal\" must identify this open proposal');\n if (\n typeof value.kind !== \"string\" ||\n !(PROPOSAL_KINDS as readonly string[]).includes(value.kind) ||\n !record(value.payload) ||\n typeof value.rationale !== \"string\" ||\n !Array.isArray(value.audience) ||\n value.audience.length < 1 ||\n value.audience.length > 100 ||\n value.audience.some((id) => typeof id !== \"string\" || id.length < 1 || id.length > 200) ||\n new Set(value.audience).size !== value.audience.length ||\n typeof value.createdBy !== \"string\" || value.createdBy.length < 1 || value.createdBy.length > 200 ||\n typeof value.createdAuthorityRef !== \"string\" ||\n value.createdAuthorityRef.length < 1 || value.createdAuthorityRef.length > 200 ||\n !Number.isSafeInteger(value.createdAt) || (value.createdAt as number) < 0 ||\n typeof value.reviewDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.reviewDigest)\n ) throw new BrandInputError('\"reviewedProposal\" has invalid fields');\n if (\n !record(value.provenance) ||\n Object.keys(value.provenance).sort().join(\",\") !==\n \"messageId,sourceAsset,sourceAssetId,taintLabels,turnId\" ||\n (value.provenance.sourceAssetId !== null &&\n (typeof value.provenance.sourceAssetId !== \"string\" ||\n value.provenance.sourceAssetId.length < 1 ||\n value.provenance.sourceAssetId.length > 200)) ||\n (value.provenance.sourceAsset !== null &&\n (!record(value.provenance.sourceAsset) ||\n Object.keys(value.provenance.sourceAsset).sort().join(\",\") !==\n \"analysisDigest,analysisRevision,assetId,contentDigest,contentType,objectEtag,objectSize,pathDigest\" ||\n typeof value.provenance.sourceAsset.assetId !== \"string\" ||\n value.provenance.sourceAsset.assetId.length < 1 ||\n value.provenance.sourceAsset.assetId.length > 200 ||\n typeof value.provenance.sourceAsset.objectEtag !== \"string\" ||\n value.provenance.sourceAsset.objectEtag.length < 1 ||\n value.provenance.sourceAsset.objectEtag.length > 200 ||\n !Number.isSafeInteger(value.provenance.sourceAsset.objectSize) ||\n (value.provenance.sourceAsset.objectSize as number) < 1 ||\n typeof value.provenance.sourceAsset.pathDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.pathDigest) ||\n (value.provenance.sourceAsset.contentType !== null &&\n (typeof value.provenance.sourceAsset.contentType !== \"string\" ||\n value.provenance.sourceAsset.contentType.length < 1 ||\n value.provenance.sourceAsset.contentType.length > 160)) ||\n typeof value.provenance.sourceAsset.contentDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(value.provenance.sourceAsset.contentDigest) ||\n (value.provenance.sourceAsset.analysisRevision !== null &&\n (!Number.isSafeInteger(value.provenance.sourceAsset.analysisRevision) ||\n (value.provenance.sourceAsset.analysisRevision as number) < 0)) ||\n (value.provenance.sourceAsset.analysisDigest !== null &&\n (typeof value.provenance.sourceAsset.analysisDigest !== \"string\" ||\n !/^sha256:[0-9a-f]{64}$/.test(\n value.provenance.sourceAsset.analysisDigest,\n ))) ||\n value.provenance.sourceAsset.assetId !==\n value.provenance.sourceAssetId)) ||\n ((value.provenance.sourceAssetId === null) !==\n (value.provenance.sourceAsset === null)) ||\n (value.provenance.messageId !== null &&\n (typeof value.provenance.messageId !== \"string\" ||\n value.provenance.messageId.length < 1 ||\n value.provenance.messageId.length > 200)) ||\n (value.provenance.turnId !== null &&\n (typeof value.provenance.turnId !== \"string\" ||\n value.provenance.turnId.length < 1 ||\n value.provenance.turnId.length > 200)) ||\n !Array.isArray(value.provenance.taintLabels) ||\n value.provenance.taintLabels.length > 16 ||\n value.provenance.taintLabels.some((label) =>\n typeof label !== \"string\" || label.length < 1 || label.length > 120) ||\n new Set(value.provenance.taintLabels).size !== value.provenance.taintLabels.length\n ) throw new BrandInputError('\"reviewedProposal.provenance\" is invalid');\n return value as unknown as BrandProposalReviewSnapshot;\n}\n\nexport const proposalGuardEquals = (\n snapshot: BrandProposalReviewSnapshot,\n): Record<string, unknown> => ({ ...snapshot });\n","import { BRAND_NS } from \"../constants\";\nimport { BrandInputError } from \"../errors\";\nimport { acceptProposalOps, rejectProposalOps } from \"../ops/palettes\";\nimport { upsertSectionOps } from \"../ops/sections\";\nimport { brandJsonDigest } from \"../review\";\nimport { compileBrandTokens } from \"../tokens/compile\";\nimport type {\n BrandBook,\n BrandOp,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTokensSnapshot,\n Swatch,\n TypographySection,\n} from \"../types\";\nimport { assertSwatches } from \"../validate\";\n\nexport interface ProposalEffectInput {\n proposal: BrandProposal;\n book: BrandBook;\n resolution: \"accepted\" | \"rejected\";\n receiptId: string;\n actionDigest: string;\n paletteId?: string;\n priorPalette?: BrandPalette;\n approvedTypography?: BrandSection;\n actorId: string;\n now: number;\n resolutionNote?: string;\n}\n\nasync function tokenSnapshot(\n swatches: Swatch[],\n typography: TypographySection | undefined,\n input: ProposalEffectInput,\n paletteId: string,\n paletteReceiptId: string,\n paletteActionDigest: string,\n typographyReceiptId?: string,\n typographyActionDigest?: string,\n): Promise<BrandTokensSnapshot> {\n const compiled = compileBrandTokens({\n swatches,\n ...(typography ? { typography, overrides: typography.tokenOverrides } : {}),\n });\n const sources = {\n paletteId,\n paletteReceiptId,\n paletteActionDigest,\n typographyReceiptId: typographyReceiptId ?? null,\n typographyActionDigest: typographyActionDigest ?? null,\n };\n return {\n light: compiled.light,\n dark: compiled.dark,\n warnings: compiled.warnings,\n compiledAt: input.now,\n paletteId,\n paletteReceiptId,\n paletteActionDigest,\n ...(typographyReceiptId ? { typographyReceiptId } : {}),\n ...(typographyActionDigest ? { typographyActionDigest } : {}),\n sourceDigest: await brandJsonDigest(sources),\n };\n}\n\nfunction stampProposal(ops: BrandOp[], input: ProposalEffectInput): void {\n const op = ops.find(\n (candidate) =>\n candidate.t === \"update\" &&\n candidate.ns === BRAND_NS.proposal &&\n candidate.id === input.proposal.id,\n );\n if (!op || op.t !== \"update\") throw new Error(\"proposal resolution op missing\");\n Object.assign(op.attrs, {\n approvedBy: input.actorId,\n appliedBy: input.actorId,\n resolutionReceiptId: input.receiptId,\n resolutionActionDigest: input.actionDigest,\n });\n}\n\n/** Build all live effects for one guarded decision. */\nexport async function proposalDecisionOps(input: ProposalEffectInput): Promise<BrandOp[]> {\n const common = {\n proposal: input.proposal,\n resolvedBy: input.actorId,\n now: input.now,\n resolutionNote: input.resolutionNote,\n };\n if (input.resolution === \"rejected\") {\n const ops = rejectProposalOps(common);\n stampProposal(ops, input);\n return ops;\n }\n\n let ops: BrandOp[];\n if (input.proposal.kind === \"palette\") {\n if (!input.paletteId) throw new Error(\"accepted palette id missing\");\n ops = acceptProposalOps({\n ...common,\n paletteId: input.paletteId,\n approvalReceiptId: input.receiptId,\n approvalActionDigest: input.actionDigest,\n });\n const swatches = assertSwatches(input.proposal.payload.swatches);\n const tokens = await tokenSnapshot(\n swatches,\n input.approvedTypography?.content as TypographySection | undefined,\n input,\n input.paletteId,\n input.receiptId,\n input.actionDigest,\n input.approvedTypography?.approvalReceiptId,\n input.approvedTypography?.approvalActionDigest,\n );\n const bookOp = ops.find(\n (op) => op.t === \"update\" && op.ns === BRAND_NS.book && op.id === input.book.id,\n );\n if (!bookOp || bookOp.t !== \"update\") throw new Error(\"book activation op missing\");\n Object.assign(bookOp.attrs, {\n version: input.book.version + 1,\n activationRevision: input.book.activationRevision + 1,\n tokens,\n });\n if (input.priorPalette && input.priorPalette.id !== input.paletteId) {\n ops.unshift({\n t: \"update\",\n ns: BRAND_NS.palette,\n id: input.priorPalette.id,\n attrs: { status: \"archived\", updatedAt: input.now },\n });\n }\n } else {\n const content = input.proposal.payload.content;\n if (typeof content !== \"object\" || content === null || Array.isArray(content))\n throw new BrandInputError(\"proposal payload.content must be an object\");\n ops = [\n ...upsertSectionOps({\n bookId: input.book.id,\n kind: input.proposal.kind,\n content: content as Record<string, unknown>,\n status: \"approved\",\n audience: input.book.memberIds,\n updatedBy: input.actorId,\n approvalReceiptId: input.receiptId,\n approvalActionDigest: input.actionDigest,\n now: input.now,\n }),\n {\n t: \"update\",\n ns: BRAND_NS.book,\n id: input.book.id,\n attrs: {\n activationRevision: input.book.activationRevision + 1,\n version: input.book.version + 1,\n updatedAt: input.now,\n },\n },\n {\n t: \"update\",\n ns: BRAND_NS.proposal,\n id: input.proposal.id,\n attrs: {\n status: \"accepted\",\n resolvedBy: input.actorId,\n resolvedAt: input.now,\n ...(input.resolutionNote ? { resolutionNote: input.resolutionNote } : {}),\n },\n },\n ];\n if (input.proposal.kind === \"typography\" && input.priorPalette) {\n const bookOp = ops.find(\n (op) => op.t === \"update\" && op.ns === BRAND_NS.book && op.id === input.book.id,\n );\n if (bookOp?.t === \"update\") {\n if (!input.priorPalette.approvalReceiptId || !input.priorPalette.approvalActionDigest)\n throw new BrandInputError(\"active palette is missing approval provenance\");\n bookOp.attrs.tokens = await tokenSnapshot(\n input.priorPalette.swatches,\n content as TypographySection,\n input,\n input.priorPalette.id,\n input.priorPalette.approvalReceiptId,\n input.priorPalette.approvalActionDigest,\n input.receiptId,\n input.actionDigest,\n );\n }\n }\n }\n stampProposal(ops, input);\n return ops;\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandForbiddenError } from \"../errors\";\nimport {\n brandJsonDigest,\n canonicalBrandJson,\n isBrandHumanAuthorityConsumption,\n receiptAsWritten,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandHumanAuthorityConsumption,\n BrandProposalReviewSnapshot,\n} from \"../types\";\nimport type { BrandRouteCtx } from \"./http\";\n\n/** Fixed-width local/central idempotency domain. Caller-controlled ids are\n * hashed so every legal request stays below registry and database key limits. */\nexport async function proposalResolutionMutationKey(\n bookId: string,\n proposalId: string,\n mutationId: string,\n): Promise<string> {\n const digest = await brandJsonDigest({\n version: 3,\n bookId,\n proposalId,\n mutationId,\n });\n return `brand:proposal-resolution:v3:${digest.slice(\"sha256:\".length)}`;\n}\n\nexport async function proposalReceiptByMutation(\n ctx: BrandRouteCtx,\n mutationKey: string,\n): Promise<BrandApprovalReceipt | undefined> {\n const result = await ctx.db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { mutationKey } },\n book: {},\n },\n });\n const row = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== row.bookId\n ) return undefined;\n const { book: _book, ...receipt } = row;\n // Back to the shape it was written in before anyone verifies it: `createdAt`\n // is a `date`, so the store hands back ISO text the digest never covered.\n return receiptAsWritten(receipt) as BrandApprovalReceipt;\n}\n\nexport async function consumeProposalAuthority(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n proposalId: string,\n actionDigest: string,\n mutationKey: string,\n): Promise<BrandHumanAuthorityConsumption> {\n const authority = await ctx.consumeHumanExact({\n req,\n actor: ctx.actor,\n appId: ctx.appId,\n capability: \"brand.proposal.resolve\",\n projectCapability: \"brand.approve\",\n effect: \"internal\",\n resource: { bookId, proposalId },\n actionDigest,\n consumptionIdempotencyKey: mutationKey,\n });\n const resourceDigest = await brandJsonDigest({ bookId, proposalId });\n if (\n !isBrandHumanAuthorityConsumption(authority) ||\n authority.actorPrincipalId !== ctx.actor.id ||\n authority.appId !== ctx.appId ||\n authority.actionDigest !== actionDigest ||\n authority.resourceDigest !== resourceDigest ||\n authority.consumptionIdempotencyKey !== mutationKey\n ) throw new BrandForbiddenError(\n \"a verified human-exact brand approval is required\",\n );\n return authority;\n}\n\nexport function sameProposalResolutionRequest(\n receipt: BrandApprovalReceipt,\n reviewed: BrandProposalReviewSnapshot,\n resolution: \"accepted\" | \"rejected\",\n note: string | undefined,\n paletteId: string | undefined,\n): boolean {\n return receipt.resolution === resolution &&\n (receipt.resolutionNote ?? null) === (note ?? null) &&\n (receipt.paletteId ?? null) === (paletteId ?? null) &&\n canonicalBrandJson(receipt.reviewedProposal) ===\n canonicalBrandJson(reviewed);\n}\n","import { BRAND_NS } from \"../constants\";\nimport { BrandConflictError } from \"../errors\";\nimport {\n canonicalBrandJson,\n verifyBrandApprovalReceipt,\n receiptAsWritten,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandBook,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n assertHex,\n assertSectionContent,\n assertSwatches,\n capString,\n} from \"../validate\";\nimport type { BrandRouteCtx } from \"./http\";\n\nasync function receipt(\n ctx: BrandRouteCtx,\n id: string,\n actionDigest: string,\n expected: {\n bookId: string;\n kind: BrandProposal[\"kind\"];\n paletteId?: string;\n proposalId?: string;\n content?: Record<string, unknown>;\n },\n): Promise<BrandApprovalReceipt> {\n const result = await ctx.db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { id } },\n book: {},\n },\n });\n const row = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !row ||\n row.actionDigest !== actionDigest ||\n row.resolution !== \"accepted\" ||\n row.bookId !== expected.bookId ||\n row.reviewedProposal.bookId !== expected.bookId ||\n row.reviewedProposal.kind !== expected.kind ||\n !Array.isArray(row.book) ||\n row.book.length !== 1 ||\n row.book[0]?.id !== expected.bookId ||\n (expected.paletteId !== undefined && row.paletteId !== expected.paletteId) ||\n (expected.proposalId !== undefined && row.proposalId !== expected.proposalId) ||\n (expected.content !== undefined &&\n canonicalBrandJson(row.reviewedProposal.payload.content) !==\n canonicalBrandJson(expected.content))\n ) throw new BrandConflictError(`approval receipt ${id} is invalid`);\n const { book: _book, ...stored } = row;\n const unhydrated = receiptAsWritten(stored);\n if (!(await verifyBrandApprovalReceipt(unhydrated)))\n throw new BrandConflictError(`approval receipt ${id} is invalid`);\n return unhydrated as BrandApprovalReceipt;\n}\n\nexport async function activePalette(\n ctx: BrandRouteCtx,\n book: BrandBook,\n): Promise<{ palette?: BrandPalette; receipt?: BrandApprovalReceipt }> {\n if (!book.activePaletteId) return {};\n const result = await ctx.db.query({\n [BRAND_NS.palette]: {\n $: { where: { id: book.activePaletteId } },\n book: {},\n },\n });\n const palette = (result[BRAND_NS.palette] ?? [])[0] as\n | (BrandPalette & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !palette ||\n palette.bookId !== book.id ||\n palette.status !== \"active\" ||\n !palette.proposalId ||\n !palette.approvalReceiptId ||\n !palette.approvalActionDigest ||\n !Array.isArray(palette.book) ||\n palette.book.length !== 1 ||\n palette.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"active palette is missing valid approval provenance\",\n );\n const approval = await receipt(\n ctx,\n palette.approvalReceiptId,\n palette.approvalActionDigest,\n {\n bookId: book.id,\n kind: \"palette\",\n paletteId: palette.id,\n proposalId: palette.proposalId,\n },\n );\n let expectedName: string;\n let expectedSwatches: ReturnType<typeof assertSwatches>;\n let expectedSeed: string | undefined;\n try {\n expectedName = capString(\n approval.reviewedProposal.payload.name,\n \"reviewedProposal.payload.name\",\n 120,\n );\n expectedSwatches = assertSwatches(\n approval.reviewedProposal.payload.swatches,\n );\n expectedSeed = approval.reviewedProposal.payload.seedHex === undefined\n ? undefined\n : assertHex(\n approval.reviewedProposal.payload.seedHex,\n \"reviewedProposal.payload.seedHex\",\n );\n } catch {\n throw new BrandConflictError(\"active palette approval payload is invalid\");\n }\n const expectedSource = approval.reviewedProposal.provenance.sourceAsset\n ? \"extracted\"\n : expectedSeed\n ? \"derived\"\n : \"manual\";\n if (\n palette.proposalId !== approval.proposalId ||\n palette.name !== expectedName ||\n canonicalBrandJson(palette.swatches) !== canonicalBrandJson(expectedSwatches) ||\n (palette.seedHex ?? null) !== (expectedSeed ?? null) ||\n palette.source !== expectedSource ||\n palette.rationale !== approval.reviewedProposal.rationale ||\n canonicalBrandJson(palette.audience) !==\n canonicalBrandJson(approval.reviewedProposal.audience) ||\n palette.createdAt !== approval.createdAt ||\n palette.updatedAt !== approval.createdAt\n ) throw new BrandConflictError(\n \"active palette does not match its approved proposal\",\n );\n return { palette, receipt: approval };\n}\n\nexport async function approvedTypography(\n ctx: BrandRouteCtx,\n book: BrandBook,\n): Promise<{ section?: BrandSection; receipt?: BrandApprovalReceipt }> {\n const key = `${book.id}:typography`;\n const result = await ctx.db.query({\n [BRAND_NS.section]: {\n $: { where: { key } },\n book: {},\n },\n });\n const section = (result[BRAND_NS.section] ?? [])[0] as\n | (BrandSection & { book?: Array<{ id: string }> })\n | undefined;\n if (!section || section.status !== \"approved\") return {};\n if (\n section.bookId !== book.id ||\n section.kind !== \"typography\" ||\n !section.approvalReceiptId ||\n !section.approvalActionDigest ||\n !Array.isArray(section.book) ||\n section.book.length !== 1 ||\n section.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"approved typography is missing valid approval provenance\",\n );\n assertSectionContent(\"typography\", section.content);\n return {\n section,\n receipt: await receipt(\n ctx,\n section.approvalReceiptId,\n section.approvalActionDigest,\n { bookId: book.id, kind: \"typography\", content: section.content },\n ),\n };\n}\n\nexport const receiptGuard = (\n value: BrandApprovalReceipt,\n): BrandTransactGuard => ({\n ns: BRAND_NS.approvalReceipt,\n id: value.id,\n exists: true,\n equals: {\n actionDigest: value.actionDigest,\n receiptDigest: value.receiptDigest,\n resolution: \"accepted\",\n },\n});\n","import { BRAND_NS } from \"../constants\";\nimport { BrandConflictError, BrandNotFoundError } from \"../errors\";\nimport { brandJsonDigest } from \"../review\";\nimport type {\n BrandAsset,\n BrandBook,\n BrandDecisionBinding,\n BrandPalette,\n BrandProposal,\n BrandSection,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n assertSectionContent,\n assertSwatches,\n capString,\n} from \"../validate\";\nimport type { BrandRouteCtx } from \"./http\";\nimport {\n activePalette,\n approvedTypography,\n receiptGuard,\n} from \"./proposal-dependencies\";\n\nexport interface ProposalDecisionState {\n priorPalette?: BrandPalette;\n approvedTypography?: BrandSection;\n binding: BrandDecisionBinding;\n effectDescriptor: Record<string, unknown>;\n dependencyGuards: BrandTransactGuard[];\n}\n\n/** Resolve, validate, and digest every live dependency before authority is\n * consumed. The caller must include every returned guard in the local CAS. */\nexport async function proposalDecisionState(\n ctx: BrandRouteCtx,\n req: Request,\n book: BrandBook,\n proposal: BrandProposal,\n resolution: \"accepted\" | \"rejected\",\n receiptId: string,\n paletteId?: string,\n): Promise<ProposalDecisionState> {\n const needsPalette = resolution === \"accepted\" &&\n (proposal.kind === \"palette\" || proposal.kind === \"typography\");\n const paletteDep = needsPalette ? await activePalette(ctx, book) : {};\n const typeDep = resolution === \"accepted\" && proposal.kind === \"palette\"\n ? await approvedTypography(ctx, book)\n : {};\n const dependencyGuards: BrandTransactGuard[] = [];\n const source = proposal.provenance.sourceAsset;\n let sourceAsset: (BrandAsset & { book?: Array<{ id: string }> }) | undefined;\n if (source && resolution === \"accepted\") {\n const result = await ctx.db.query({\n [BRAND_NS.asset]: {\n $: { where: { id: source.assetId, bookId: book.id } },\n book: {},\n },\n });\n sourceAsset = (result[BRAND_NS.asset] ?? [])[0] as\n | (BrandAsset & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !sourceAsset ||\n sourceAsset.id !== source.assetId ||\n sourceAsset.bookId !== book.id ||\n sourceAsset.status !== \"live\" ||\n sourceAsset.deletedAt !== undefined ||\n sourceAsset.contentDigest !== source.contentDigest ||\n sourceAsset.size !== source.objectSize ||\n sourceAsset.contentType !== source.contentType ||\n (await brandJsonDigest({ appId: ctx.appId, path: sourceAsset.path })) !==\n source.pathDigest ||\n sourceAsset.analysisRevision !== source.analysisRevision ||\n (sourceAsset.analysisDigest ?? null) !== source.analysisDigest ||\n !Array.isArray(sourceAsset.book) ||\n sourceAsset.book.length !== 1 ||\n sourceAsset.book[0]?.id !== book.id\n ) throw new BrandConflictError(\n \"source asset changed since the proposal was reviewed\",\n );\n if (!(await ctx.verifySourceAssetSnapshot({\n req,\n appId: ctx.appId,\n bookId: book.id,\n assetId: source.assetId,\n path: sourceAsset.path,\n snapshot: source,\n }))) throw new BrandConflictError(\n \"source asset bytes changed since the proposal was reviewed\",\n );\n dependencyGuards.push({\n ns: BRAND_NS.asset,\n id: sourceAsset.id,\n exists: true,\n equals: {\n bookId: book.id,\n status: \"live\",\n path: sourceAsset.path,\n storageObjectId: sourceAsset.storageObjectId,\n contentDigest: source.contentDigest,\n contentType: source.contentType,\n size: source.objectSize,\n analysisRevision: source.analysisRevision,\n ...(source.analysisDigest ? { analysisDigest: source.analysisDigest } : {}),\n },\n });\n }\n if (paletteDep.palette && paletteDep.receipt) {\n dependencyGuards.push({\n ns: BRAND_NS.palette,\n id: paletteDep.palette.id,\n exists: true,\n equals: {\n bookId: book.id,\n status: \"active\",\n name: paletteDep.palette.name,\n swatches: paletteDep.palette.swatches,\n seedHex: paletteDep.palette.seedHex ?? null,\n source: paletteDep.palette.source,\n rationale: paletteDep.palette.rationale,\n proposalId: paletteDep.palette.proposalId,\n approvalReceiptId: paletteDep.palette.approvalReceiptId,\n approvalActionDigest: paletteDep.palette.approvalActionDigest,\n audience: paletteDep.palette.audience,\n createdAt: paletteDep.palette.createdAt,\n updatedAt: paletteDep.palette.updatedAt,\n },\n }, receiptGuard(paletteDep.receipt));\n }\n if (typeDep.section && typeDep.receipt) {\n dependencyGuards.push({\n ns: BRAND_NS.section,\n id: typeDep.section.id,\n exists: true,\n equals: {\n key: typeDep.section.key,\n bookId: book.id,\n kind: \"typography\",\n status: \"approved\",\n content: typeDep.section.content,\n approvalReceiptId: typeDep.section.approvalReceiptId,\n approvalActionDigest: typeDep.section.approvalActionDigest,\n updatedAt: typeDep.section.updatedAt,\n },\n }, receiptGuard(typeDep.receipt));\n }\n\n let approvedContent: Record<string, unknown> | null = null;\n let paletteResult: Record<string, unknown> | null = null;\n if (resolution === \"accepted\" && proposal.kind === \"palette\") {\n if (!paletteId) throw new BrandNotFoundError(\"resulting palette id\");\n paletteResult = {\n id: paletteId,\n name: capString(proposal.payload.name, \"payload.name\", 120),\n swatches: assertSwatches(proposal.payload.swatches),\n seedHex: proposal.payload.seedHex ?? null,\n receiptId,\n archivePaletteId: paletteDep.palette?.id ?? null,\n };\n } else if (resolution === \"accepted\") {\n approvedContent = assertSectionContent(\n proposal.kind,\n proposal.payload.content,\n );\n }\n const tokenSources = resolution === \"accepted\" && (\n proposal.kind === \"palette\" || proposal.kind === \"typography\"\n ) ? {\n paletteReceiptId: proposal.kind === \"palette\"\n ? receiptId\n : paletteDep.palette?.approvalReceiptId ?? null,\n paletteActionDigest: proposal.kind === \"palette\"\n ? \"this-action\"\n : paletteDep.palette?.approvalActionDigest ?? null,\n typographyReceiptId: proposal.kind === \"typography\"\n ? receiptId\n : typeDep.section?.approvalReceiptId ?? null,\n typographyActionDigest: proposal.kind === \"typography\"\n ? \"this-action\"\n : typeDep.section?.approvalActionDigest ?? null,\n } : null;\n const effectDescriptor = {\n proposalId: proposal.id,\n resolution,\n nextBookVersion: resolution === \"accepted\" ? book.version + 1 : null,\n nextActivationRevision:\n resolution === \"accepted\" ? book.activationRevision + 1 : null,\n resultingActivePaletteId: proposal.kind === \"palette\" && resolution === \"accepted\"\n ? paletteId ?? null\n : book.activePaletteId ?? null,\n palette: paletteResult,\n approvedSection: approvedContent\n ? { kind: proposal.kind, content: approvedContent, receiptId }\n : null,\n tokenSources,\n };\n const binding: BrandDecisionBinding = {\n version: 1,\n bookVersion: book.version,\n activationRevision: book.activationRevision,\n activePaletteId: book.activePaletteId ?? null,\n memberIdsDigest: await brandJsonDigest(book.memberIds),\n activePaletteDigest: paletteDep.palette\n ? await brandJsonDigest({\n id: paletteDep.palette.id,\n swatches: paletteDep.palette.swatches,\n approvalReceiptId: paletteDep.palette.approvalReceiptId,\n approvalActionDigest: paletteDep.palette.approvalActionDigest,\n })\n : null,\n typographyDigest: typeDep.section\n ? await brandJsonDigest({\n key: typeDep.section.key,\n content: typeDep.section.content,\n approvalReceiptId: typeDep.section.approvalReceiptId,\n approvalActionDigest: typeDep.section.approvalActionDigest,\n })\n : null,\n sourceAssetDigest: source\n ? await brandJsonDigest(source)\n : null,\n effectDigest: await brandJsonDigest(effectDescriptor),\n };\n return {\n ...(paletteDep.palette ? { priorPalette: paletteDep.palette } : {}),\n ...(typeDep.section ? { approvedTypography: typeDep.section } : {}),\n binding,\n effectDescriptor,\n dependencyGuards,\n };\n}\n","// Decisions consume one credential-bound central `human_exact` authority use.\n// Local receipts are immutable projections; their hash proves consistency,\n// while authenticity comes only from the host's central receipt verifier.\nimport { BRAND_NS } from \"../constants\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandNotFoundError,\n BrandReviewStateChangedError,\n} from \"../errors\";\nimport {\n brandAuthorityRef,\n brandJsonDigest,\n canonicalBrandJson,\n proposalAsWritten,\n verifyBrandApprovalReceipt,\n} from \"../review\";\nimport type {\n BrandApprovalReceipt,\n BrandProposal,\n BrandTransactGuard,\n} from \"../types\";\nimport {\n json,\n loadMemberBook,\n methodNotAllowed,\n readJson,\n type BrandRouteCtx,\n} from \"./http\";\nimport {\n parseProposalResolutionRequest,\n proposalGuardEquals,\n proposalReviewSnapshot,\n} from \"./proposal-input\";\nimport { proposalDecisionOps } from \"./proposal-effects\";\nimport {\n consumeProposalAuthority,\n proposalReceiptByMutation,\n proposalResolutionMutationKey,\n sameProposalResolutionRequest,\n} from \"./proposal-resolution-receipts\";\nimport { proposalDecisionState } from \"./proposal-state\";\n\nexport { proposalResolutionMutationKey } from \"./proposal-resolution-receipts\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst sameStrings = (left: string[], right: string[]): boolean =>\n left.length === right.length && left.every((value, index) => value === right[index]);\nconst guardFailure = (error: unknown): boolean =>\n record(error) && error.code === \"transact_guard_failed\";\n\n/** `POST /books/:bookId/proposals/:proposalId/resolve` — direct human member\n * plus current app owner/co-owner central approval. */\nexport async function handleProposalResolution(\n ctx: BrandRouteCtx,\n req: Request,\n bookId: string,\n proposalId: string,\n): Promise<Response> {\n if (req.method !== \"POST\") return methodNotAllowed();\n const book = await loadMemberBook(ctx.db, bookId, ctx.actor.id);\n if (ctx.actor.kind !== \"human\")\n throw new BrandForbiddenError(\"only a directly authenticated human can resolve a proposal\");\n\n const body = await readJson(req);\n const {\n mutationId,\n resolution,\n reviewed,\n resolutionNote,\n } = parseProposalResolutionRequest(body, bookId, proposalId);\n const mutationKey = await proposalResolutionMutationKey(\n bookId,\n proposalId,\n mutationId,\n );\n const stable = (await brandJsonDigest({ mutationKey })).slice(7);\n const receiptId = `brand-receipt-${stable.slice(0, 32)}`;\n const paletteId = resolution === \"accepted\" && reviewed.kind === \"palette\"\n ? `brand-palette-${stable.slice(32)}`\n : undefined;\n\n // Completed retries re-authenticate and replay the exact central receipt;\n // they never need the now-resolved proposal row.\n const existing = await proposalReceiptByMutation(ctx, mutationKey);\n if (existing) {\n if (\n !(await verifyBrandApprovalReceipt(existing)) ||\n !sameProposalResolutionRequest(\n existing, reviewed, resolution, resolutionNote, paletteId,\n )\n ) throw new BrandConflictError(\"mutationId was used for another decision\");\n const replayed = await consumeProposalAuthority(\n ctx, req, bookId, proposalId, existing.actionDigest, mutationKey,\n );\n if (\n canonicalBrandJson(replayed) !==\n canonicalBrandJson(existing.authorityConsumption)\n ) throw new BrandConflictError(\"central approval receipt changed\");\n return json({ receipt: existing, duplicate: true });\n }\n\n const result = await ctx.db.query({\n [BRAND_NS.proposal]: {\n $: { where: { id: proposalId, bookId } },\n book: {},\n },\n });\n // Back to the shape it was written in: `reviewDigest` covers `createdAt`,\n // which the store hands back as ISO text it never digested.\n const proposal = proposalAsWritten((result[BRAND_NS.proposal] ?? [])[0]) as\n | (BrandProposal & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !proposal ||\n proposal.bookId !== book.id ||\n !Array.isArray(proposal.book) ||\n proposal.book.length !== 1 ||\n proposal.book[0]?.id !== book.id\n ) throw new BrandNotFoundError(`proposal ${proposalId}`);\n const current = proposalReviewSnapshot(proposal);\n const { reviewDigest, ...unsignedReview } = current;\n if (\n (await brandJsonDigest(unsignedReview)) !== reviewDigest ||\n canonicalBrandJson(current) !== canonicalBrandJson(reviewed)\n ) throw new BrandConflictError(\"proposal changed since review\");\n // Acceptance applies live effects and therefore requires a fresh review\n // against the current roster. Rejection applies no Brand materialization:\n // a current human owner who remains a book member may close the exact\n // immutable stale proposal instead of leaving it permanently unresolvable.\n if (resolution === \"accepted\" && !sameStrings(current.audience, book.memberIds))\n throw new BrandConflictError(\"book membership changed; review the proposal again\");\n\n const state = await proposalDecisionState(\n ctx, req, book, proposal, resolution, receiptId, paletteId,\n );\n const actionDigest = await brandJsonDigest({\n version: 1,\n reviewedProposal: current,\n resolution,\n resolutionNote: resolutionNote ?? null,\n paletteId: paletteId ?? null,\n decisionBinding: state.binding,\n });\n const authority = await consumeProposalAuthority(\n ctx, req, bookId, proposalId, actionDigest, mutationKey,\n );\n const receiptBase = {\n version: 1 as const,\n id: receiptId,\n mutationKey,\n bookId,\n proposalId,\n resolution,\n ...(paletteId ? { paletteId } : {}),\n ...(resolutionNote ? { resolutionNote } : {}),\n reviewedProposal: current,\n actionDigest,\n decisionBinding: state.binding,\n approvedBy: ctx.actor.id,\n approvedByKind: \"human\" as const,\n appliedBy: ctx.actor.id,\n appliedByKind: \"human\" as const,\n authorityRef: brandAuthorityRef(authority),\n authorityCapability: \"brand.approve\" as const,\n authorityConsumption: authority,\n createdAt: authority.consumedAt,\n };\n const receipt: BrandApprovalReceipt = {\n ...receiptBase,\n receiptDigest: await brandJsonDigest(receiptBase),\n };\n const ops = await proposalDecisionOps({\n proposal: { ...proposal, audience: [...book.memberIds] },\n book,\n resolution,\n receiptId,\n actionDigest,\n ...(paletteId ? { paletteId } : {}),\n ...(state.priorPalette ? { priorPalette: state.priorPalette } : {}),\n ...(state.approvedTypography\n ? { approvedTypography: state.approvedTypography }\n : {}),\n actorId: ctx.actor.id,\n now: authority.consumedAt,\n resolutionNote,\n });\n ops.push({\n t: \"update\",\n ns: BRAND_NS.approvalReceipt,\n id: receipt.id,\n attrs: receipt,\n }, {\n t: \"link\",\n ns: BRAND_NS.approvalReceipt,\n id: receipt.id,\n label: \"book\",\n target: bookId,\n });\n const guards: BrandTransactGuard[] = [\n {\n ns: BRAND_NS.proposal,\n id: proposalId,\n exists: true,\n equals: proposalGuardEquals(current),\n },\n { ns: BRAND_NS.approvalReceipt, id: receiptId, exists: false },\n {\n ns: BRAND_NS.book,\n id: bookId,\n exists: true,\n equals: {\n version: book.version,\n activationRevision: book.activationRevision,\n memberIds: book.memberIds,\n },\n },\n ...state.dependencyGuards,\n ];\n if (paletteId) {\n guards.push({ ns: BRAND_NS.palette, id: paletteId, exists: false });\n }\n try {\n const tx = await ctx.db.transact(ops, {\n mutationId: mutationKey,\n guards,\n asUser: ctx.actor.id,\n ...(ctx.actor.email ? { asEmail: ctx.actor.email } : {}),\n asPrincipalKind: \"human\",\n });\n if (tx.duplicate) {\n const replay = await proposalReceiptByMutation(ctx, mutationKey);\n if (\n !replay ||\n !(await verifyBrandApprovalReceipt(replay)) ||\n !sameProposalResolutionRequest(\n replay, reviewed, resolution, resolutionNote, paletteId,\n ) ||\n canonicalBrandJson(replay.authorityConsumption) !==\n canonicalBrandJson(authority)\n )\n throw new BrandConflictError(\"proposal decision replay is invalid\");\n return json({ receipt: replay, duplicate: true });\n }\n return json({ receipt, duplicate: false });\n } catch (error) {\n if (guardFailure(error)) throw new BrandReviewStateChangedError();\n throw error;\n }\n}\n","// Tokens are served only from an approval-bound cache. GET never compiles\n// drafts or repairs stale state; any missing/mismatched dependency fails\n// closed until a new human-approved activation recompiles the cache.\nimport { BRAND_NS } from \"../constants\";\nimport { BrandNotFoundError } from \"../errors\";\nimport { brandJsonDigest, receiptAsWritten, verifyBrandApprovalReceipt } from \"../review\";\nimport { renderTokensCss } from \"../tokens/css\";\nimport type { BrandTokens } from \"../tokens/types\";\nimport type {\n BrandActor,\n BrandApprovalReceipt,\n BrandBook,\n BrandPalette,\n BrandSection,\n BrandTokensSnapshot,\n} from \"../types\";\nimport { json, loadBook, loadMemberBook, methodNotAllowed } from \"./http\";\n\nconst record = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\nconst missing = (bookId: string): never => {\n throw new BrandNotFoundError(`compiled tokens for brand book ${bookId}`);\n};\n\nasync function acceptedReceipt(\n db: Parameters<typeof loadBook>[0],\n bookId: string,\n receiptId: string,\n actionDigest: string,\n): Promise<BrandApprovalReceipt> {\n const result = await db.query({\n [BRAND_NS.approvalReceipt]: {\n $: { where: { id: receiptId, bookId } },\n book: {},\n },\n });\n const receipt = (result[BRAND_NS.approvalReceipt] ?? [])[0] as\n | (BrandApprovalReceipt & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !receipt ||\n receipt.resolution !== \"accepted\" ||\n receipt.actionDigest !== actionDigest ||\n !Array.isArray(receipt.book) ||\n receipt.book.length !== 1 ||\n receipt.book[0]?.id !== bookId\n ) return missing(bookId);\n const { book: _book, ...stored } = receipt;\n const unhydrated = receiptAsWritten(stored);\n if (!(await verifyBrandApprovalReceipt(unhydrated))) return missing(bookId);\n return unhydrated as BrandApprovalReceipt;\n}\n\nasync function approvedCache(\n db: Parameters<typeof loadBook>[0],\n book: BrandBook,\n): Promise<BrandTokensSnapshot> {\n const cache = book.tokens;\n if (\n !cache ||\n !record(cache.light) ||\n !record(cache.dark) ||\n !book.activePaletteId ||\n cache.paletteId !== book.activePaletteId ||\n !cache.paletteReceiptId ||\n !cache.paletteActionDigest ||\n !cache.sourceDigest\n ) return missing(book.id);\n const paletteResult = await db.query({\n [BRAND_NS.palette]: {\n $: { where: { id: cache.paletteId, bookId: book.id } },\n book: {},\n },\n });\n const palette = (paletteResult[BRAND_NS.palette] ?? [])[0] as\n | (BrandPalette & { book?: Array<{ id: string }> })\n | undefined;\n if (\n !palette ||\n palette.status !== \"active\" ||\n palette.approvalReceiptId !== cache.paletteReceiptId ||\n palette.approvalActionDigest !== cache.paletteActionDigest ||\n !Array.isArray(palette.book) ||\n palette.book.length !== 1 ||\n palette.book[0]?.id !== book.id\n ) return missing(book.id);\n await acceptedReceipt(\n db, book.id, cache.paletteReceiptId, cache.paletteActionDigest,\n );\n\n const hasTypeId = cache.typographyReceiptId !== undefined;\n const hasTypeDigest = cache.typographyActionDigest !== undefined;\n if (hasTypeId !== hasTypeDigest) return missing(book.id);\n const sectionResult = await db.query({\n [BRAND_NS.section]: {\n $: { where: { key: `${book.id}:typography` } },\n book: {},\n },\n });\n const typography = (sectionResult[BRAND_NS.section] ?? [])[0] as\n | (BrandSection & { book?: Array<{ id: string }> })\n | undefined;\n if (hasTypeId) {\n if (\n !typography ||\n typography.bookId !== book.id ||\n typography.kind !== \"typography\" ||\n typography.status !== \"approved\" ||\n typography.approvalReceiptId !== cache.typographyReceiptId ||\n typography.approvalActionDigest !== cache.typographyActionDigest ||\n !Array.isArray(typography.book) ||\n typography.book.length !== 1 ||\n typography.book[0]?.id !== book.id\n ) return missing(book.id);\n await acceptedReceipt(\n db,\n book.id,\n cache.typographyReceiptId!,\n cache.typographyActionDigest!,\n );\n } else if (\n typography?.status === \"approved\" &&\n (typography.approvalReceiptId || typography.approvalActionDigest)\n ) {\n // An approved dependency exists but the cache omits it.\n return missing(book.id);\n }\n const sourceDigest = await brandJsonDigest({\n paletteId: cache.paletteId,\n paletteReceiptId: cache.paletteReceiptId,\n paletteActionDigest: cache.paletteActionDigest,\n typographyReceiptId: cache.typographyReceiptId ?? null,\n typographyActionDigest: cache.typographyActionDigest ?? null,\n });\n if (sourceDigest !== cache.sourceDigest) return missing(book.id);\n return cache;\n}\n\n/** Serve approved cached CSS/JSON, optionally public. ETags are derived from\n * immutable dependency provenance, never wall-clock timestamps. */\nexport async function handleTokens(\n db: Parameters<typeof loadBook>[0],\n req: Request,\n bookId: string,\n which: \"tokens.css\" | \"tokens.json\",\n actor: BrandActor | null,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const book = actor === null\n ? await loadBook(db, bookId)\n : await loadMemberBook(db, bookId, actor.id);\n const cache = await approvedCache(db, book);\n const light = cache.light as BrandTokens;\n const dark = cache.dark as BrandTokens;\n if (which === \"tokens.json\") return json({ light, dark });\n const etag = `\"brand-tokens-${book.activationRevision}-${cache.sourceDigest.slice(7)}\"`;\n if (\n req.headers.get(\"if-none-match\")\n ?.split(\",\")\n .map((value) => value.trim())\n .includes(etag)\n ) return new Response(null, { status: 304, headers: { etag } });\n return new Response(renderTokensCss(light, { dark }), {\n status: 200,\n headers: {\n \"content-type\": \"text/css; charset=utf-8\",\n \"cache-control\": \"public, max-age=0, must-revalidate\",\n etag,\n },\n });\n}\n","import { BrandInputError, BrandNotFoundError } from \"../errors\";\nimport type { BrandAsset, BrandBook } from \"../types\";\nimport { linkedAsset } from \"./asset-query\";\nimport {\n json,\n loadMemberBook,\n type BrandRouteCtx,\n} from \"./http\";\n\n/** Same aggregate 4.5 MiB inline-media lane used by Brand and Discussion. */\nexport const MAX_DISCUSSION_ASSET_BYTES = 4_718_592;\nconst SIGN_TTL_SECONDS = 30;\nconst TYPES = new Set([\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/pdf\",\n]);\n\nconst bare = (value: string | null): string =>\n (value?.split(\";\", 1)[0] ?? \"\").trim().toLowerCase();\n\nconst starts = (bytes: Uint8Array, expected: readonly number[]): boolean =>\n expected.every((value, index) => bytes[index] === value);\n\nfunction magicMatches(contentType: string, bytes: Uint8Array): boolean {\n if (contentType === \"image/png\") {\n return starts(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n }\n if (contentType === \"image/jpeg\") {\n return starts(bytes, [0xff, 0xd8, 0xff]);\n }\n const prefix = new TextDecoder().decode(bytes.subarray(0, 16));\n if (contentType === \"image/gif\") {\n return prefix.startsWith(\"GIF87a\") || prefix.startsWith(\"GIF89a\");\n }\n if (contentType === \"image/webp\") {\n return prefix.startsWith(\"RIFF\") && prefix.slice(8, 12) === \"WEBP\";\n }\n return contentType === \"application/pdf\" && prefix.startsWith(\"%PDF-\");\n}\n\nasync function boundedBytes(\n response: Response,\n max: number,\n): Promise<Uint8Array | null> {\n const length = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(length) && length > max) return null;\n if (!response.body) return new Uint8Array();\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const next = await reader.read();\n if (next.done) break;\n total += next.value.byteLength;\n if (total > max) {\n await reader.cancel();\n return null;\n }\n chunks.push(next.value);\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return out;\n}\n\nasync function digest(bytes: Uint8Array): Promise<string> {\n const value = await crypto.subtle.digest(\"SHA-256\", bytes.slice().buffer);\n return `sha256:${[...new Uint8Array(value)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n\nfunction exactAsset(\n beforeBook: BrandBook,\n before: BrandAsset,\n afterBook: BrandBook,\n after: BrandAsset,\n): boolean {\n return afterBook.id === beforeBook.id &&\n after.id === before.id &&\n after.bookId === before.bookId &&\n after.status === \"live\" &&\n after.path === before.path &&\n after.storageObjectId === before.storageObjectId &&\n after.contentDigest === before.contentDigest &&\n after.contentType === before.contentType &&\n after.size === before.size;\n}\n\nfunction safeSignedUrl(value: string): URL | null {\n try {\n const url = new URL(value);\n return value.length <= 4_096 &&\n url.protocol === \"https:\" &&\n !url.username &&\n !url.password\n ? url\n : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read one exact private Brand asset through a product-owned signed fetch.\n * The URL is derived from the linked row, used once, and never returned.\n */\nexport async function handleBrandDiscussionAsset(\n ctx: BrandRouteCtx,\n req: Request,\n target: { bookId: string; resourceId: string },\n): Promise<Response> {\n const beforeBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);\n const before = await linkedAsset(ctx, beforeBook, target.resourceId);\n const contentType = bare(before.contentType);\n if (!TYPES.has(contentType)) {\n return json({ error: \"asset content type is not viewable\" }, 415);\n }\n if (before.size < 1 || before.size > MAX_DISCUSSION_ASSET_BYTES) {\n return json({ error: \"asset exceeds the discussion media limit\" }, 413);\n }\n const signed = safeSignedUrl(\n await ctx.db.storage.sign(before.path, SIGN_TTL_SECONDS),\n );\n if (!signed) throw new BrandInputError(\"private asset signing failed\");\n // Through a local: a property call would hand `ctx` to fetch as its receiver.\n const fetchPrivateAsset = ctx.fetchPrivateAsset;\n const response = await fetchPrivateAsset(signed, {\n headers: { accept: contentType },\n redirect: \"manual\",\n signal: req.signal,\n });\n if (!response.ok || response.type === \"opaqueredirect\") {\n throw new BrandNotFoundError(`asset ${before.id}`);\n }\n const served = bare(response.headers.get(\"content-type\"));\n if (\n served === \"image/svg+xml\" ||\n (served && served !== \"application/octet-stream\" && served !== contentType)\n ) {\n return json({ error: \"asset content type is inconsistent\" }, 415);\n }\n const bytes = await boundedBytes(response, MAX_DISCUSSION_ASSET_BYTES);\n if (\n !bytes ||\n bytes.byteLength !== before.size ||\n !magicMatches(contentType, bytes) ||\n await digest(bytes) !== before.contentDigest\n ) {\n return json({ error: \"asset bytes failed validation\" }, 422);\n }\n const afterBook = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id);\n const after = await linkedAsset(ctx, afterBook, target.resourceId);\n if (!exactAsset(beforeBook, before, afterBook, after)) {\n return json({ error: \"asset changed during inspection\" }, 409);\n }\n return json({\n asset: {\n reference: { kind: \"brand:asset\", id: `${before.bookId}/${before.id}` },\n contentType,\n byteLength: bytes.byteLength,\n data: base64(bytes),\n taint: \"untrusted_project_material\",\n },\n }, 200, {\n \"cache-control\": \"private, no-store\",\n \"x-content-type-options\": \"nosniff\",\n });\n}\n\nfunction base64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let index = 0; index < bytes.length; index += 0x2000) {\n binary += String.fromCharCode(...bytes.subarray(index, index + 0x2000));\n }\n return btoa(binary);\n}\n","import { BRAND_NS } from \"../constants\";\nimport {\n brandDiscussionReferenceHref,\n brandDiscussionReferenceId,\n parseBrandDiscussionReference,\n type BrandDiscussionReference,\n type BrandDiscussionReferenceKind,\n type BrandDiscussionSwatch,\n type BrandDiscussionReferenceTarget,\n} from \"../discussion-reference\";\nimport type {\n BrandApprovalReceipt,\n BrandAsset,\n BrandBook,\n BrandPalette,\n BrandProposal,\n} from \"../types\";\nimport { assertSwatches } from \"../validate\";\nimport { handleBrandDiscussionAsset } from \"./discussion-asset\";\nimport { isMember, json, loadMemberBook, methodNotAllowed, type BrandRouteCtx } from \"./http\";\n\ntype Child = BrandAsset | BrandPalette | BrandProposal | BrandApprovalReceipt;\n\nconst capLimit = (raw: string | null): number => {\n const parsed = Number(raw ?? 20);\n return Number.isInteger(parsed) ? Math.max(1, Math.min(parsed, 20)) : 20;\n};\n\nconst targetFromQuery = (url: URL): BrandDiscussionReferenceTarget | null => {\n const kind = url.searchParams.get(\"kind\");\n const id = url.searchParams.get(\"id\");\n if (!kind && !id) return null;\n if (!kind || !id) return null;\n const value = new URL(\"https://brand.invalid\");\n value.searchParams.set(\"odla-ref\", `${kind}/${id}`);\n return parseBrandDiscussionReference(value);\n};\n\nconst childNamespace = (\n kind: BrandDiscussionReferenceKind,\n): string | null => ({\n \"brand:asset\": BRAND_NS.asset,\n \"brand:palette\": BRAND_NS.palette,\n \"brand:proposal\": BRAND_NS.proposal,\n \"brand:receipt\": BRAND_NS.approvalReceipt,\n} as Partial<Record<BrandDiscussionReferenceKind, string>>)[kind] ?? null;\n\nconst childTarget = (\n kind: Exclude<BrandDiscussionReferenceKind, \"brand:book\">,\n row: Child,\n): BrandDiscussionReferenceTarget => ({\n kind,\n bookId: row.bookId,\n resourceId: row.id,\n});\n\nconst projection = (\n req: Request,\n ctx: BrandRouteCtx,\n book: BrandBook,\n target: BrandDiscussionReferenceTarget,\n row: BrandBook | Child,\n): BrandDiscussionReference => {\n let label = book.name;\n let hint = `${book.status} brand book`;\n let summary = `${book.name} brand book`;\n let status: string = book.status;\n let destination = \"Brand Studio · Brand book\";\n let swatches: BrandDiscussionSwatch[] | undefined;\n if (target.kind === \"brand:asset\") {\n const asset = row as BrandAsset;\n label = asset.title?.trim() || `${asset.kind} asset`;\n hint = `${book.name} · ${asset.status}`;\n summary = `${asset.kind} source asset in ${book.name}`;\n status = asset.status;\n destination = \"Brand Studio · Conversation\";\n } else if (target.kind === \"brand:palette\") {\n const palette = row as BrandPalette;\n swatches = assertSwatches(palette.swatches).map((swatch) => ({\n role: swatch.role,\n hex: swatch.hex,\n ...(swatch.name ? { name: swatch.name } : {}),\n }));\n label = palette.name;\n hint = `${book.name} · ${palette.status} palette`;\n summary = `${palette.swatches.length}-color palette in ${book.name}`;\n status = palette.status;\n destination = \"Brand Studio · Review changes\";\n } else if (target.kind === \"brand:proposal\") {\n const proposal = row as BrandProposal;\n label = `${proposal.kind} proposal`;\n hint = `${book.name} · ${proposal.status}`;\n summary = proposal.rationale;\n status = proposal.status;\n destination = \"Brand Studio · Review changes\";\n } else if (target.kind === \"brand:receipt\") {\n const receipt = row as BrandApprovalReceipt;\n label = `${receipt.resolution} ${receipt.reviewedProposal.kind} change`;\n hint = `${book.name} · approval receipt`;\n summary = `${receipt.resolution} ${receipt.reviewedProposal.kind} decision`;\n status = receipt.resolution;\n destination = \"Brand Studio · Review changes\";\n }\n return {\n kind: target.kind,\n id: brandDiscussionReferenceId(target),\n label,\n hint,\n summary,\n status,\n destination,\n href: brandDiscussionReferenceHref(\n new URL(req.url),\n target,\n ctx.discussionBasePath,\n ),\n ...(swatches ? { swatches } : {}),\n };\n};\n\nasync function exact(\n ctx: BrandRouteCtx,\n req: Request,\n target: BrandDiscussionReferenceTarget,\n): Promise<BrandDiscussionReference[]> {\n const book = await loadMemberBook(ctx.db, target.bookId, ctx.actor.id)\n .catch(() => null);\n if (!book) return [];\n if (target.kind === \"brand:book\") {\n return [projection(req, ctx, book, target, book)];\n }\n const namespace = childNamespace(target.kind);\n if (!namespace || !target.resourceId) return [];\n const result = await ctx.db.query({\n [namespace]: {\n $: { where: { id: target.resourceId }, limit: 1 },\n },\n });\n const row = (result[namespace] ?? [])[0] as Child | undefined;\n if (\n !row ||\n row.bookId !== book.id ||\n (target.kind === \"brand:asset\" && (row as BrandAsset).status !== \"live\")\n ) return [];\n return [projection(req, ctx, book, target, row)];\n}\n\nconst matches = (\n item: BrandDiscussionReference,\n needle: string,\n): boolean => !needle ||\n `${item.label}\\n${item.hint}\\n${item.id}`.toLowerCase().includes(needle);\n\nasync function search(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n): Promise<BrandDiscussionReference[]> {\n const result = await ctx.db.query({\n [BRAND_NS.book]: { $: { order: { updatedAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.asset]: { $: { order: { createdAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.palette]: { $: { order: { updatedAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.proposal]: { $: { order: { createdAt: \"desc\" }, limit: 100 } },\n [BRAND_NS.approvalReceipt]: {\n $: { order: { createdAt: \"desc\" }, limit: 100 },\n },\n });\n const books = ((result[BRAND_NS.book] ?? []) as unknown as BrandBook[])\n .filter((book) => isMember(book, ctx.actor.id));\n const bookById = new Map(books.map((book) => [book.id, book]));\n const items = books.map((book) =>\n projection(req, ctx, book, { kind: \"brand:book\", bookId: book.id }, book)\n );\n const append = (\n kind: Exclude<BrandDiscussionReferenceKind, \"brand:book\">,\n rows: unknown[],\n ) => {\n for (const row of rows as Child[]) {\n const book = bookById.get(row.bookId);\n if (\n !book ||\n (kind === \"brand:asset\" && (row as BrandAsset).status !== \"live\")\n ) continue;\n items.push(projection(req, ctx, book, childTarget(kind, row), row));\n }\n };\n append(\"brand:asset\", result[BRAND_NS.asset] ?? []);\n append(\"brand:palette\", result[BRAND_NS.palette] ?? []);\n append(\"brand:proposal\", result[BRAND_NS.proposal] ?? []);\n append(\"brand:receipt\", result[BRAND_NS.approvalReceipt] ?? []);\n const needle = (url.searchParams.get(\"q\") ?? \"\").trim().toLowerCase()\n .slice(0, 120);\n return items.filter((item) => matches(item, needle))\n .slice(0, capLimit(url.searchParams.get(\"limit\")));\n}\n\n/**\n * Authenticated product-owned Brand reference search and exact resolution.\n * Membership and row existence are checked here, never inferred by Registry.\n */\nexport async function handleBrandDiscussionReferences(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n): Promise<Response> {\n if (req.method !== \"GET\") return methodNotAllowed();\n const inspect = url.searchParams.get(\"inspect\");\n const kind = url.searchParams.get(\"kind\");\n const id = url.searchParams.get(\"id\");\n if ((kind && !id) || (!kind && id)) return json({ error: \"kind and id must be paired\" }, 400);\n const target = targetFromQuery(url);\n if ((kind || id) && !target) return json({ items: [] });\n if (inspect === \"asset-content\") {\n const allowed = new Set([\"inspect\", \"kind\", \"id\"]);\n if (\n [...url.searchParams.keys()].some((key) => !allowed.has(key)) ||\n target?.kind !== \"brand:asset\" ||\n !target.resourceId\n ) return json({ error: \"exact brand asset kind and id required\" }, 400);\n return handleBrandDiscussionAsset(ctx, req, {\n bookId: target.bookId,\n resourceId: target.resourceId,\n });\n }\n if (inspect !== null && inspect !== \"1\") {\n return json({ error: \"invalid inspection mode\" }, 400);\n }\n return json({\n items: target ? await exact(ctx, req, target) : await search(ctx, req, url),\n });\n}\n","// The mountable route factory (crm's createCrmRoutes contract): the host\n// worker composes it —\n// const brandRoutes = createBrandRoutes({ db, authorize, … });\n// return (await brandRoutes(request)) ?? next(request);\n// — keeping full ownership of auth (`authorize`) and the admin db key.\nimport { handleAssetContent, handleAssetItem, handleAssetsRoot } from \"./assets\";\nimport { handleBookItem, handleBookMembers, handleBooksRoot } from \"./books\";\nimport { handleDesignDigest, handleDesignPreview } from \"./design-preview\";\nimport { errorResponse, json, type BrandRouteCtx, type BrandRouteOpts } from \"./http\";\nimport { handleProposalResolution } from \"./proposals\";\nimport { handleTokens } from \"./tokens\";\nimport { handleBrandDiscussionReferences } from \"./discussion-references\";\n\nexport type { BrandRouteCtx, BrandRouteOpts } from \"./http\";\nexport { proposalReviewSnapshot } from \"./proposal-input\";\n\ntype TokensFile = \"tokens.css\" | \"tokens.json\";\n\n/** `/books/:id/tokens.css|json` recognizer — the only publicTokens-eligible paths. */\nconst tokensFile = (seg: string[]): TokensFile | null =>\n seg.length === 3 && seg[0] === \"books\" && (seg[2] === \"tokens.css\" || seg[2] === \"tokens.json\")\n ? (seg[2] as TokensFile)\n : null;\n\nasync function route(\n ctx: BrandRouteCtx,\n req: Request,\n url: URL,\n seg: string[],\n): Promise<Response | null> {\n const [head, id, sub, subId, action] = seg;\n if (head === \"discussion-references\" && seg.length === 1)\n return handleBrandDiscussionReferences(ctx, req, url);\n if (head !== \"books\") return null;\n if (seg.length === 1) return handleBooksRoot(ctx, req);\n if (seg.length === 2) return handleBookItem(ctx, req, id!);\n if (seg.length === 3 && sub === \"members\") return handleBookMembers(ctx, req, id!);\n if (sub === \"assets\") {\n if (seg.length === 3) return handleAssetsRoot(ctx, req, id!);\n if (seg.length === 4) return handleAssetItem(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"content\")\n return handleAssetContent(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"preview\")\n return handleDesignPreview(ctx, req, id!, subId!);\n if (seg.length === 5 && action === \"design\")\n return handleDesignDigest(ctx, req, id!, subId!);\n return null;\n }\n if (sub === \"proposals\" && seg.length === 5 && action === \"resolve\")\n return handleProposalResolution(ctx, req, id!, subId!);\n const file = tokensFile(seg);\n if (file) return handleTokens(ctx.db, req, id!, file, ctx.actor);\n return null;\n}\n\n/**\n * Build the brand fetch handler. Returns `null` for requests outside\n * `basePath` (default `/api/brand`) so the host worker falls through to its\n * own routes; inside it, every route requires `authorize` to resolve an\n * actor (401 otherwise) EXCEPT the two tokens routes when `publicTokens` is\n * true — compiled tokens are the one intentionally publishable surface.\n * Domain errors map to 400/404 JSON; anything unexpected is an opaque 500.\n */\nexport function createBrandRoutes(options: BrandRouteOpts): (req: Request) => Promise<Response | null> {\n const basePath = options.basePath ?? \"/api/brand\";\n const publicTokens = options.publicTokens === true;\n const base = {\n db: options.db,\n appId: options.appId,\n authorizeCapability: options.authorizeCapability,\n consumeHumanExact: options.consumeHumanExact,\n verifySourceAssetSnapshot: options.verifySourceAssetSnapshot,\n now: options.now ?? Date.now,\n newId: options.newId ?? (() => crypto.randomUUID()),\n maxUploadBytes: options.maxUploadBytes ?? 8 * 1024 * 1024,\n discussionBasePath: options.discussionBasePath ?? \"/\",\n // Bound: this is stored on the context and invoked from route handlers,\n // where a property call would set the receiver to that context and\n // Cloudflare's fetch refuses a foreign receiver (\"Illegal invocation\").\n fetchPrivateAsset: options.fetchPrivateAsset ??\n globalThis.fetch.bind(globalThis),\n previewFrameAncestors: options.previewFrameAncestors ?? [\"'self'\"],\n };\n return async (req: Request): Promise<Response | null> => {\n const url = new URL(req.url);\n if (url.pathname !== basePath && !url.pathname.startsWith(`${basePath}/`)) return null;\n const seg = url.pathname.slice(basePath.length).split(\"/\").filter(Boolean);\n try {\n const file = tokensFile(seg);\n if (publicTokens && file) return await handleTokens(base.db, req, seg[1]!, file, null);\n const actor = await (\n seg[0] === \"discussion-references\"\n ? options.authorizeDiscussionReferences ?? options.authorize\n : options.authorize\n )(req);\n if (!actor) return json({ error: \"unauthorized\" }, 401);\n return (await route({ ...base, actor }, req, url, seg)) ??\n json({ error: \"not found\" }, 404);\n } catch (error) {\n return errorResponse(error);\n }\n };\n}\n","import { BRAND_NS } from \"./constants\";\nimport type { BrandAsset, BrandBook, BrandDb } from \"./types\";\n\nconst MAX_MESSAGE_ASSETS = 12;\n\nfunction candidateAssetIds(row: Record<string, unknown>): string[] {\n const standard = Array.isArray(row.attachments)\n ? row.attachments.flatMap((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return [];\n const id = (value as Record<string, unknown>).id;\n return typeof id === \"string\" && id.length > 0 && id.length <= 200\n ? [id]\n : [];\n })\n : [];\n // Compatibility for rows written before standard Chat attachments were\n // included in the initial message transaction.\n const legacy = Array.isArray(row.assetIds)\n ? row.assetIds.filter((value): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= 200)\n : [];\n return [...new Set([...standard, ...legacy])].slice(0, MAX_MESSAGE_ASSETS);\n}\n\n/** Reload message attachment ids against the exact live linked Brand book. */\nexport async function attachedBrandAssetIds(\n db: BrandDb,\n book: BrandBook,\n row: Record<string, unknown>,\n): Promise<string[]> {\n const candidates = candidateAssetIds(row);\n const assets = await Promise.all(candidates.map(async (id) => {\n const result = await db.query({\n [BRAND_NS.asset]: {\n $: { where: { id, bookId: book.id, status: \"live\" }, limit: 2 },\n book: { $: { limit: 2 } },\n },\n });\n const rows = result[BRAND_NS.asset] ?? [];\n if (rows.length !== 1) return null;\n const asset = rows[0] as BrandAsset & { book?: Array<{ id: string }> };\n return asset.id === id &&\n asset.bookId === book.id &&\n asset.status === \"live\" &&\n asset.deletedAt === undefined &&\n Array.isArray(asset.book) &&\n asset.book.length === 1 &&\n asset.book[0]?.id === book.id\n ? id\n : null;\n }));\n return assets.filter((id): id is string => id !== null);\n}\n","// Commit-trigger config brand installs into odla-db (POST to\n// `/app/:id/admin/triggers`), mirroring @odla-ai/chat's botTrigger: the\n// @odla/server commit hook fires on matching human-authored chat-message\n// writes and dispatches to the host's agent worker with `skill: \"brand\"`.\n// Two deployment modes, both this one builder:\n// - global mention-gated: one bot, `mention: \"@brand\"`, no `channels`;\n// - per-book channel-scoped: `channels: [book.channelId]`, no mention.\n\n/** The odla-db namespace chat messages live in.\n * PROVENANCE: @odla-ai/chat `CHAT_NS.message` (packages/chat/src/constants.ts)\n * — duplicated as a local const because this package is zero-dep and the wire\n * value is a stable contract, not an implementation detail. */\nexport const CHAT_MESSAGE_NS = \"chat_message\";\n\n/** Matches @odla/server's `Trigger` (the exact JSON POSTed to\n * `/app/:id/admin/triggers`) — the same wire shape as chat's `ChatTrigger`. */\nexport interface BrandTrigger {\n id: string;\n watch: { ns: string; on: \"create\" | \"update\" };\n when?: string;\n runAs: { agentId: string; persona: string };\n skill: string;\n maxDepth?: number;\n channels?: string[];\n validate?: string;\n}\n\n/** Options for {@link brandBotTrigger}. */\nexport interface BrandBotTriggerOpts {\n /** Trigger id (unique per app). */\n id: string;\n /** The bot's agent id — must be in each target book's `memberIds` roster. */\n agentId: string;\n /** Persona name the dispatching worker runs. */\n persona: string;\n /** Fire only on messages mentioning this handle, e.g. \"@brand\". */\n mention?: string;\n /** Extra CEL over the new message row, ANDed with the built-in guards. */\n when?: string;\n /** Restrict to specific channel ids (the per-book mode). */\n channels?: string[];\n /** Watched write kind (default \"create\"). */\n on?: \"create\" | \"update\";\n}\n\n/** Escape a value for embedding inside a CEL double-quoted string literal —\n * copied verbatim from @odla-ai/chat (packages/chat/src/triggers.ts):\n * `mention` is matched as literal text, so a stray quote or backslash must\n * not break out of the literal into CEL syntax. */\nconst celString = (value: string): string => value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n\n/**\n * Build a trigger that runs the brand agent on human chat messages\n * (optionally @-mentions, optionally channel-scoped): chat's `botTrigger`\n * shape with `skill: \"brand\"` and `maxDepth: 1` so a bot reply can never\n * re-trigger a bot.\n */\nexport function brandBotTrigger(opts: BrandBotTriggerOpts): BrandTrigger {\n const clauses = ['data.authorKind == \"human\"'];\n if (opts.mention) clauses.push(`data.body.contains(\"${celString(opts.mention)}\")`);\n // `when` is documented as caller-authored CEL, so it is intentionally not escaped.\n if (opts.when) clauses.push(`(${opts.when})`);\n return {\n id: opts.id,\n watch: { ns: CHAT_MESSAGE_NS, on: opts.on ?? \"create\" },\n when: clauses.join(\" && \"),\n runAs: { agentId: opts.agentId, persona: opts.persona },\n skill: \"brand\",\n maxDepth: 1,\n ...(opts.channels ? { channels: opts.channels } : {}),\n };\n}\n","// Host dispatch for one Brand chat turn. The service DB resolves the book;\n// tools receive a separate rules-scoped DB bound to the exact runAs agent.\nimport type { ImageBlock, OracleContentBlock } from \"@odla-ai/ai\";\nimport { BRAND_NS } from \"./constants\";\nimport {\n BrandConflictError,\n BrandForbiddenError,\n BrandNotFoundError,\n} from \"./errors\";\nimport { attachedBrandAssetIds } from \"./dispatch-assets\";\nimport { createBrandPersona, supportsBrandVision } from \"./skill/persona\";\nimport type { BrandSkillSelf } from \"./skill/skill\";\nimport { CHAT_MESSAGE_NS } from \"./triggers\";\nimport type { BrandBook, BrandDb } from \"./types\";\nimport type { BrandDispatchBody, BrandDispatchDeps } from \"./dispatch-types\";\nimport type { BrandPrincipalProjection } from \"./skill/agent-types\";\n\nexport type { BrandDispatchBody, BrandDispatchDeps } from \"./dispatch-types\";\nexport { attachedBrandAssetIds } from \"./dispatch-assets\";\n\n/** Strict-enough structural parse for the signed host dispatch envelope. */\nexport function parseBrandDispatch(raw: unknown): BrandDispatchBody | null {\n if (!raw || typeof raw !== \"object\") return null;\n const body = raw as Record<string, unknown>;\n const trigger = body.trigger as {\n id?: unknown;\n skill?: unknown;\n maxDepth?: unknown;\n runAs?: { agentId?: unknown; persona?: unknown };\n } | undefined;\n const event = body.event as {\n ns?: unknown;\n id?: unknown;\n row?: unknown;\n } | undefined;\n if (\n body.v !== 2 ||\n typeof body.appId !== \"string\" ||\n !body.appId ||\n typeof body.appIncarnation !== \"string\" ||\n !/^[0-9a-f]{32}$/.test(body.appIncarnation) ||\n typeof body.jobId !== \"string\" ||\n !body.jobId ||\n !trigger ||\n typeof trigger.runAs?.agentId !== \"string\" ||\n !trigger.runAs.agentId ||\n typeof trigger.runAs.persona !== \"string\" ||\n !event ||\n typeof event.id !== \"string\" ||\n !event.row ||\n typeof event.row !== \"object\" ||\n Array.isArray(event.row)\n ) return null;\n return {\n v: 2,\n appId: body.appId,\n appIncarnation: body.appIncarnation,\n jobId: body.jobId,\n trigger: {\n id: typeof trigger.id === \"string\" ? trigger.id : \"\",\n skill: typeof trigger.skill === \"string\" ? trigger.skill : \"\",\n runAs: {\n agentId: trigger.runAs.agentId,\n persona: trigger.runAs.persona,\n },\n ...(typeof trigger.maxDepth === \"number\"\n ? { maxDepth: trigger.maxDepth }\n : {}),\n },\n event: {\n ns: typeof event.ns === \"string\" ? event.ns : CHAT_MESSAGE_NS,\n id: event.id,\n row: event.row as Record<string, unknown>,\n },\n };\n}\n\n/** Channel ids are unique by schema, but ambiguity still fails closed if a\n * legacy/corrupt store returns more than one row. */\nexport async function bookForChannel(\n db: BrandDb,\n channelId: string,\n): Promise<BrandBook | null> {\n if (!channelId) return null;\n const result = await db.query({\n [BRAND_NS.book]: { $: { where: { channelId } } },\n });\n const books = (result[BRAND_NS.book] ?? []) as BrandBook[];\n if (books.length > 1)\n throw new BrandConflictError(`multiple brand books claim channel ${channelId}`);\n return books[0] ?? null;\n}\n\n/** Assemble the conversational request. Attachments remain supported as a\n * pure helper, but secure dispatch does not pass signed/private URLs here. */\nexport function brandInputFor(\n body: BrandDispatchBody,\n attachments?: ImageBlock[],\n author?: BrandPrincipalProjection,\n attachedAssetIds: readonly string[] = [],\n): string | OracleContentBlock[] {\n const row = body.event.row;\n const actor = author\n ? `${author.displayName} (${author.kind}` +\n `${author.managerDisplayName\n ? `, managed by ${author.managerDisplayName}`\n : \"\"})`\n : row.authorKind === \"bot\"\n ? \"a managed agent\"\n : \"a participant\";\n const prompt =\n `A new message arrived in this brand book's channel from ` +\n `${actor}: ` +\n `\"${String(row.body ?? \"\")}\". Ground yourself first (read_brand_book, ` +\n \"list_assets), then move the work forward. Study real material, justify \" +\n \"colors, and park exact proposals. A human approves in the Brand surface; \" +\n \"acceptance applies the reviewed facet and recompiles dependent tokens. \" +\n (attachedAssetIds.length > 0\n ? `This message atomically attached Brand asset id${attachedAssetIds.length === 1 ? \"\" : \"s\"} ` +\n `${attachedAssetIds.join(\", \")}; use view_asset on those exact ids before drawing conclusions. `\n : \"\") +\n \"Keep any chat reply concise.\";\n return attachments?.length\n ? [...attachments, { type: \"text\", text: prompt }]\n : prompt;\n}\n\n/** Preflight exact app/skill/channel/roster/live brand.read before the model\n * is invoked. Every tool revalidates its own read/edit capability as well. */\nexport async function dispatchBrandTurn(\n deps: BrandDispatchDeps,\n body: BrandDispatchBody,\n): Promise<{ finalText: string; durableOutcome: boolean }> {\n if (\n body.appId !== deps.appId ||\n body.trigger.skill !== \"brand\" ||\n body.event.ns !== CHAT_MESSAGE_NS\n ) throw new BrandForbiddenError(\"foreign or non-brand dispatch\");\n const channelId = String(body.event.row.channelId ?? \"\");\n const book = await bookForChannel(deps.db, channelId);\n if (!book)\n throw new BrandNotFoundError(\n `brand book for channel ${channelId || \"(missing channelId)\"}`,\n );\n const agentId = body.trigger.runAs.agentId;\n if (!book.memberIds.includes(agentId))\n throw new BrandNotFoundError(`brand book for channel ${channelId}`);\n const read = await deps.authorizeCapability({\n agentId,\n bookId: book.id,\n capability: \"brand.read\",\n });\n if (!read || read.capability !== \"brand.read\" || !read.authorityRef)\n throw new BrandForbiddenError(\"agent lacks live brand.read\");\n const authorId =\n typeof body.event.row.authorId === \"string\"\n ? body.event.row.authorId\n : \"\";\n const authors = authorId\n ? await deps.resolvePrincipals({\n requesterAgentId: agentId,\n bookId: book.id,\n principalIds: [authorId],\n })\n : [];\n const author = authors.find((candidate) => candidate.id === authorId);\n const attachedAssetIds = await attachedBrandAssetIds(\n deps.db,\n book,\n body.event.row,\n );\n const runtime = await deps.agentRuntimeFor({\n appId: body.appId,\n agentId,\n bookId: book.id,\n triggerId: body.trigger.id,\n eventId: body.event.id,\n jobId: body.jobId,\n });\n if (\n !runtime.credentialRef ||\n !runtime.jobId ||\n runtime.jobId !== body.jobId\n )\n throw new BrandForbiddenError(\"agent data credential is not bound\");\n let durableOutcome = false;\n const bridge = {\n ...runtime.bridge,\n createProposal: async (\n input: Parameters<typeof runtime.bridge.createProposal>[0],\n ) => {\n const proposal = await runtime.bridge.createProposal(input);\n durableOutcome = true;\n return proposal;\n },\n recordAssetAnalysis: async (\n input: Parameters<typeof runtime.bridge.recordAssetAnalysis>[0],\n ) => {\n const asset = await runtime.bridge.recordAssetAnalysis(input);\n durableOutcome = true;\n return asset;\n },\n };\n\n const visionInToolResults = supportsBrandVision(\n deps.catalog?.[deps.model],\n );\n const self: BrandSkillSelf = {\n selfId: agentId,\n kind: \"bot\",\n displayName: body.trigger.runAs.persona,\n };\n const persona = createBrandPersona({\n model: deps.model,\n brand: {\n db: runtime.db,\n bookId: book.id,\n self,\n agentDbBinding: {\n principalId: agentId,\n credentialRef: runtime.credentialRef,\n },\n agentJobId: runtime.jobId,\n agentBridge: bridge,\n authorizeCapability: deps.authorizeCapability,\n resolvePrincipals: deps.resolvePrincipals,\n visionInToolResults,\n ...(deps.newId ? { newId: deps.newId } : {}),\n },\n skills: deps.chatSkillFor\n ? [deps.chatSkillFor(channelId, self)]\n : [],\n });\n const run = await deps.runAgent(deps.inference, persona, {\n // Models without tool-result vision receive no raw/signed fallback URL.\n input: brandInputFor(body, undefined, author, attachedAssetIds),\n });\n return { finalText: run.finalText, durableOutcome };\n}\n","// The integration descriptor: documentation-as-data for the brand capability,\n// following the crm/chat pattern — what installing @odla-ai/brand into an app\n// means (schema, deny-all rules, per-bot triggers, worker mount), described\n// but not performed. The base shapes are inlined so the zero-dependency\n// package does not depend on the CLI; the CLI consumes descriptors\n// structurally from odla.config.mjs.\nimport { BRAND_SCHEMA, type SerializedSchema } from \"./schema\";\nimport { brandRules, type BrandRules } from \"./rules\";\nimport type { BrandTrigger } from \"./triggers\";\nimport {\n BRAND_AGENT_PROFILE,\n type BrandAgentProfile,\n} from \"./agent-profile\";\n\n/** One owner-facing setting the integration exposes (crm's shape). */\nexport interface IntegrationSetting {\n key: string;\n description: string;\n public: boolean;\n pattern?: string;\n perEnv: boolean;\n source: string;\n}\n\n/** One vault secret the integration needs (brand core needs none). */\nexport interface IntegrationSecret {\n key: string;\n description: string;\n pattern?: string;\n vault: boolean;\n}\n\n/** Human / CLI / doctor provisioning steps, documentation-as-data. */\nexport interface IntegrationProvision {\n human: string[];\n cli: string[];\n doctor: string[];\n}\n\n/** Unauthenticated route check run by `odla-ai smoke`. */\nexport interface BrandIntegrationProbe {\n path: string;\n expectedStatus: number;\n}\n\n/** The brand descriptor shape: the shared base plus the schema + rules\n * provisioning installs and the (app-supplied) bot triggers. */\nexport interface BrandIntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n settings: IntegrationSetting[];\n secrets: IntegrationSecret[];\n /** The schema to POST at /app/:id/schema. */\n schema: SerializedSchema;\n /** The default-deny rules to install at /app/:id/admin/rules (merged with existing). */\n rules: BrandRules;\n /** Commit triggers to register at /app/:id/admin/triggers (per-bot; app-supplied). */\n triggers: BrandTrigger[];\n /** Least-privilege agent capabilities and semantic-operation boundary. */\n agentProfile: BrandAgentProfile;\n probes?: BrandIntegrationProbe[];\n provision: IntegrationProvision;\n}\n\n/**\n * The static documentation descriptor for @odla-ai/brand. Data only: it\n * describes what installing the brand capability means — push\n * {@link BRAND_SCHEMA}, install the default-deny `brandRules()`, register\n * `brandBotTrigger`s (app-supplied, in either the global mention-gated or the\n * per-book channel-scoped mode), mount `createBrandRoutes` in the app worker\n * — and performs none of it. Use {@link createBrandIntegration} in\n * `odla.config.mjs` to add the live route probe the CLI can execute.\n */\nexport const brandIntegration: BrandIntegrationDescriptor = {\n id: \"brand\",\n title: \"Brand books (assets, palettes, proposals, design tokens)\",\n npm: \"@odla-ai/brand\",\n settings: [\n {\n key: \"basePath\",\n description: 'Route mount point the app worker serves brand under. Default \"/api/brand\".',\n public: true,\n perEnv: false,\n source: \"createBrandRoutes({ basePath }) in the app worker\",\n },\n {\n key: \"publicTokens\",\n description:\n \"Serve GET /books/:id/tokens.css and tokens.json without authorization (compiled tokens \" +\n \"only — books and assets always authorize). Default false.\",\n public: true,\n perEnv: false,\n source: \"createBrandRoutes({ publicTokens }) in the app worker\",\n },\n ],\n secrets: [],\n schema: BRAND_SCHEMA,\n rules: brandRules(),\n triggers: [],\n agentProfile: BRAND_AGENT_PROFILE,\n provision: {\n human: [\n \"Configure direct Clerk human approval through authorizeCapability + consumeHumanExact; delegated, machine, and agent principals must not resolve proposals.\",\n \"Choose the trigger mode: one global mention-gated bot (brandBotTrigger({ mention: \\\"@brand\\\" }), no channels) or per-book channel-scoped bots (channels: [book.channelId], no mention).\",\n \"Pick a model where supportsBrandVision(catalog[model]) is true for in-conversation asset viewing; secure dispatch never falls back to signed or persistent asset URLs.\",\n \"Decide whether compiled tokens are public (publicTokens serves tokens.css/tokens.json unauthenticated).\",\n ],\n cli: [\n \"POST BRAND_SCHEMA to /app/:id/schema.\",\n \"Install brandRules() at /app/:id/admin/rules (merged with the app's existing rules).\",\n \"Register a brandBotTrigger(...) per bot at /app/:id/admin/triggers — global mention-gated, or channel-scoped per book.\",\n \"Seed the bot's agent id into each brand_book.memberIds roster (audienceFanoutOps covers existing child rows).\",\n \"Issue the bot brand.read + brand.edit and expose only BRAND_AGENT_PROFILE semantic operations; deny raw brand_* writes and raw file operations.\",\n \"Provision private file signing and verifySourceAssetSnapshot; never expose an admin credential or persistent asset URL to the agent.\",\n ],\n doctor: [\n \"All six brand_* namespaces have rules installed; raw browser/agent writes are denied and child reads use current linked-book membership.\",\n \"The agent runtime matches BRAND_AGENT_PROFILE: brand.read/edit only, semantic operations only, no raw brand_* or file access.\",\n \"Proposal decisions consume a direct-human exact brand.approve authority use and persist one guarded brand_approval_receipt.\",\n \"Private source assets are signed briefly and verifySourceAssetSnapshot revalidates path, ETag, size, content type, and digest before approval.\",\n \"brand_book.id/slug, brand_section.key, and the other mirrored id attrs are unique.\",\n \"Each registered trigger's agent id is present in its target books' memberIds rosters.\",\n \"Books with channelId set point at real chat channels when @odla-ai/chat is installed.\",\n ],\n },\n};\n\n/** Options for {@link createBrandIntegration}. */\nexport interface CreateBrandIntegrationOptions {\n /** Worker mount path; defaults to `/api/brand`. */\n basePath?: string;\n /** Document (and probe-plan for) unauthenticated tokens routes. */\n publicTokens?: boolean;\n /** The global bot's mention handle — folded into the CLI trigger step. */\n mention?: string;\n}\n\n/**\n * Build the project-specific, CLI-consumable brand integration descriptor:\n * {@link brandIntegration} plus a live smoke probe (an anonymous GET of\n * `<basePath>/books` must answer 401 — routes mounted, authorize enforced,\n * exactly crm's probe idiom) and, when `mention`/`publicTokens` are given,\n * concrete CLI steps carrying the app's actual values. Mounting\n * `createBrandRoutes` remains app-owned source work.\n */\nexport function createBrandIntegration(\n options: CreateBrandIntegrationOptions = {},\n): BrandIntegrationDescriptor {\n const basePath = options.basePath ?? \"/api/brand\";\n if (!/^\\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(basePath) || basePath.endsWith(\"/\")) {\n throw new Error(\"createBrandIntegration: basePath must be an absolute path without a trailing slash\");\n }\n const cli = [...brandIntegration.provision.cli];\n if (options.mention !== undefined)\n cli.push(`Gate the global bot on mentions: brandBotTrigger({ mention: ${JSON.stringify(options.mention)}, ... }).`);\n if (options.publicTokens === true)\n cli.push(`Mount createBrandRoutes({ publicTokens: true }) so ${basePath}/books/:id/tokens.css serves unauthenticated.`);\n return {\n ...brandIntegration,\n provision: { ...brandIntegration.provision, cli },\n probes: [{ path: `${basePath}/books`, expectedStatus: 401 }],\n };\n}\n"],"mappings":"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","names":["record","record","receipt","isRecord","HEX_ALPHA","a","value","toHex","a","missing","isRecord","from","end","a","a","HEX6","a","isRecord","digest","missing","a","record","record","ops","digest","receipt","record","sameStrings","guardFailure","receipt","record","receipt","receipt"]}