shipseal 0.4.0 → 0.4.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.
- package/README.md +1 -1
- package/dist/cli.js +20 -2
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":["formatCount","measureOpts","propsSchema","propsSchema","propsSchema","formatCount","formatCount","propsSchema","propsSchema","execFileAsync","API_ROOT","stripScope","repositoryUrl","normalizeGitUrl","textNode","takumiFromJsx","execFileAsync","execFileAsync","matchingBrace","basename","input","STORY_FORMATS"],"sources":["../src/core/errors.ts","../src/brand/schema.ts","../src/brand/load.ts","../src/formats.ts","../src/config/schema.ts","../src/config/load.ts","../src/copy/slots.ts","../src/copy/deterministic.ts","../src/bench/percent.ts","../src/fit/fit-text.ts","../src/templates/theme.ts","../src/takumi-jsx/jsx-runtime.ts","../src/templates/code-card.tsx","../src/templates/highlight.ts","../src/templates/bench.tsx","../src/templates/milestone.tsx","../src/templates/primitives/seal.ts","../src/templates/release-hero.tsx","../src/templates/release-highlights.tsx","../src/facts/schema.ts","../src/templates/story-page.tsx","../src/templates/registry.ts","../src/core/generate.ts","../src/facts/fact.ts","../src/facts/merge.ts","../src/sources/bench-file.ts","../src/sources/readme.ts","../src/sources/release-line.ts","../src/sources/changelog.ts","../src/sources/git.ts","../src/sources/github.ts","../src/sources/npm.ts","../src/sources/package-json.ts","../src/sources/collect.ts","../src/render/takumi.ts","../src/render/takumi-node.ts","../src/copy/number-guard.ts","../src/copy/llm.ts","../src/outputs/manifest.ts","../src/outputs/files.ts","../src/outputs/github-release.ts","../src/commands/shared.ts","../src/commands/bench.ts","../src/commands/doctor.ts","../src/brand/color.ts","../src/brand/css-vars.ts","../src/brand/dtcg.ts","../src/brand/tailwind.ts","../src/brand/detect-colors.ts","../src/brand/logo.ts","../src/brand/png.ts","../src/brand/detect.ts","../src/brand/detect-node.ts","../src/commands/init.ts","../src/commands/milestone.ts","../src/commands/release.ts","../src/core/story.ts","../src/outputs/downloads.ts","../src/studio/pack.ts","../src/commands/story.ts","../src/commands/preview.ts","../src/cli.ts"],"sourcesContent":["// Typed errors: what went wrong, why, how to fix\n// Spec: docs/PROJECT_PLAN.md §0.3\n\nexport class ShipsealError extends Error {\n readonly code: string;\n readonly fix: string;\n\n constructor(code: string, message: string, fix: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ShipsealError\";\n this.code = code;\n this.fix = fix;\n }\n}\n\nexport function formatError(error: ShipsealError): string {\n return `${error.message}\\nFix: ${error.fix}`;\n}\n","// brand.json zod schema\n// Spec: docs/PROJECT_PLAN.md §10.2\n\nimport { z } from \"zod\";\n\nexport const hexColorSchema = z\n .string()\n .regex(/^#([\\da-f]{6})$/i, \"Expected a 6-digit hex color like #0b0b0c\");\n\nexport const fontFaceSchema = z.object({\n family: z.string().min(1),\n weight: z.number().int().min(100).max(900),\n file: z.string().min(1).optional(),\n});\n\nexport const brandSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n name: z.string().min(1),\n tagline: z.string().optional(),\n url: z.string().optional(),\n logo: z\n .object({\n light: z.string().min(1),\n dark: z.string().min(1).optional(),\n })\n .optional(),\n colors: z.object({\n background: hexColorSchema,\n foreground: hexColorSchema,\n muted: hexColorSchema.optional(),\n primary: hexColorSchema.optional(),\n accent: hexColorSchema.optional(),\n }),\n fonts: z.object({\n heading: fontFaceSchema,\n body: fontFaceSchema,\n mono: fontFaceSchema,\n }),\n radius: z.number().nonnegative(),\n theme: z.enum([\"dark\", \"light\"]),\n style: z.enum([\"minimal\", \"editorial\", \"terminal\"]),\n tokens: z.string().nullable(),\n});\n\nexport type Brand = z.infer<typeof brandSchema>;\n\nexport const DEFAULT_BRAND_COLORS = {\n background: \"#0b0b0c\",\n foreground: \"#fafafa\",\n muted: \"#a1a1aa\",\n primary: \"#ff4d4d\",\n accent: \"#fbbf24\",\n} as const;\n\nexport const DEFAULT_BRAND_FONTS = {\n heading: { family: \"Geist\", weight: 700 },\n body: { family: \"Geist\", weight: 400 },\n mono: { family: \"Geist Mono\", weight: 400 },\n} as const;\n","// Load .shipseal/brand.json\n// Spec: docs/PROJECT_PLAN.md §10.1\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { brandSchema, type Brand } from \"./schema.js\";\n\nexport async function loadBrand(cwd: string): Promise<Brand> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n return brandSchema.parse(raw);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n throw new ShipsealError(\n \"brand.missing\",\n \"No .shipseal/brand.json found.\",\n \"Run shipseal init to detect brand colors and write brand.json.\",\n );\n }\n throw error;\n }\n}\n","// Single table of platform sizes\n// Spec: docs/PROJECT_PLAN.md §14.2\n\nexport const FORMAT_IDS = [\n \"og\",\n \"github-social\",\n \"x\",\n \"linkedin\",\n \"square\",\n \"portrait\",\n \"producthunt\",\n \"readme-banner\",\n] as const;\n\nexport type FormatId = (typeof FORMAT_IDS)[number];\n\nexport interface Format {\n id: FormatId;\n width: number;\n height: number;\n /** Minimum inset for critical text on landscape formats, in px. */\n safeZone: number;\n}\n\nconst LANDSCAPE_SAFE_ZONE = 64;\n\nexport const FORMATS: Record<FormatId, Format> = {\n og: { id: \"og\", width: 1200, height: 630, safeZone: LANDSCAPE_SAFE_ZONE },\n \"github-social\": {\n id: \"github-social\",\n width: 1280,\n height: 640,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n x: { id: \"x\", width: 1200, height: 675, safeZone: LANDSCAPE_SAFE_ZONE },\n linkedin: { id: \"linkedin\", width: 1200, height: 627, safeZone: LANDSCAPE_SAFE_ZONE },\n square: { id: \"square\", width: 1080, height: 1080, safeZone: LANDSCAPE_SAFE_ZONE },\n portrait: { id: \"portrait\", width: 1080, height: 1350, safeZone: LANDSCAPE_SAFE_ZONE },\n producthunt: {\n id: \"producthunt\",\n width: 1270,\n height: 760,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n \"readme-banner\": {\n id: \"readme-banner\",\n width: 1280,\n height: 400,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n};\n\nexport const V1_FORMAT_IDS = [\"og\", \"github-social\", \"x\", \"linkedin\"] as const satisfies readonly FormatId[];\n","// config.json zod schema\n// Spec: docs/PROJECT_PLAN.md §11\n\nimport { z } from \"zod\";\nimport { FORMAT_IDS } from \"../formats.js\";\n\nexport const configSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n outputDir: z.string().optional(),\n formats: z.array(z.enum(FORMAT_IDS)).optional(),\n release: z\n .object({\n templates: z.array(z.string()).optional(),\n maxHighlights: z.number().int().positive().optional(),\n changelogPath: z.string().optional(),\n snippet: z.string().nullable().optional(),\n announce: z.enum([\"major\", \"minor\", \"patch\"]).optional(),\n headline: z.string().nullable().optional(),\n subheadline: z.string().nullable().optional(),\n story: z.object({\n upgrade: z.string().max(4000).optional(),\n before: z.string().optional(),\n after: z.string().optional(),\n }).refine((value) => Boolean(value.before) === Boolean(value.after), {\n message: \"Supply both story.before and story.after screenshot paths, or neither.\",\n }).optional(),\n })\n .optional(),\n milestones: z\n .object({\n stars: z.array(z.number().int().positive()).optional(),\n downloads: z.array(z.number().int().positive()).optional(),\n contributors: z.array(z.number().int().positive()).optional(),\n })\n .optional(),\n bench: z\n .object({\n file: z.string().optional(),\n })\n .optional(),\n copy: z\n .object({\n llm: z.boolean().optional(),\n provider: z.string().nullable().optional(),\n model: z.string().nullable().optional(),\n maxRetries: z.number().int().nonnegative().optional(),\n })\n .optional(),\n output: z\n .object({\n imageFormat: z.enum([\"png\", \"webp\", \"jpeg\"]).optional(),\n })\n .optional(),\n attribution: z.boolean().optional(),\n});\n\nexport type Config = z.infer<typeof configSchema>;\n\nexport const DEFAULT_CONFIG: Config = {\n version: 1,\n outputDir: \".shipseal/output\",\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\"],\n release: {\n templates: [\"release-hero\", \"release-highlights\", \"code-card\"],\n maxHighlights: 4,\n changelogPath: \"CHANGELOG.md\",\n // Announce everything by default. The review proposed \"minor\", but a project whose release\n // script copies the rendered hero (this one does) breaks when a patch produces nothing.\n announce: \"patch\",\n snippet: null,\n },\n milestones: {\n // Starts at 10. A ladder beginning at 100 meant a new project saw no\n // milestone card for months, which is exactly when it is deciding whether this is\n // worth keeping. The first few stars are the ones worth celebrating.\n stars: [10, 50, 100, 250, 500, 1000, 2500, 5000, 10000],\n downloads: [1000, 10000, 100000, 1000000],\n contributors: [10, 25, 50, 100],\n },\n bench: {\n file: \".shipseal/bench.json\",\n },\n copy: {\n llm: false,\n provider: null,\n model: null,\n maxRetries: 2,\n },\n output: {\n imageFormat: \"png\",\n },\n attribution: true,\n};\n","// Load and merge config (flags > file > defaults)\n// Spec: docs/PROJECT_PLAN.md §11\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { DEFAULT_CONFIG, configSchema, type Config } from \"./schema.js\";\n\nexport async function loadConfig(cwd: string): Promise<Config> {\n const path = join(cwd, \".shipseal\", \"config.json\");\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = configSchema.parse(raw);\n return mergeConfig(DEFAULT_CONFIG, parsed);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return DEFAULT_CONFIG;\n }\n throw error;\n }\n}\n\nexport function mergeConfig(base: Config, overlay: Config): Config {\n return {\n ...base,\n ...overlay,\n release: { ...base.release, ...overlay.release },\n milestones: { ...base.milestones, ...overlay.milestones },\n bench: { ...base.bench, ...overlay.bench },\n copy: { ...base.copy, ...overlay.copy },\n output: { ...base.output, ...overlay.output },\n };\n}\n","// Copy slots filled by the copy layer\n// Spec: docs/PROJECT_PLAN.md §13.1\n\nexport const COPY_LIMITS = {\n headline: 48,\n subheadline: 90,\n highlight: 56,\n cta: 32,\n milestoneLine: 48,\n} as const;\n\nexport const MAX_HIGHLIGHTS = 4;\n\nexport interface Copy {\n headline: string;\n subheadline: string;\n highlights: string[];\n cta: string;\n milestoneLine?: string;\n codeLines?: CodeLine[];\n /** Title for the code card, when reusing the release headline would not make sense. */\n codeTitle?: string;\n}\n\nexport type CodeLine = Array<{ text: string; color: string }>;\n","// No-LLM copy rules (default path)\n// Spec: docs/PROJECT_PLAN.md §13.2\n\nimport type { Facts } from \"../facts/schema.js\";\nimport { MAX_HIGHLIGHTS, type Copy } from \"./slots.js\";\n\nexport function deterministicCopy(\n facts: Facts,\n maxHighlights = MAX_HIGHLIGHTS,\n // The card shows the brand wordmark beside the headline. Falling back to the raw project\n // fact put \"shipseal 0.0.8\" under \"Shipseal\" on the same card.\n displayName?: string,\n): Copy {\n const name = facts.project.name.value;\n const version = facts.release?.version.value;\n const features = (facts.release?.features ?? []).map((item) => item.value);\n const fixes = (facts.release?.fixes ?? []).map((item) => item.value);\n const breaking = (facts.release?.breaking ?? []).map((item) => item.value);\n\n // Breaking changes lead, then features. Fixes are deliberately excluded: every Changesets\n // \"Patch Changes\" entry maps to a fix, so including them put a maintainer's note on the hero.\n // v0.0.6 announced itself as \"Never put a truncated headline on a card\", which reads as a\n // strange instruction rather than a release, and nobody posts that. A release with only fixes\n // is better titled by its name and version.\n //\n // Prefer the first entry whose opening sentence actually fits. Taking the first sentence is\n // not enough on its own: a single long sentence still overflowed, and the v0.0.5 card shipped\n // with a headline truncated mid-phrase.\n const headlineSource = [...breaking, ...features]\n .map((line) => cleanLine(firstSentence(line)))\n .find((line) => line.length <= HEADLINE_MAX_CHARS);\n const title = displayName ?? name;\n const headline =\n facts.release?.headline?.value ??\n headlineSource ??\n (version === undefined ? title : `${title} ${version}`);\n\n const tagline = facts.release?.subheadline?.value ?? facts.project.tagline?.value;\n const subheadline =\n tagline !== undefined && tagline.length > 0\n ? cleanLine(tagline)\n : cleanLine(features[1] ?? fixes[1] ?? fixes[0] ?? `What's new in ${version ?? name}`);\n\n // One sentence per highlight, for the same reason the headline takes one: changelog entries\n // are prose paragraphs, so whole entries could only be truncated mid-word on a card.\n const highlights: string[] = [];\n const addHighlight = (line: string, prefix = \"\"): void => {\n if (highlights.length >= maxHighlights) {\n return;\n }\n highlights.push(`${prefix}${cleanLine(firstSentence(line))}`);\n };\n for (const line of breaking) {\n addHighlight(line, \"Breaking: \");\n }\n for (const line of features) {\n addHighlight(line);\n }\n for (const line of fixes) {\n addHighlight(line);\n }\n\n const copy: Copy = {\n headline,\n subheadline,\n highlights,\n cta: ctaFor(facts),\n };\n const snippet = facts.release?.codeSnippet?.value.code;\n if (snippet !== undefined && isInstallOnly(snippet)) {\n copy.codeTitle = \"Get started\";\n }\n return copy;\n}\n\n/**\n * Is this snippet nothing but install commands?\n *\n * Pairing \"npm i thing\" with a release headline reads as though the release was about\n * installing, which is how v0.0.6 shipped a bug-fix headline over the README's install block.\n * Install commands are still worth showing, they just need their own title.\n */\nconst INSTALL_COMMAND =\n /^\\s*(?:\\$\\s*)?(?:npm\\s+(?:i|install|add)|pnpm\\s+(?:i|install|add|dlx)|yarn\\s+(?:add|install)|bun\\s+(?:a|add|install)|npx|deno\\s+add|pip\\s+install|cargo\\s+add|go\\s+get|gem\\s+install|brew\\s+install)\\b/;\n\nexport function isInstallOnly(code: string): boolean {\n const lines = code\n .split(\"\\n\")\n .map((line) => line.replace(/\\s+#.*$/, \"\").trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n return lines.length > 0 && lines.every((line) => INSTALL_COMMAND.test(line));\n}\n\nexport function formatCount(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nexport function milestoneCopy(\n facts: Facts,\n metric: \"stars\" | \"downloads\" | \"contributors\",\n threshold: number,\n): Copy {\n const formatted = formatCount(threshold);\n const line =\n metric === \"stars\"\n ? `Thank you for ${formatted} stars`\n : metric === \"downloads\"\n ? `${formatted} weekly downloads`\n : `Thank you, ${formatted} contributors`;\n const tagline = facts.project.tagline?.value;\n return {\n headline: facts.project.name.value,\n subheadline: tagline !== undefined && tagline.length > 0 ? cleanLine(tagline) : \"\",\n highlights: [],\n cta: ctaFor(facts),\n milestoneLine: line,\n };\n}\n\nexport function benchCopy(facts: Facts): Copy {\n const title = facts.bench?.title.value ?? facts.project.name.value;\n const note = facts.bench?.note?.value;\n return {\n headline: title,\n subheadline: note !== undefined && note.length > 0 ? note : (facts.project.tagline?.value ?? \"\"),\n highlights: [],\n cta: ctaFor(facts),\n };\n}\n\n/**\n * First sentence of an entry, for use as a headline.\n *\n * Changesets entries are prose paragraphs written for a changelog, so using one whole made a\n * headline that could only be truncated mid-word. The first sentence is the part a person\n * actually wrote as the summary. Abbreviations are not special-cased: a sentence ending is a\n * period followed by a space and a capital, which leaves \"e.g. foo\" and version numbers alone.\n */\nexport function firstSentence(text: string): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n const match = /^(.+?[.?!])\\s+[A-Z]/.exec(collapsed);\n return match?.[1] ?? collapsed;\n}\n\n/**\n * Longest headline that fits two lines at the minimum font size on a 1200 wide card.\n * Measured rather than guessed: §13.1 originally said 48, which rejects most real changelog\n * sentences, and the fitting pass comfortably handles more.\n */\nconst HEADLINE_MAX_CHARS = 72;\n\n/**\n * Emoji ranges, removed from anything that reaches a card.\n *\n * No font we register carries these glyphs, so `\\u{1F310} Human-friendly ...` (got's real\n * GitHub description) rendered a tofu box on shipseal.dev. Takumi ships an emoji helper, but it\n * rewrites each emoji into an <img> pointing at jsDelivr, and `generate()` does no network.\n *\n * The ranges deliberately start at U+2600, which keeps the textual symbols people put in real\n * product names: (c) U+00A9, (r) U+00AE and (tm) U+2122 all sit below it.\n */\n// Alternation rather than one class: variation selectors and the zero-width joiner are\n// combining marks, which lint rejects when mixed into a class with ordinary code points.\nconst EMOJI = /[\\u{1F000}-\\u{1FAFF}]|[\\u{2600}-\\u{27BF}]|[\\u{FE00}-\\u{FE0F}]|\\u200D/gu;\n\nexport function stripEmoji(text: string): string {\n return text.replaceAll(EMOJI, \"\").replace(/\\s+/g, \" \").trim();\n}\n\nexport function cleanLine(text: string): string {\n // Replace an em dash with a colon and swallow the space in front of it, so \"shops \\u2014 mobile\"\n // becomes \"shops: mobile\" rather than \"shops : mobile\". Spaced en dashes become a comma for\n // the same reason: a bare hyphen with spaces reads like a stray dash on a card.\n const stripped = stripEmoji(text)\n .replace(/\\s*\\u2014\\s*/g, \": \")\n .replace(/\\s+\\u2013\\s+/g, \", \")\n .replaceAll(\"\\u2013\", \"-\")\n .replaceAll(\"!\", \".\")\n .replace(/\\s+/g, \" \")\n .trim();\n const noTrail = stripped.endsWith(\".\") ? stripped.slice(0, -1) : stripped;\n const first = noTrail.at(0);\n if (first === undefined) {\n return noTrail;\n }\n return first.toUpperCase() + noTrail.slice(1);\n}\n\nfunction ctaFor(facts: Facts): string {\n const npm = facts.project.npmPackage?.value;\n if (npm !== undefined && npm.length > 0) {\n // A package with a bin is run, not installed as a dependency. `@latest` because npx reuses\n // a cached copy otherwise, which is the footgun the README already warns about.\n return facts.project.cli?.value === true ? `npx ${npm}@latest` : `npm i ${npm}`;\n }\n const url = facts.project.url?.value ?? facts.project.repo?.value;\n if (url === undefined) {\n return facts.project.name.value;\n }\n return url.replace(/^https?:\\/\\//, \"\");\n}\n","// Percent change for benchmark cards. Display numbers are computed here, never by an LLM.\n// Spec: docs/PROJECT_PLAN.md §12.7\n\nexport interface PercentChange {\n signed: number;\n absPercent: number;\n regression: boolean;\n}\n\nexport function percentChange(before: number, after: number, better: \"lower\" | \"higher\"): PercentChange {\n if (before === 0) {\n if (after === 0) {\n return { signed: 0, absPercent: 0, regression: false };\n }\n const improved = better === \"higher\" ? after > 0 : after < 0;\n return { signed: improved ? 100 : -100, absPercent: 100, regression: !improved };\n }\n const raw = better === \"lower\" ? (before - after) / before : (after - before) / before;\n const signed = Math.round(raw * 100);\n return { signed, absPercent: Math.abs(signed), regression: signed < 0 };\n}\n\nexport function changePhrase(unit: string, better: \"lower\" | \"higher\", change: PercentChange): string {\n if (change.absPercent === 0) {\n return \"unchanged\";\n }\n return `${String(change.absPercent)}% ${deltaWord(unit, better, change.regression)}`;\n}\n\nfunction deltaWord(unit: string, better: \"lower\" | \"higher\", regression: boolean): string {\n if (better === \"higher\") {\n return regression ? \"lower\" : \"higher\";\n }\n const normalized = unit.toLowerCase();\n if (normalized === \"ms\" || normalized === \"s\" || normalized === \"sec\" || normalized === \"seconds\") {\n return regression ? \"slower\" : \"faster\";\n }\n if (\n normalized === \"kb\" ||\n normalized === \"mb\" ||\n normalized === \"b\" ||\n normalized === \"bytes\" ||\n normalized === \"gzip\"\n ) {\n return regression ? \"larger\" : \"smaller\";\n }\n return regression ? \"worse\" : \"better\";\n}\n","// Text fitting: shrink, then retry/truncate + manifest warning\n// Spec: docs/PROJECT_PLAN.md §15\n\nimport type { MeasureTextOptions, RendererAdapter } from \"../render/adapter.js\";\n\nexport interface TextSlotSpec {\n maxLines: number;\n maxFontSize: number;\n minFontSize: number;\n step: number;\n box: { width: number };\n}\n\nexport interface FittedText {\n fontSize: number;\n text: string;\n lines: number;\n truncated: boolean;\n}\n\nexport interface FitFont {\n family: string;\n lineHeight: number;\n weight?: number;\n whiteSpace?: \"normal\" | \"pre\";\n}\n\nexport async function fitText(\n renderer: Pick<RendererAdapter, \"measureText\">,\n text: string,\n spec: TextSlotSpec,\n font: FitFont,\n): Promise<FittedText> {\n const sizes = fontSizes(spec);\n for (const fontSize of sizes) {\n // Sizes must be tried largest-first; the first fit wins.\n // eslint-disable-next-line no-await-in-loop -- sequential by spec §15.2\n const measured = await renderer.measureText(text, measureOpts(spec, font, fontSize));\n if (measured.lines <= spec.maxLines) {\n return { fontSize, text, lines: measured.lines, truncated: false };\n }\n }\n\n const fontSize = spec.minFontSize;\n const truncated = await truncateToFit(renderer, text, spec, font, fontSize);\n const measured = await renderer.measureText(truncated, measureOpts(spec, font, fontSize));\n return { fontSize, text: truncated, lines: measured.lines, truncated: truncated !== text };\n}\n\nfunction fontSizes(spec: TextSlotSpec): number[] {\n const sizes: number[] = [];\n for (let size = spec.maxFontSize; size >= spec.minFontSize; size -= spec.step) {\n sizes.push(size);\n }\n const last = sizes[sizes.length - 1];\n if (last !== spec.minFontSize) {\n sizes.push(spec.minFontSize);\n }\n return sizes;\n}\n\nfunction measureOpts(spec: TextSlotSpec, font: FitFont, fontSize: number): MeasureTextOptions {\n const opts: MeasureTextOptions = {\n fontFamily: font.family,\n fontSize,\n maxWidth: spec.box.width,\n lineHeight: font.lineHeight,\n };\n if (font.weight !== undefined) {\n opts.fontWeight = font.weight;\n }\n if (font.whiteSpace !== undefined) {\n opts.whiteSpace = font.whiteSpace;\n }\n return opts;\n}\n\nasync function truncateToFit(\n renderer: Pick<RendererAdapter, \"measureText\">,\n text: string,\n spec: TextSlotSpec,\n font: FitFont,\n fontSize: number,\n): Promise<string> {\n const words = text.trim().length === 0 ? [] : text.trim().split(/\\s+/);\n if (words.length === 0) {\n return text;\n }\n\n const fits = async (candidate: string): Promise<boolean> => {\n const measured = await renderer.measureText(\n candidate,\n measureOpts(spec, font, fontSize),\n );\n return measured.lines <= spec.maxLines;\n };\n\n for (let count = words.length - 1; count >= 1; count -= 1) {\n const candidate = `${words.slice(0, count).join(\" \")}...`;\n // eslint-disable-next-line no-await-in-loop -- drop words until the truncated text fits\n if (await fits(candidate)) {\n return candidate;\n }\n }\n\n const first = words[0];\n if (first === undefined) {\n return \"...\";\n }\n for (let length = first.length; length >= 1; length -= 1) {\n const candidate = `${first.slice(0, length)}...`;\n // eslint-disable-next-line no-await-in-loop -- hard-cut the first word as a last resort\n if (await fits(candidate)) {\n return candidate;\n }\n }\n return \"...\";\n}\n","// Dark/light palette derived from brand.json\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { DEFAULT_BRAND_COLORS, type Brand } from \"../brand/schema.js\";\n\nexport interface ThemeColors {\n background: string;\n foreground: string;\n muted: string;\n primary: string;\n accent: string;\n card: string;\n}\n\nexport function themeColors(brand: Brand, theme: \"dark\" | \"light\"): ThemeColors {\n const primary = brand.colors.primary ?? DEFAULT_BRAND_COLORS.primary;\n const accent = brand.colors.accent ?? DEFAULT_BRAND_COLORS.accent;\n const muted = brand.colors.muted ?? DEFAULT_BRAND_COLORS.muted;\n if (theme === \"dark\") {\n const background = brand.theme === \"dark\" ? brand.colors.background : brand.colors.foreground;\n const foreground = brand.theme === \"dark\" ? brand.colors.foreground : brand.colors.background;\n return {\n background,\n foreground,\n muted: brand.theme === \"dark\" ? muted : DEFAULT_BRAND_COLORS.muted,\n primary,\n accent,\n card: mix(background, foreground, 0.08),\n };\n }\n const background = brand.theme === \"light\" ? brand.colors.background : brand.colors.foreground;\n const foreground = brand.theme === \"light\" ? brand.colors.foreground : brand.colors.background;\n return {\n background,\n foreground,\n muted: brand.theme === \"light\" ? muted : \"#52525b\",\n primary,\n accent,\n card: mix(background, foreground, 0.06),\n };\n}\n\nfunction mix(a: string, b: string, amount: number): string {\n const ar = Number.parseInt(a.slice(1, 3), 16);\n const ag = Number.parseInt(a.slice(3, 5), 16);\n const ab = Number.parseInt(a.slice(5, 7), 16);\n const br = Number.parseInt(b.slice(1, 3), 16);\n const bg = Number.parseInt(b.slice(3, 5), 16);\n const bb = Number.parseInt(b.slice(5, 7), 16);\n return `#${toHex(ar + (br - ar) * amount)}${toHex(ag + (bg - ag) * amount)}${toHex(ab + (bb - ab) * amount)}`;\n}\n\nfunction toHex(value: number): string {\n return Math.round(value).toString(16).padStart(2, \"0\");\n}\n","// Local four-line JSX runtime for Takumi templates (no React)\n// Spec: docs/PROJECT_PLAN.md §16.2, §25 (S1)\n\nexport type JsxElement = {\n type: string | symbol | ((props: Record<string, unknown>) => unknown);\n props: Record<string, unknown> | null;\n key: string | null;\n};\n\nexport function jsx(\n type: JsxElement[\"type\"],\n props: Record<string, unknown> | null,\n key?: string | null,\n): JsxElement {\n return { type, props, key: key ?? null };\n}\n\nexport const jsxs = jsx;\nexport const jsxDEV = jsx;\nexport const Fragment = Symbol.for(\"takumi.fragment\");\n\nexport namespace JSX {\n export type Element = JsxElement;\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n export type IntrinsicElements = Record<string, Record<string, unknown>>;\n}\n","// Template: syntax-highlighted snippet\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { CodeLine, Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\n/** Advance width of a monospace glyph as a fraction of the font size. */\nexport const MONO_ADVANCE = 0.6;\n\nconst propsSchema = z.object({\n headline: z.string(),\n headingFamily: z.string(),\n monoFamily: z.string(),\n headingWeight: z.number(),\n monoWeight: z.number(),\n radius: z.number(),\n lines: z.array(z.array(z.object({ text: z.string(), color: z.string() }))),\n});\n\nexport type CodeCardProps = z.infer<typeof propsSchema>;\n\nexport const codeCard: TemplateDefinition = {\n id: \"code-card\",\n events: [\"release\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n headline: { maxLines: 1, maxFontSize: 40, minFontSize: 28, step: 2, box: { width } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return { headline: props.headline };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"headline\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n }\n return { family: props.monoFamily, weight: props.monoWeight, lineHeight: 1.35, whiteSpace: \"pre\" };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n const lines = copy.codeLines ?? [];\n if (lines.length === 0) {\n missing.push({ fact: \"release.codeSnippet\", effect: \"code card uses empty snippet\" });\n }\n return {\n props: {\n headline: copy.codeTitle ?? copy.headline,\n headingFamily: brand.fonts.heading.family,\n monoFamily: brand.fonts.mono.family,\n headingWeight: brand.fonts.heading.weight,\n monoWeight: brand.fonts.mono.weight,\n radius: brand.radius,\n lines,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const headline = ctx.fitted.headline;\n\n // Size the type to the snippet rather than the card. A fixed 22px in a box with flexGrow\n // drew a 14-line frame around a 2-line snippet, leaving most of the card empty with small\n // text on it. Mono glyphs are a constant fraction of the em, so the widest line and the\n // line count give a size directly, with no measurement pass.\n const boxPad = 28;\n const lineHeight = 1.35;\n const lines = props.lines.length === 0 ? 1 : props.lines.length;\n const longest = Math.max(\n 1,\n ...props.lines.map((line) => line.reduce((total, token) => total + token.text.length, 0)),\n );\n const headlineHeight = (headline?.fontSize ?? 36) * 1.25;\n const attributionHeight = ctx.attribution ? 18 * 1.4 + 24 : 0;\n const innerWidth = ctx.format.width - 2 * pad - 2 * boxPad;\n const innerHeight =\n ctx.format.height - 2 * pad - headlineHeight - 24 - attributionHeight - 2 * boxPad;\n const codeSize = Math.max(\n 18,\n Math.min(44, Math.floor(Math.min(innerWidth / (longest * MONO_ADVANCE), innerHeight / (lines * lineHeight)))),\n );\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n gap: 24,\n }}\n >\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: headline?.fontSize ?? 36,\n color: colors.foreground,\n }}\n >\n {headline?.text ?? props.headline}\n </div>\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: \"center\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n padding: boxPad,\n gap: 0,\n }}\n >\n {props.lines.map((line, lineIndex) => (\n <div\n key={String(lineIndex)}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n }}\n >\n {line.map((token, tokenIndex) => (\n <div\n key={`${String(lineIndex)}-${String(tokenIndex)}`}\n style={{\n fontFamily: props.monoFamily,\n fontWeight: props.monoWeight,\n fontSize: codeSize,\n color: token.color,\n whiteSpace: \"pre\",\n lineHeight,\n }}\n >\n {token.text}\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: 400,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n );\n },\n};\n\nexport function emptyCodeLines(): CodeLine[] {\n return [[{ text: \" \", color: \"#e6edf3\" }]];\n}\n","// Syntax-highlight a snippet into colored spans (shiki tokens)\n// Spec: docs/PROJECT_PLAN.md §14.3, spike S5\n\nimport type { CodeLine } from \"../copy/slots.js\";\n\nconst MAX_LINES = 14;\n\nexport async function highlightCode(\n code: string,\n lang: string,\n theme: \"dark\" | \"light\",\n): Promise<CodeLine[]> {\n const clipped = code.split(\"\\n\").slice(0, MAX_LINES).join(\"\\n\");\n const fallbackColor = theme === \"dark\" ? \"#e6edf3\" : \"#1f2328\";\n try {\n const { codeToTokens } = await import(\"shiki\");\n const result = await codeToTokens(clipped, {\n lang: mapLang(lang),\n theme: theme === \"dark\" ? \"github-dark\" : \"github-light\",\n });\n return result.tokens.map((line) => {\n if (line.length === 0) {\n return [{ text: \" \", color: fallbackColor }];\n }\n return line.map((token) => ({\n text: token.content,\n color: token.color ?? fallbackColor,\n }));\n });\n } catch {\n return clipped.split(\"\\n\").map((line) => [{ text: line.length === 0 ? \" \" : line, color: fallbackColor }]);\n }\n}\n\nfunction mapLang(lang: string): \"ts\" | \"js\" | \"tsx\" | \"jsx\" | \"json\" | \"bash\" {\n const key = lang.toLowerCase();\n if (key === \"javascript\" || key === \"js\") {\n return \"js\";\n }\n if (key === \"tsx\") {\n return \"tsx\";\n }\n if (key === \"jsx\") {\n return \"jsx\";\n }\n if (key === \"json\") {\n return \"json\";\n }\n if (key === \"bash\" || key === \"shell\" || key === \"sh\") {\n return \"bash\";\n }\n return \"ts\";\n}\n","// Template: before/after metrics\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport { changePhrase, percentChange } from \"../bench/percent.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst rowSchema = z.object({\n label: z.string(),\n beforeText: z.string(),\n afterText: z.string(),\n changeText: z.string(),\n regression: z.boolean(),\n});\n\nconst propsSchema = z.object({\n title: z.string(),\n note: z.string(),\n rows: z.array(rowSchema),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n});\n\nexport type BenchProps = z.infer<typeof propsSchema>;\n\nexport const bench: TemplateDefinition = {\n id: \"bench\",\n events: [\"bench\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n const slots: Record<string, { maxLines: number; maxFontSize: number; minFontSize: number; step: number; box: { width: number } }> =\n {\n title: { maxLines: 2, maxFontSize: 48, minFontSize: 28, step: 2, box: { width } },\n };\n for (let index = 0; index < 3; index += 1) {\n slots[`change-${String(index)}`] = {\n maxLines: 1,\n maxFontSize: 36,\n minFontSize: 22,\n step: 2,\n box: { width: Math.min(360, width) },\n };\n }\n return slots;\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n const text: Record<string, string> = { title: props.title };\n props.rows.forEach((row, index) => {\n text[`change-${String(index)}`] = row.changeText;\n });\n return text;\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"title\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.15 };\n }\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (facts.bench === undefined) {\n missing.push({ fact: \"bench\", effect: \"metrics hidden\" });\n }\n const rows =\n facts.bench?.metrics.map((metric) => {\n const change = percentChange(metric.before.value, metric.after.value, metric.better.value);\n return {\n label: metric.label.value,\n beforeText: `${formatMetric(metric.before.value)} ${metric.unit.value}`,\n afterText: `${formatMetric(metric.after.value)} ${metric.unit.value}`,\n changeText: changePhrase(metric.unit.value, metric.better.value, change),\n regression: change.regression,\n };\n }) ?? [];\n return {\n props: {\n title: copy.headline,\n note: copy.subheadline,\n rows,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const title = ctx.fitted.title;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n }}\n >\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: title?.fontSize ?? 40,\n color: colors.foreground,\n lineHeight: 1.15,\n }}\n >\n {title?.text ?? props.title}\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 20 }}>\n {props.rows.map((row, index) => {\n const change = ctx.fitted[`change-${String(index)}`];\n return (\n <div\n key={row.label}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n paddingTop: 16,\n paddingBottom: 16,\n paddingLeft: 24,\n paddingRight: 24,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6 }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.muted,\n }}\n >\n {row.label}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 24,\n color: colors.foreground,\n }}\n >\n {`${row.beforeText} to ${row.afterText}`}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"flex-end\", gap: 4 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: change?.fontSize ?? 32,\n color: row.regression ? colors.primary : colors.accent,\n }}\n >\n {change?.text ?? row.changeText}\n </div>\n {row.regression ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.primary,\n }}\n >\n regression\n </div>\n ) : undefined}\n </div>\n </div>\n );\n })}\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 20,\n color: colors.muted,\n }}\n >\n {props.note}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n\nfunction formatMetric(value: number): string {\n return String(value);\n}\n","// Template: milestone big number\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport { formatCount } from \"../copy/deterministic.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n numberText: z.string(),\n metricLabel: z.string(),\n thankYou: z.string(),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n showLogo: z.boolean(),\n});\n\nexport type MilestoneProps = z.infer<typeof propsSchema>;\n\nexport const milestone: TemplateDefinition = {\n id: \"milestone\",\n events: [\"milestone\"],\n formats: [\"og\", \"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n number: { maxLines: 1, maxFontSize: 160, minFontSize: 72, step: 8, box: { width } },\n thankYou: { maxLines: 2, maxFontSize: 36, minFontSize: 24, step: 2, box: { width } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return { number: props.numberText, thankYou: props.thankYou };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"number\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1 };\n }\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n const threshold = facts.milestone?.threshold.value;\n if (threshold === undefined) {\n missing.push({ fact: \"milestone.threshold\", effect: \"number hidden\" });\n }\n const metric = facts.milestone?.metric.value;\n const metricLabel =\n metric === \"downloads\" ? \"weekly downloads\" : metric === \"contributors\" ? \"contributors\" : \"stars\";\n const showLogo = brand.logo !== undefined;\n if (!showLogo) {\n missing.push({ fact: \"brand.logo\", effect: \"logo hidden\" });\n }\n const thankYou = copy.milestoneLine ?? (threshold === undefined ? \"\" : `Thank you for ${formatCount(threshold)} ${metricLabel}`);\n return {\n props: {\n name: brand.name,\n numberText: threshold === undefined ? \"\" : formatCount(threshold),\n metricLabel,\n thankYou,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n showLogo,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const number = ctx.fitted.number;\n const thanks = ctx.fitted.thankYou;\n const compact = ctx.format.height <= 640;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"row\", alignItems: \"center\", gap: 20 }}>\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <img src={ctx.logoSrc} width={compact ? 56 : 72} height={compact ? 56 : 72} />\n ) : undefined}\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 28,\n color: colors.foreground,\n }}\n >\n {props.name}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: number?.fontSize ?? 140,\n color: colors.foreground,\n lineHeight: 1,\n }}\n >\n {number?.text ?? props.numberText}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: 32,\n color: colors.primary,\n }}\n >\n {props.metricLabel}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: thanks?.fontSize ?? 28,\n color: colors.muted,\n lineHeight: 1.25,\n }}\n >\n {thanks?.text ?? props.thankYou}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n","// Seal stamp: the verified-facts mark shared by every template\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport type { Facts } from \"../../facts/schema.js\";\nimport { formatCount } from \"../../copy/deterministic.js\";\n\nexport interface SealStamp {\n segments: string[];\n missing: { fact: string; effect: string }[];\n}\n\n/**\n * The core promise, made visible on the card.\n *\n * \"sealed · 7 commits · 2026-09-11\" turns \"every number has a source\" from a claim on the\n * website into a mark in the feed. Every segment is a fact, so rule 1 holds: a missing fact\n * drops its segment and is reported, it never becomes a placeholder or an estimate.\n */\nexport function sealStamp(facts: Facts): SealStamp {\n const segments = [\"sealed\"];\n const missing: SealStamp[\"missing\"] = [];\n\n const commits = facts.release?.commitCount?.value;\n if (commits === undefined) {\n missing.push({ fact: \"release.commitCount\", effect: \"seal stamp omits the commit count\" });\n } else {\n segments.push(`${formatCount(commits)} ${commits === 1 ? \"commit\" : \"commits\"}`);\n }\n\n const date = facts.release?.date?.value;\n if (date === undefined) {\n missing.push({ fact: \"release.date\", effect: \"seal stamp omits the date\" });\n } else {\n segments.push(date);\n }\n\n return { segments, missing };\n}\n","// Template: release hero\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\nimport { sealStamp } from \"./primitives/seal.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n version: z.string(),\n headline: z.string(),\n subheadline: z.string(),\n cta: z.string(),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n showCta: z.boolean(),\n showLogo: z.boolean(),\n seal: z.array(z.string()),\n});\n\nexport type ReleaseHeroProps = z.infer<typeof propsSchema>;\n\nexport const releaseHero: TemplateDefinition = {\n id: \"release-hero\",\n events: [\"release\"],\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n headline: { maxLines: 2, maxFontSize: 72, minFontSize: 48, step: 4, box: { width } },\n subheadline: { maxLines: 2, maxFontSize: 32, minFontSize: 24, step: 2, box: { width } },\n cta: { maxLines: 1, maxFontSize: 28, minFontSize: 22, step: 2, box: { width: Math.min(480, width) } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return {\n headline: props.headline,\n subheadline: props.subheadline,\n cta: props.cta,\n };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"headline\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n }\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (facts.project.npmPackage === undefined && facts.project.url === undefined) {\n missing.push({ fact: \"project.npmPackage\", effect: \"cta uses project name\" });\n }\n const showLogo = brand.logo !== undefined;\n if (!showLogo) {\n missing.push({ fact: \"brand.logo\", effect: \"logo hidden\" });\n }\n const seal = sealStamp(facts);\n missing.push(...seal.missing);\n const version = facts.release?.version.value ?? \"\";\n return {\n props: {\n name: brand.name,\n version,\n headline: copy.headline,\n subheadline: copy.subheadline,\n cta: copy.cta,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n showCta: copy.cta.length > 0,\n seal: seal.segments,\n showLogo,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const headline = ctx.fitted.headline;\n const sub = ctx.fitted.subheadline;\n const cta = ctx.fitted.cta;\n const compact = ctx.format.height <= 640;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n position: \"relative\",\n }}\n >\n {/* The right half was empty on every hero. A large, faint mark fills it without\n competing with the headline, and reads as the seal rather than as decoration. */}\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <div\n style={{\n display: \"flex\",\n position: \"absolute\",\n right: -Math.round(ctx.format.height * 0.12),\n top: Math.round(ctx.format.height * 0.18),\n opacity: 0.06,\n }}\n >\n <img\n src={ctx.logoSrc}\n width={Math.round(ctx.format.height * 0.72)}\n height={Math.round(ctx.format.height * 0.72)}\n />\n </div>\n ) : undefined}\n <div style={{ display: \"flex\", flexDirection: \"row\", alignItems: \"center\", gap: 20 }}>\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <img src={ctx.logoSrc} width={compact ? 56 : 72} height={compact ? 56 : 72} />\n ) : undefined}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 28,\n color: colors.foreground,\n }}\n >\n {props.name}\n </div>\n {props.version.length > 0 ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n paddingTop: 6,\n paddingBottom: 6,\n paddingLeft: 14,\n paddingRight: 14,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.foreground,\n }}\n >\n {`v${props.version}`}\n </div>\n </div>\n ) : undefined}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: headline?.fontSize ?? 64,\n color: colors.foreground,\n lineHeight: 1.1,\n }}\n >\n {headline?.text ?? props.headline}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: sub?.fontSize ?? 28,\n color: colors.muted,\n lineHeight: 1.25,\n }}\n >\n {sub?.text ?? props.subheadline}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n {props.showCta ? (\n <div\n style={{\n display: \"flex\",\n backgroundColor: colors.primary,\n borderRadius: props.radius,\n paddingTop: 14,\n paddingBottom: 14,\n paddingLeft: 24,\n paddingRight: 24,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: cta?.fontSize ?? 24,\n color: colors.background,\n }}\n >\n {cta?.text ?? props.cta}\n </div>\n </div>\n ) : (\n <div />\n )}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n gap: 6,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: 20,\n color: colors.primary,\n }}\n >\n {props.seal.join(\" \\u00b7 \")}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n </div>\n );\n },\n};\n","// Template: what's new list\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n version: z.string(),\n highlights: z.array(z.string()),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n});\n\nexport type ReleaseHighlightsProps = z.infer<typeof propsSchema>;\n\nexport const releaseHighlights: TemplateDefinition = {\n id: \"release-highlights\",\n events: [\"release\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone - 48;\n const slots: Record<string, { maxLines: number; maxFontSize: number; minFontSize: number; step: number; box: { width: number } }> = {};\n for (let index = 0; index < 4; index += 1) {\n slots[`highlight-${String(index)}`] = {\n maxLines: 2,\n maxFontSize: 32,\n minFontSize: 24,\n step: 2,\n box: { width },\n };\n }\n return slots;\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n const text: Record<string, string> = {};\n props.highlights.forEach((line, index) => {\n text[`highlight-${String(index)}`] = line;\n });\n return text;\n },\n slotFont(raw) {\n const props = propsSchema.parse(raw);\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (copy.highlights.length === 0) {\n missing.push({ fact: \"release.features\", effect: \"highlights list empty\" });\n }\n return {\n props: {\n name: brand.name,\n version: facts.release?.version.value ?? \"\",\n highlights: copy.highlights,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const title = props.version.length > 0 ? `What's new in v${props.version}` : \"What's new\";\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n gap: 28,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.primary,\n }}\n >\n {props.name}\n </div>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 48,\n color: colors.foreground,\n }}\n >\n {title}\n </div>\n </div>\n {/*\n Grow the list to fill the card and centre it. A release with one or two highlights\n used to leave most of the card empty, which reads as a broken render rather than a\n small release.\n */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: props.highlights.length > 2 ? \"flex-start\" : \"center\",\n gap: props.highlights.length > 2 ? 16 : 20,\n }}\n >\n {props.highlights.map((line, index) => {\n const fitted = ctx.fitted[`highlight-${String(index)}`];\n const breaking = line.startsWith(\"Breaking:\");\n return (\n <div\n key={String(index)}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"flex-start\",\n gap: 16,\n backgroundColor: colors.card,\n borderRadius: props.radius,\n padding: 18,\n }}\n >\n <div\n style={{\n width: 12,\n height: 12,\n borderRadius: 6,\n backgroundColor: breaking ? colors.accent : colors.primary,\n marginTop: 10,\n }}\n />\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: fitted?.fontSize ?? 28,\n color: colors.foreground,\n lineHeight: 1.25,\n }}\n >\n {fitted?.text ?? line}\n </div>\n </div>\n );\n })}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n marginTop: \"auto\",\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n );\n },\n};\n","// zod schemas for Facts, Fact<T>, Provenance\n// Spec: docs/PROJECT_PLAN.md §9\n\nimport { z } from \"zod\";\n\nexport const SOURCE_IDS = [\n \"git\",\n \"package-json\",\n \"readme\",\n \"changelog\",\n \"github-api\",\n \"npm-api\",\n \"bench-file\",\n \"user-config\",\n \"brand\",\n] as const;\n\nexport const sourceIdSchema = z.enum(SOURCE_IDS);\nexport type SourceId = z.infer<typeof sourceIdSchema>;\n\nexport const provenanceSchema = z.object({\n source: sourceIdSchema,\n ref: z.string().min(1),\n fetchedAt: z.iso.datetime(),\n});\nexport type Provenance = z.infer<typeof provenanceSchema>;\n\nexport function factSchema<T extends z.ZodType>(valueSchema: T) {\n return z.object({\n value: valueSchema,\n provenance: provenanceSchema,\n });\n}\n\nexport type Fact<T> = {\n value: T;\n provenance: Provenance;\n};\n\nconst stringFact = factSchema(z.string());\nconst numberFact = factSchema(z.number());\nconst stringListFact = factSchema(z.array(z.string()));\nconst codeSnippetFact = factSchema(\n z.object({\n code: z.string(),\n lang: z.string(),\n }),\n);\nconst betterFact = factSchema(z.enum([\"lower\", \"higher\"]));\n\nexport const storyPageSchema = z.object({\n kind: z.enum([\"cover\", \"change\", \"code\", \"comparison\", \"upgrade\"]),\n title: stringFact,\n body: stringFact,\n before: stringFact.optional(),\n after: stringFact.optional(),\n});\nexport type StoryPage = z.infer<typeof storyPageSchema>;\n\nexport const factsSchema = z.object({\n story: z.array(storyPageSchema).optional(),\n project: z.object({\n name: stringFact,\n tagline: stringFact.optional(),\n url: stringFact.optional(),\n repo: stringFact.optional(),\n npmPackage: stringFact.optional(),\n cli: factSchema(z.boolean()).optional(),\n license: stringFact.optional(),\n }),\n release: z\n .object({\n version: stringFact,\n tag: stringFact,\n kind: factSchema(z.enum([\"major\", \"minor\", \"patch\"])).optional(),\n headline: stringFact.optional(),\n subheadline: stringFact.optional(),\n previousVersion: stringFact.optional(),\n date: stringFact,\n features: z.array(stringFact),\n fixes: z.array(stringFact),\n breaking: z.array(stringFact),\n commitCount: numberFact.optional(),\n contributors: stringListFact.optional(),\n codeSnippet: codeSnippetFact.optional(),\n })\n .optional(),\n metrics: z\n .object({\n stars: numberFact.optional(),\n weeklyDownloads: numberFact.optional(),\n contributorCount: numberFact.optional(),\n })\n .optional(),\n bench: z\n .object({\n title: stringFact,\n metrics: z.array(\n z.object({\n label: stringFact,\n before: numberFact,\n after: numberFact,\n unit: stringFact,\n better: betterFact,\n }),\n ),\n note: stringFact.optional(),\n })\n .optional(),\n milestone: z\n .object({\n metric: stringFact,\n threshold: numberFact,\n })\n .optional(),\n});\n\nexport type Facts = z.infer<typeof factsSchema>;\n","// One page of a release story. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n//\n// The kind on the page decides the body treatment: `code` uses the mono family and preserves\n// whitespace, `comparison` lays out two supplied screenshots, everything else is prose. The\n// brand style decides the chrome: editorial adds rules, terminal adds a framed body.\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { MONO_ADVANCE } from \"./code-card.js\";\nimport { storyPageSchema } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n page: storyPageSchema,\n name: z.string(),\n version: z.string(),\n heading: z.string(),\n body: z.string(),\n mono: z.string(),\n weight: z.number(),\n});\n\nconst HEADER_HEIGHT = 36;\nconst BODY_PAD = 24;\nconst CODE_LINE_HEIGHT = 1.35;\nconst CODE_MIN_FONT_SIZE = 14;\nconst FOOTER_ALLOWANCE = 144;\nconst TALL_THRESHOLD = 900;\n\nfunction geometry(format: Format) {\n const tall = format.height > TALL_THRESHOLD;\n const titleHeight = tall ? 220 : 112;\n return {\n tall,\n titleHeight,\n width: format.width - 2 * format.safeZone,\n bodyHeight: format.height - 2 * format.safeZone - titleHeight - FOOTER_ALLOWANCE,\n };\n}\n\nconst NO_BORDER = \"0px solid transparent\";\n\n/**\n * Monospace `pre` text does not wrap, so the generic line-count fitter cannot keep it inside\n * the card: it reports two lines that fit and the long one runs off the right edge. Mono\n * glyphs are a constant fraction of the em, so the widest line gives a size directly. Same\n * approach as code-card, which is why MONO_ADVANCE is shared rather than copied.\n */\nfunction codeFontSize(text: string, box: { width: number; height: number }, max: number): number {\n const lines = text.split(\"\\n\");\n const longest = Math.max(1, ...lines.map((line) => line.length));\n const byWidth = box.width / (longest * MONO_ADVANCE);\n const byHeight = box.height / (lines.length * CODE_LINE_HEIGHT);\n return Math.max(CODE_MIN_FONT_SIZE, Math.min(max, Math.floor(Math.min(byWidth, byHeight))));\n}\n\n/**\n * A body the reader is meant to copy and run: a code snippet, or upgrade instructions the\n * maintainer supplied. Generated upgrade prose (a link to the release notes) is not one, so\n * the provenance decides rather than the page kind alone.\n */\nfunction isCommand(page: z.infer<typeof propsSchema>[\"page\"]): boolean {\n return (\n page.kind === \"code\" ||\n (page.kind === \"upgrade\" && page.body.provenance.source === \"user-config\")\n );\n}\n\nexport const storyPage: TemplateDefinition = {\n id: \"story-page\",\n events: [\"release\"],\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\", \"square\", \"portrait\", \"producthunt\"],\n propsSchema,\n\n slots(format) {\n const { width, titleHeight, bodyHeight, tall } = geometry(format);\n return {\n name: { maxLines: 1, maxFontSize: 24, minFontSize: 18, step: 2, box: { width: width - 300 } },\n version: { maxLines: 1, maxFontSize: 22, minFontSize: 16, step: 2, box: { width: 220 } },\n // The floor sits above the body's ceiling on purpose. Fitted independently, a long title\n // shrank to 28 while the body stayed at 34, so the page read with its hierarchy inverted.\n // Truncating with a manifest warning is the honest outcome, not a title smaller than its\n // own paragraph.\n title: {\n // Four lines on a tall canvas. Change titles truncated on 6 of the 20 repositories\n // surveyed on 2026-09-15, and a portrait page has the room to spare.\n maxLines: tall ? 4 : 2,\n maxFontSize: tall ? 64 : 48,\n minFontSize: tall ? 36 : 30,\n step: 2,\n box: { width: width - 32, height: titleHeight },\n },\n body: {\n maxLines: Math.floor(bodyHeight / 30),\n maxFontSize: tall ? 34 : 28,\n minFontSize: 20,\n step: 2,\n box: { width: width - 48, height: bodyHeight - 48 },\n },\n };\n },\n\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return {\n name: props.name,\n version: props.version,\n title: props.page.title.value,\n body: props.page.body.value,\n };\n },\n\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n const mono = slot === \"body\" && isCommand(props.page);\n return {\n family: mono ? props.mono : slot === \"title\" ? props.heading : props.body,\n weight: slot === \"title\" ? props.weight : 400,\n lineHeight: mono ? 1.35 : 1.2,\n whiteSpace: mono ? \"pre\" : \"normal\",\n };\n },\n\n buildProps(facts, _copy, brand) {\n const page = facts.story?.[0];\n if (page === undefined) {\n // Reachable when release.templates names story-page directly, so this has to be a\n // typed error rather than a schema failure from inside generate().\n throw new ShipsealError(\n \"story-page.no-page\",\n \"The story-page template has no story page to render.\",\n \"Run shipseal story to build a story pack. Do not list story-page in release.templates.\",\n );\n }\n return {\n props: {\n page,\n name: brand.name,\n version: facts.release?.tag.value ?? \"\",\n heading: brand.style === \"terminal\" ? brand.fonts.mono.family : brand.fonts.heading.family,\n body: brand.fonts.body.family,\n mono: brand.fonts.mono.family,\n weight: brand.fonts.heading.weight,\n },\n missing: [],\n };\n },\n\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const { tall, bodyHeight, width } = geometry(ctx.format);\n const editorial = ctx.brand.style === \"editorial\";\n const terminal = ctx.brand.style === \"terminal\";\n const code = isCommand(props.page);\n const comparison = props.page.kind === \"comparison\";\n const title = ctx.fitted.title;\n const body = ctx.fitted.body;\n const hasBody = props.page.body.value.trim().length > 0;\n const bodyText = body?.text ?? props.page.body.value;\n const bodyFontSize = code\n ? codeFontSize(\n bodyText,\n { width: width - 2 * BODY_PAD, height: bodyHeight - 2 * BODY_PAD },\n tall ? 34 : 28,\n )\n : (body?.fontSize ?? 28);\n const paneWidth = tall ? width : (width - 16) / 2;\n const paneHeight = tall ? (bodyHeight - 16) / 2 : bodyHeight;\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n color: colors.foreground,\n padding: ctx.format.safeZone,\n gap: 24,\n borderTop: editorial ? `16px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n height: HEADER_HEIGHT,\n flexShrink: 0,\n borderBottom: terminal ? `1px solid ${colors.muted}` : NO_BORDER,\n paddingBottom: terminal ? 12 : 0,\n }}\n >\n <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n {ctx.logoSrc !== undefined ? <img src={ctx.logoSrc} width={32} height={32} /> : undefined}\n <div\n style={{\n fontFamily: terminal ? props.mono : props.body,\n fontWeight: 400,\n fontSize: ctx.fitted.name?.fontSize ?? 24,\n color: colors.primary,\n }}\n >\n {ctx.fitted.name?.text ?? props.name}\n </div>\n </div>\n <div\n style={{\n fontFamily: props.mono,\n fontWeight: 400,\n fontSize: ctx.fitted.version?.fontSize ?? 22,\n color: colors.muted,\n }}\n >\n {ctx.fitted.version?.text ?? props.version}\n </div>\n </div>\n\n {/*\n Title and body are one block, centred in whatever space the header and footer leave.\n They used to sit in two fixed-height boxes, so a short cover or closing page put its\n content in the top third and left the rest of a 1080x1350 canvas empty.\n */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: \"center\",\n gap: 24,\n minHeight: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n flexShrink: 0,\n paddingLeft: editorial ? 24 : 0,\n borderLeft: editorial ? `8px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n fontFamily: props.heading,\n fontWeight: props.weight,\n fontSize: title?.fontSize ?? 48,\n lineHeight: 1.2,\n maxWidth: width - (editorial ? 32 : 0),\n }}\n >\n {title?.text ?? props.page.title.value}\n </div>\n </div>\n\n {comparison ? (\n <div\n style={{\n display: \"flex\",\n flexDirection: tall ? \"column\" : \"row\",\n gap: 16,\n height: bodyHeight,\n }}\n >\n {[\"before\", \"after\"].map((label) => (\n <div\n key={label}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n width: paneWidth,\n height: paneHeight,\n }}\n >\n <div style={{ fontFamily: props.body, fontSize: 20, color: colors.muted }}>\n {label === \"before\" ? \"Before\" : \"After\"}\n </div>\n <img\n src={`story-${label}`}\n width={paneWidth}\n height={paneHeight - HEADER_HEIGHT}\n style={{ objectFit: \"contain\" }}\n />\n </div>\n ))}\n </div>\n ) : hasBody ? (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n // Top-aligned: centring a short paragraph in a full-height box leaves a hole\n // in the middle of the card rather than margin at the bottom.\n justifyContent: \"flex-start\",\n maxHeight: bodyHeight,\n padding: terminal || code ? BODY_PAD : 0,\n backgroundColor: terminal || code ? colors.card : \"transparent\",\n borderRadius: terminal ? 0 : ctx.brand.radius,\n borderLeft: terminal ? `3px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n fontFamily: code ? props.mono : props.body,\n fontWeight: 400,\n fontSize: bodyFontSize,\n lineHeight: code ? CODE_LINE_HEIGHT : 1.2,\n whiteSpace: code ? \"pre\" : \"normal\",\n color: colors.foreground,\n }}\n >\n {bodyText}\n </div>\n </div>\n ) : undefined}\n </div>\n\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n flexShrink: 0,\n fontFamily: props.mono,\n fontWeight: 400,\n fontSize: 16,\n color: colors.muted,\n }}\n >\n <div style={{ fontFamily: props.mono }}>\n {comparison ? \"Supplied screenshots\" : \"Sources in manifest.json\"}\n </div>\n {ctx.attribution ? (\n <div style={{ fontFamily: props.mono }}>made with shipseal.dev</div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n","// Template registry\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { bench } from \"./bench.js\";\nimport { codeCard } from \"./code-card.js\";\nimport { milestone } from \"./milestone.js\";\nimport { releaseHero } from \"./release-hero.js\";\nimport { releaseHighlights } from \"./release-highlights.js\";\nimport { storyPage } from \"./story-page.js\";\n\nconst templates = [releaseHero, releaseHighlights, codeCard, milestone, bench, storyPage] as const;\n\nexport function getTemplate(id: string): TemplateDefinition {\n const found = templates.find((template) => template.id === id);\n if (found === undefined) {\n throw new ShipsealError(\n \"template.unknown\",\n `Unknown template \"${id}\".`,\n `Use one of: ${templates.map((template) => template.id).join(\", \")}.`,\n );\n }\n return found;\n}\n\nexport function templatesForEvent(kind: \"release\" | \"milestone\" | \"bench\"): TemplateDefinition[] {\n return templates.filter((template) => template.events.includes(kind));\n}\n\nexport const RELEASE_TEMPLATE_IDS = [\"release-hero\", \"release-highlights\", \"code-card\"] as const;\n","// The pure pipeline: facts + copy + brand + templates -> rendered files (no network I/O)\n// Spec: docs/PROJECT_PLAN.md §6.1\n\nimport { percentChange } from \"../bench/percent.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { ShipsealEvent } from \"./events.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { fitText, type FittedText } from \"../fit/fit-text.js\";\nimport { FORMATS, type Format, type FormatId } from \"../formats.js\";\nimport type { ImageFormat, RenderOptions, RendererAdapter } from \"../render/adapter.js\";\nimport { emptyCodeLines } from \"../templates/code-card.js\";\nimport type { ManifestMissing, RenderContext, TemplateDefinition } from \"../templates/contract.js\";\nimport { highlightCode } from \"../templates/highlight.js\";\nimport { getTemplate } from \"../templates/registry.js\";\n\n/**\n * Digest via WebCrypto, not `node:crypto`. The browser demo imports `generate()`, so nothing\n * in the pure core may reach for a Node builtin. Do not \"simplify\" this back to createHash.\n */\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", Uint8Array.from(bytes));\n return Array.from(new Uint8Array(digest))\n .map((value) => value.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nexport interface GenerateInput {\n event: ShipsealEvent;\n facts: Facts;\n brand: Brand;\n config: Config;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n renderer: RendererAdapter;\n themes: Array<\"dark\" | \"light\">;\n generatedAt: string;\n logos?: { light?: Uint8Array; dark?: Uint8Array };\n images?: Array<{ src: string; data: Uint8Array }>;\n}\n\nexport interface GeneratedFile {\n fileName: string;\n template: string;\n format: FormatId;\n theme: \"dark\" | \"light\";\n width: number;\n height: number;\n bytes: Uint8Array;\n sha256: string;\n}\n\nexport interface FitWarning {\n type: \"fit-warning\";\n template: string;\n format: FormatId;\n slot: string;\n action: \"truncated\";\n}\n\nexport interface GenerateResult {\n files: GeneratedFile[];\n warnings: FitWarning[];\n missing: Array<ManifestMissing & { template: string }>;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n generatedAt: string;\n computed: Record<string, { value: unknown; computedFrom: string[] }>;\n}\n\nexport async function generate(input: GenerateInput): Promise<GenerateResult> {\n const templateIds = templateIdsFor(input.event, input.config);\n const formatIds = input.config.formats ?? [\"og\", \"github-social\", \"x\", \"linkedin\"];\n const imageFormat: ImageFormat = input.config.output?.imageFormat ?? \"png\";\n const attribution = input.config.attribution !== false;\n const files: GeneratedFile[] = [];\n const warnings: FitWarning[] = [];\n const missing: Array<ManifestMissing & { template: string }> = [];\n const recordedMissing = new Set<string>();\n const omitThemeSuffix = input.themes.length === 1;\n\n for (const templateId of templateIds) {\n const template = getTemplate(templateId);\n if (!template.events.includes(input.event.kind)) {\n continue;\n }\n for (const formatId of formatIds) {\n if (!template.formats.includes(formatId)) {\n continue;\n }\n const format = FORMATS[formatId];\n for (const theme of input.themes) {\n // Formats and themes render sequentially so fit warnings stay attached to the right file.\n // eslint-disable-next-line no-await-in-loop\n const copy = await copyForTemplate(template.id, input.copy, input.facts, theme);\n const built = template.buildProps(input.facts, copy, input.brand);\n const props = template.propsSchema.parse(built.props);\n if (!recordedMissing.has(template.id)) {\n recordedMissing.add(template.id);\n for (const item of built.missing) {\n missing.push({ template: template.id, fact: item.fact, effect: item.effect });\n }\n }\n // eslint-disable-next-line no-await-in-loop\n const { fitted, truncated } = await fitSlots(input.renderer, template, props, format);\n for (const slot of truncated) {\n warnings.push({\n type: \"fit-warning\",\n template: template.id,\n format: formatId,\n slot,\n action: \"truncated\",\n });\n }\n const logo = logoForTheme(input.logos, theme);\n const ctx: RenderContext = {\n format,\n theme,\n brand: input.brand,\n fitted,\n attribution,\n };\n if (logo !== undefined) {\n ctx.logoSrc = \"shipseal-logo\";\n }\n const jsx = template.render(props, ctx);\n // eslint-disable-next-line no-await-in-loop\n const node = await input.renderer.fromJsx(jsx);\n const renderOpts: RenderOptions = {\n width: format.width,\n height: format.height,\n format: imageFormat,\n };\n if (logo !== undefined) {\n renderOpts.images = [{ src: \"shipseal-logo\", data: logo }];\n }\n if (input.images !== undefined) {\n renderOpts.images = [...(renderOpts.images ?? []), ...input.images];\n }\n // eslint-disable-next-line no-await-in-loop\n const bytes = await input.renderer.render(node, renderOpts);\n const fileName = outputName(template.id, formatId, theme, omitThemeSuffix, imageFormat);\n // eslint-disable-next-line no-await-in-loop -- one digest per rendered file\n const sha256 = await sha256Hex(bytes);\n files.push({\n fileName,\n template: template.id,\n format: formatId,\n theme,\n width: format.width,\n height: format.height,\n bytes,\n sha256,\n });\n }\n }\n }\n\n return {\n files,\n warnings,\n missing,\n facts: input.facts,\n copy: input.copy,\n copyMode: input.copyMode,\n generatedAt: input.generatedAt,\n computed: computedFromFacts(input.facts),\n };\n}\n\nfunction templateIdsFor(event: ShipsealEvent, config: Config): string[] {\n if (event.kind === \"milestone\") {\n return [\"milestone\"];\n }\n if (event.kind === \"bench\") {\n return [\"bench\"];\n }\n return config.release?.templates ?? [\"release-hero\", \"release-highlights\", \"code-card\"];\n}\n\nfunction computedFromFacts(facts: Facts): Record<string, { value: unknown; computedFrom: string[] }> {\n const out: Record<string, { value: unknown; computedFrom: string[] }> = {};\n if (facts.bench === undefined) {\n return out;\n }\n facts.bench.metrics.forEach((metric, index) => {\n const change = percentChange(metric.before.value, metric.after.value, metric.better.value);\n const prefix = `bench.metrics[${String(index)}]`;\n out[`${prefix}.percent`] = {\n value: change.signed,\n computedFrom: [`${prefix}.before`, `${prefix}.after`, `${prefix}.better`],\n };\n });\n return out;\n}\n\nasync function fitSlots(\n renderer: RendererAdapter,\n template: TemplateDefinition,\n props: unknown,\n format: Format,\n): Promise<{ fitted: Record<string, FittedText>; truncated: string[] }> {\n const specs = template.slots(format);\n const texts = template.slotText(props);\n const fitted: Record<string, FittedText> = {};\n const truncated: string[] = [];\n for (const [slot, spec] of Object.entries(specs)) {\n const text = texts[slot];\n if (text === undefined) {\n continue;\n }\n const font = template.slotFont(props, slot);\n const fitFont: { family: string; lineHeight: number; weight: number; whiteSpace?: \"normal\" | \"pre\" } = {\n family: font.family,\n lineHeight: font.lineHeight,\n weight: font.weight,\n };\n if (font.whiteSpace !== undefined) {\n fitFont.whiteSpace = font.whiteSpace;\n }\n // eslint-disable-next-line no-await-in-loop -- sizes are sequential per slot spec\n const result = await fitText(renderer, text, spec, fitFont);\n fitted[slot] = result;\n if (result.truncated) {\n truncated.push(slot);\n }\n }\n return { fitted, truncated };\n}\n\nfunction outputName(\n template: string,\n format: FormatId,\n theme: \"dark\" | \"light\",\n omitTheme: boolean,\n imageFormat: string,\n): string {\n const themePart = omitTheme ? \"\" : `-${theme}`;\n return `${template}-${format}${themePart}.${imageFormat}`;\n}\n\nfunction logoForTheme(\n logos: GenerateInput[\"logos\"],\n theme: \"dark\" | \"light\",\n): Uint8Array | undefined {\n if (logos === undefined) {\n return undefined;\n }\n if (theme === \"dark\") {\n return logos.dark ?? logos.light;\n }\n return logos.light ?? logos.dark;\n}\n\nasync function copyForTemplate(\n templateId: string,\n copy: Copy,\n facts: Facts,\n theme: \"dark\" | \"light\",\n): Promise<Copy> {\n if (templateId !== \"code-card\") {\n return copy;\n }\n const snippet = facts.release?.codeSnippet?.value;\n if (snippet === undefined) {\n return { ...copy, codeLines: emptyCodeLines() };\n }\n return { ...copy, codeLines: await highlightCode(snippet.code, snippet.lang, theme) };\n}\n","// fact() helper that attaches provenance\n// Spec: docs/PROJECT_PLAN.md §9.1\n\nimport type { Fact, SourceId } from \"./schema.js\";\n\nexport function fact<T>(\n value: T,\n provenance: { source: SourceId; ref: string; fetchedAt?: string },\n): Fact<T> {\n const fetchedAt = provenance.fetchedAt ?? new Date().toISOString();\n return {\n value,\n provenance: {\n source: provenance.source,\n ref: provenance.ref,\n fetchedAt,\n },\n };\n}\n","// Merge partial Facts from sources. Later sources fill holes.\n// Changelog feature lists replace git commit lists when present.\n// Spec: docs/PROJECT_PLAN.md §12\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { Facts } from \"./schema.js\";\nimport type { PartialFacts, PartialMetrics, PartialMilestone, PartialProject, PartialRelease } from \"./partial.js\";\n\nexport function mergeFacts(parts: PartialFacts[]): Facts {\n const project: PartialProject = {};\n const release: PartialRelease = {};\n const metrics: PartialMetrics = {};\n const milestone: PartialMilestone = {};\n let bench: Facts[\"bench\"];\n\n for (const part of parts) {\n fillObject(project, part.project);\n mergeRelease(release, part.release);\n fillObject(metrics, part.metrics);\n fillObject(milestone, part.milestone);\n if (part.bench !== undefined) {\n bench = part.bench;\n }\n }\n\n if (project.name === undefined) {\n throw new ShipsealError(\n \"facts.missing-name\",\n \"Could not determine the project name.\",\n \"Add a name field to package.json, or an H1 in README.md.\",\n );\n }\n\n const facts: Facts = {\n project: {\n name: project.name,\n },\n };\n if (project.tagline !== undefined) {\n facts.project.tagline = project.tagline;\n }\n if (project.url !== undefined) {\n facts.project.url = project.url;\n }\n if (project.repo !== undefined) {\n facts.project.repo = project.repo;\n }\n if (project.npmPackage !== undefined) {\n facts.project.npmPackage = project.npmPackage;\n }\n if (project.cli !== undefined) {\n facts.project.cli = project.cli;\n }\n if (project.license !== undefined) {\n facts.project.license = project.license;\n }\n\n // A partial release block is dropped, not fatal. `package.json#version` alone makes\n // `hasRelease` true on every project, so throwing here broke `bench` and `milestone`,\n // which do not need release facts at all (§6.3). The release event still errors, in\n // collectFacts, where the check knows the event kind.\n if (isCompleteRelease(release)) {\n facts.release = {\n version: release.version,\n tag: release.tag,\n date: release.date,\n features: release.features ?? [],\n fixes: release.fixes ?? [],\n breaking: release.breaking ?? [],\n };\n if (release.kind !== undefined) {\n facts.release.kind = release.kind;\n }\n if (release.headline !== undefined) {\n facts.release.headline = release.headline;\n }\n if (release.subheadline !== undefined) {\n facts.release.subheadline = release.subheadline;\n }\n if (release.previousVersion !== undefined) {\n facts.release.previousVersion = release.previousVersion;\n }\n if (release.commitCount !== undefined) {\n facts.release.commitCount = release.commitCount;\n }\n if (release.contributors !== undefined) {\n facts.release.contributors = release.contributors;\n }\n if (release.codeSnippet !== undefined) {\n facts.release.codeSnippet = release.codeSnippet;\n }\n }\n\n if (Object.keys(metrics).length > 0) {\n facts.metrics = metrics;\n }\n if (bench !== undefined) {\n facts.bench = bench;\n }\n if (milestone.metric !== undefined && milestone.threshold !== undefined) {\n facts.milestone = { metric: milestone.metric, threshold: milestone.threshold };\n }\n return facts;\n}\n\nfunction mergeRelease(target: PartialRelease, overlay: PartialRelease | undefined): void {\n if (overlay === undefined) {\n return;\n }\n fillObject(target, overlay, [\"features\", \"fixes\", \"breaking\"]);\n replaceList(target, overlay, \"features\");\n replaceList(target, overlay, \"fixes\");\n replaceList(target, overlay, \"breaking\");\n}\n\nfunction replaceList(\n target: PartialRelease,\n overlay: PartialRelease,\n key: \"features\" | \"fixes\" | \"breaking\",\n): void {\n const next = overlay[key];\n if (next !== undefined) {\n target[key] = next;\n }\n}\n\nfunction fillObject<T extends object>(target: T, overlay: T | undefined, skip: (keyof T)[] = []): void {\n if (overlay === undefined) {\n return;\n }\n const skipped = new Set(skip);\n for (const key of Object.keys(overlay) as (keyof T)[]) {\n if (skipped.has(key)) {\n continue;\n }\n const value = overlay[key];\n if (value !== undefined && target[key] === undefined) {\n target[key] = value;\n }\n }\n}\n\nfunction isCompleteRelease(\n release: PartialRelease,\n): release is PartialRelease &\n Required<Pick<PartialRelease, \"version\" | \"tag\" | \"date\">> {\n return release.version !== undefined && release.tag !== undefined && release.date !== undefined;\n}\n","// Benchmark JSON reader\n// Spec: docs/PROJECT_PLAN.md §12.7\n\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\n\nconst metricSchema = z.object({\n label: z.string().min(1),\n before: z.number().finite(),\n after: z.number().finite(),\n unit: z.string().min(1),\n better: z.enum([\"lower\", \"higher\"]),\n});\n\nconst benchFileSchema = z.object({\n title: z.string().min(1),\n metrics: z.array(metricSchema).min(1).max(3),\n note: z.string().optional(),\n});\n\nexport async function collectBenchFile(cwd: string, filePath = \".shipseal/bench.json\"): Promise<PartialFacts> {\n const resolved = isAbsolute(filePath) ? filePath : join(cwd, filePath);\n let raw: string;\n try {\n raw = await readFile(resolved, \"utf8\");\n } catch (error) {\n throw new ShipsealError(\n \"bench.missing-file\",\n `Benchmark file not found: ${filePath}.`,\n \"Write .shipseal/bench.json (title, metrics with before/after/unit/better), or pass --file <path>.\",\n { cause: error },\n );\n }\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (error) {\n throw new ShipsealError(\n \"bench.invalid-json\",\n `Benchmark file is not valid JSON: ${filePath}.`,\n \"Fix the JSON syntax, then retry.\",\n { cause: error },\n );\n }\n const parsed = benchFileSchema.safeParse(json);\n if (!parsed.success) {\n throw new ShipsealError(\n \"bench.invalid-shape\",\n `Benchmark file is missing required fields: ${filePath}.`,\n 'Each metric needs label, before, after, unit, and better (\"lower\" or \"higher\"). At most 3 metrics.',\n );\n }\n const fetchedAt = new Date().toISOString();\n const ref = filePath;\n const bench: NonNullable<Facts[\"bench\"]> = {\n title: fact(parsed.data.title, { source: \"bench-file\", ref: `${ref}#title`, fetchedAt }),\n metrics: parsed.data.metrics.map((metric, index) => ({\n label: fact(metric.label, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].label`, fetchedAt }),\n before: fact(metric.before, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].before`, fetchedAt }),\n after: fact(metric.after, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].after`, fetchedAt }),\n unit: fact(metric.unit, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].unit`, fetchedAt }),\n better: fact(metric.better, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].better`, fetchedAt }),\n })),\n };\n if (parsed.data.note !== undefined) {\n bench.note = fact(parsed.data.note, { source: \"bench-file\", ref: `${ref}#note`, fetchedAt });\n }\n return { bench };\n}\n","// README source: title, tagline, first fenced code block\n// Spec: docs/PROJECT_PLAN.md §12.3\n\nimport { readFile } from \"node:fs/promises\";\nimport { extname, join } from \"node:path\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nexport async function collectReadme(cwd: string): Promise<PartialFacts> {\n let markdown: string;\n try {\n markdown = await readFile(join(cwd, \"README.md\"), \"utf8\");\n } catch {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const out: PartialFacts = {};\n const h1 = extractH1(markdown);\n const tagline = extractTagline(markdown);\n const snippet = extractFirstCodeFence(markdown);\n\n const project: PartialProject = {};\n if (h1 !== undefined) {\n project.name = fact(h1, { source: \"readme\", ref: \"README.md H1\", fetchedAt });\n }\n if (tagline !== undefined) {\n project.tagline = fact(stripEmoji(tagline), {\n source: \"readme\",\n ref: \"README.md first paragraph\",\n fetchedAt,\n });\n }\n if (project.name !== undefined || project.tagline !== undefined) {\n out.project = project;\n }\n if (snippet !== undefined) {\n out.release = {\n codeSnippet: fact(snippet, {\n source: \"readme\",\n ref: \"README.md first fenced code block\",\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nexport async function collectConfiguredSnippet(\n cwd: string,\n spec: string,\n): Promise<PartialFacts> {\n const parsed = parseSnippetSpec(spec);\n if (parsed === undefined) {\n return {};\n }\n let contents: string;\n try {\n contents = await readFile(join(cwd, parsed.path), \"utf8\");\n } catch {\n return {};\n }\n const lines = contents.split(/\\r?\\n/);\n const slice = lines.slice(parsed.start - 1, parsed.end).join(\"\\n\");\n const fetchedAt = new Date().toISOString();\n return {\n release: {\n codeSnippet: fact(\n { code: slice, lang: langFromPath(parsed.path) },\n { source: \"user-config\", ref: spec, fetchedAt },\n ),\n },\n };\n}\n\n/**\n * Strip fenced code and HTML before reading prose out of a README.\n *\n * Skipping blocks that merely *start* with a fence is not enough. A `#` comment inside a YAML\n * example reads as a markdown H1, and a blank line inside a fence makes its body look like a\n * paragraph. Shipseal's own README hit both: the detected name became\n * \".github/workflows/shipseal.yml\" and the tagline became a chunk of workflow YAML.\n */\nfunction stripNonProse(markdown: string): string {\n return markdown\n .replace(/```[\\s\\S]*?```/g, \"\")\n .replace(/~~~[\\s\\S]*?~~~/g, \"\")\n .replace(/<[^>]+>/g, \"\");\n}\n\nexport function extractH1(markdown: string): string | undefined {\n const match = /^#\\s+(.+)$/m.exec(stripNonProse(markdown));\n const heading = match?.[1];\n if (heading === undefined) {\n return undefined;\n }\n return heading.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\").trim();\n}\n\nexport function extractTagline(markdown: string): string | undefined {\n const prose = stripNonProse(markdown);\n const h1 = /^#\\s+.+$/m.exec(prose);\n const start = h1 === null ? 0 : (h1.index ?? 0) + h1[0].length;\n for (const block of prose.slice(start).split(/\\n\\s*\\n/)) {\n const cleaned = stripBadges(block).trim();\n if (cleaned.length >= 20 && !cleaned.startsWith(\"#\") && !cleaned.startsWith(\"```\")) {\n return cleaned;\n }\n }\n return undefined;\n}\n\nexport function extractFirstCodeFence(markdown: string): { code: string; lang: string } | undefined {\n const match = /```([a-zA-Z0-9+-]+)\\n([\\s\\S]*?)```/.exec(markdown);\n if (match === null || match[1] === undefined || match[2] === undefined) {\n return undefined;\n }\n return { lang: match[1], code: match[2].replace(/\\n$/, \"\") };\n}\n\nfunction parseSnippetSpec(spec: string): { path: string; start: number; end: number } | undefined {\n const match = /^(?<path>.+)#L(?<start>\\d+)(?:-L(?<end>\\d+))?$/.exec(spec);\n if (match === null || match.groups === undefined) {\n return undefined;\n }\n const path = match.groups.path;\n const start = Number.parseInt(match.groups.start ?? \"0\", 10);\n const end = Number.parseInt(match.groups.end ?? match.groups.start ?? \"0\", 10);\n if (path === undefined || start < 1 || end < start) {\n return undefined;\n }\n return { path, start, end };\n}\n\nfunction langFromPath(path: string): string {\n const ext = extname(path).replace(\".\", \"\");\n if (ext === \"ts\") {\n return \"ts\";\n }\n if (ext === \"tsx\") {\n return \"tsx\";\n }\n if (ext === \"js\" || ext === \"mjs\" || ext === \"cjs\") {\n return \"js\";\n }\n if (ext === \"jsx\") {\n return \"jsx\";\n }\n return ext.length > 0 ? ext : \"text\";\n}\n\nfunction stripBadges(text: string): string {\n return text\n .replace(/\\[!\\[[^\\]]*]\\([^)]+\\)]\\([^)]+\\)/g, \"\")\n .replace(/!\\[[^\\]]*]\\([^)]+\\)/g, \"\")\n .replace(/<img[^>]*>/gi, \"\")\n .replace(/<[^>]+>/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n","// One cleaner for every line that becomes card text, whatever source it came from.\n//\n// There used to be two. `cleanChangelogItem` stripped fourteen patterns for the CLI path and\n// `cleanBullet` stripped five for the browser demo, so a GitHub release body kept the things a\n// CHANGELOG entry had removed. oven-sh/bun rendered a card headlined \"@dylan-conway\", a\n// contributor's handle, and astral-sh/ruff kept backslash-escaped brackets. Same input shape,\n// two different answers, because the rules lived in two places.\n\n/** Markdown escapes a maintainer never meant to see rendered: \\[ruff\\] becomes [ruff]. */\nconst MARKDOWN_ESCAPE = /\\\\([[\\]()*_`~#+\\-.!])/g;\n\nexport function cleanReleaseLine(item: string): string {\n return (\n item\n .replace(/^\\s*[-*]\\s*/, \"\")\n // Commit and pull request references: a card is not an audit trail.\n .replace(/\\[`[a-f0-9]{7,40}`]\\([^)]+\\)/gi, \"\")\n .replace(/^[a-f0-9]{7,40}:\\s*/i, \"\")\n .replace(/\\(#\\d+\\)/g, \"\")\n .replace(/\\[#\\d+]\\([^)]+\\)/g, \"\")\n .replace(/#\\d+\\b/g, \"\")\n // Credit lines. These are why a handle became a headline.\n .replace(/Thanks\\s+\\[@[\\w-]+]\\([^)]+\\)!?\\s*-?\\s*/gi, \"\")\n .replace(/\\[@[\\w-]+]\\([^)]+\\)/g, \"\")\n .replace(/\\(@[\\w-]+\\)/g, \"\")\n .replace(/\\s+by\\s+@[\\w-]+/gi, \"\")\n .replace(/@[\\w-]+/g, \"\")\n .replace(/^Thanks\\s*!?\\s*-?\\s*/i, \"\")\n // Markdown: images dropped, links reduced to their text, HTML and emphasis removed.\n .replaceAll(/!\\[[^\\]]*\\]\\([^)]*\\)/g, \"\")\n .replaceAll(/\\[([^\\]]+)\\]\\([^)]*\\)/g, \"$1\")\n .replaceAll(/<[^>]*>/g, \"\")\n .replaceAll(MARKDOWN_ESCAPE, \"$1\")\n .replaceAll(/[*`]/g, \"\")\n .replace(/^\\s*[-*]\\s*/, \"\")\n // Whatever the removals left behind.\n .replace(/\\s*\\(\\s*\\)/g, \"\")\n .replace(/\\s+([,.;:])/g, \"$1\")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/[\\s,;:-]+$/, \"\")\n .replace(/\\.$/, \"\")\n );\n}\n","// Keep a Changelog + Changesets parsing\n// Spec: docs/PROJECT_PLAN.md §12.4\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { extractFirstCodeFence } from \"./readme.js\";\nimport { cleanReleaseLine } from \"./release-line.js\";\n\nexport async function collectChangelog(\n cwd: string,\n version: string | undefined,\n changelogPath = \"CHANGELOG.md\",\n): Promise<PartialFacts> {\n if (version === undefined) {\n return {};\n }\n let markdown: string;\n try {\n markdown = await readFile(join(cwd, changelogPath), \"utf8\");\n } catch {\n return {};\n }\n const section = findVersionSection(markdown, version);\n if (section === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const features: Fact<string>[] = [];\n const fixes: Fact<string>[] = [];\n const breaking: Fact<string>[] = [];\n\n for (const group of parseGroups(section.body)) {\n const bucket = bucketForHeading(group.heading);\n if (bucket === undefined) {\n continue;\n }\n for (const item of group.items) {\n const cleaned = cleanChangelogItem(item);\n if (cleaned.length === 0) {\n continue;\n }\n const entry = fact(cleaned, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading} ${group.heading}: ${item}`,\n fetchedAt,\n });\n if (bucket === \"features\") {\n features.push(entry);\n } else if (bucket === \"fixes\") {\n fixes.push(entry);\n } else {\n breaking.push(entry);\n }\n }\n }\n\n const out: PartialFacts = {\n release: {\n version: fact(version.replace(/^v/, \"\"), {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n tag: fact(version.startsWith(\"v\") ? version : `v${version}`, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n features,\n fixes,\n breaking,\n },\n };\n // An author can title their own release from inside the notes, where the words already live:\n // <!-- shipseal: headline \"Milestone cards are here\" -->\n // Deterministic copy can only reuse a changelog sentence, and those are written for\n // maintainers. This is the cheap way to write for an audience without turning on the LLM.\n for (const slot of [\"headline\", \"subheadline\"] as const) {\n const marker = new RegExp(`<!--\\\\s*shipseal:\\\\s*${slot}\\\\s+\"([^\"]+)\"\\\\s*-->`).exec(section.body);\n const text = marker?.[1]?.trim();\n if (text !== undefined && text.length > 0) {\n out.release = {\n ...out.release,\n [slot]: fact(text, {\n source: \"user-config\",\n ref: `${changelogPath} ${section.heading} shipseal:${slot} marker`,\n fetchedAt,\n }),\n };\n }\n }\n\n // A snippet from the release notes is about this release. The README's first fence is\n // usually the install command, which says nothing about what changed. Sits above the README\n // in the merge order and below an explicit `release.snippet`.\n const snippet = extractFirstCodeFence(section.body);\n if (snippet !== undefined) {\n out.release = {\n ...out.release,\n codeSnippet: fact(snippet, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading} first fenced code block`,\n fetchedAt,\n }),\n };\n }\n if (section.date !== undefined) {\n out.release = {\n ...out.release,\n date: fact(section.date, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nexport function findVersionSection(\n markdown: string,\n version: string,\n): { heading: string; body: string; date?: string } | undefined {\n const needle = version.replace(/^v/, \"\");\n const headingRe = /^##\\s+(.+)$/gm;\n const matches = [...markdown.matchAll(headingRe)];\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n if (match === undefined) {\n continue;\n }\n const heading = match[1];\n if (heading === undefined || !headingIncludesVersion(heading, needle)) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].length;\n const next = matches[index + 1];\n const end = next?.index ?? markdown.length;\n const date = extractDate(heading);\n const body = markdown.slice(start, end);\n if (date === undefined) {\n return { heading, body };\n }\n return { heading, body, date };\n }\n return undefined;\n}\n\nexport function cleanChangelogItem(item: string): string {\n return cleanReleaseLine(item);\n}\n\nfunction headingIncludesVersion(heading: string, version: string): boolean {\n const unwrapped = heading.replace(/[[\\]]/g, \" \");\n return new RegExp(`(?:^|\\\\s)v?${escapeRegExp(version)}(?:\\\\s|$)`).test(unwrapped);\n}\n\nfunction extractDate(heading: string): string | undefined {\n const match = /(\\d{4}-\\d{2}-\\d{2})/.exec(heading);\n return match?.[1];\n}\n\nfunction parseGroups(body: string): Array<{ heading: string; items: string[] }> {\n const groups: Array<{ heading: string; items: string[] }> = [];\n const headingRe = /^###\\s+(.+)$/gm;\n const matches = [...body.matchAll(headingRe)];\n if (matches.length === 0) {\n return [{ heading: \"Added\", items: listItems(body) }];\n }\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n if (match === undefined) {\n continue;\n }\n const heading = match[1];\n if (heading === undefined) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].length;\n const next = matches[index + 1];\n const end = next?.index ?? body.length;\n groups.push({ heading, items: listItems(body.slice(start, end)) });\n }\n return groups;\n}\n\nfunction listItems(block: string): string[] {\n const items: string[] = [];\n let current: string | undefined;\n for (const raw of block.split(\"\\n\")) {\n const trimmed = raw.trim();\n // Only an unindented bullet starts a new entry. A nested bullet belongs to the entry\n // above it: Changesets writes sub-lists inside one entry, and treating those as separate\n // highlights put a sentence fragment on a card with no context.\n const indented = /^\\s+/.test(raw);\n if (!indented && (trimmed.startsWith(\"- \") || trimmed.startsWith(\"* \"))) {\n if (current !== undefined) {\n items.push(current);\n }\n current = trimmed;\n continue;\n }\n if (current !== undefined && trimmed.length > 0 && !trimmed.startsWith(\"#\")) {\n current = `${current} ${trimmed}`;\n }\n }\n if (current !== undefined) {\n items.push(current);\n }\n return items;\n}\n\nfunction bucketForHeading(heading: string): \"features\" | \"fixes\" | \"breaking\" | undefined {\n const key = heading.trim().toLowerCase();\n if (\n key === \"added\" ||\n key === \"changed\" ||\n key === \"minor changes\" ||\n key === \"features\"\n ) {\n return \"features\";\n }\n if (key === \"fixed\" || key === \"patch changes\" || key === \"security\" || key === \"fixes\") {\n return \"fixes\";\n }\n if (\n key === \"removed\" ||\n key === \"major changes\" ||\n key === \"breaking\" ||\n key === \"breaking changes\"\n ) {\n return \"breaking\";\n }\n return undefined;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","// git source: tags, commits, contributors\n// Spec: docs/PROJECT_PLAN.md §12.1\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { cleanChangelogItem } from \"./changelog.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport async function collectGit(\n cwd: string,\n event: { tag?: string; previousTag?: string },\n): Promise<PartialFacts> {\n const inside = await git(cwd, [\"rev-parse\", \"--is-inside-work-tree\"]);\n if (inside !== \"true\") {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const tag = event.tag ?? (await gitCurrentTag(cwd));\n if (tag === undefined) {\n return {};\n }\n const exists = await git(cwd, [\"rev-parse\", \"--verify\", `${tag}^{commit}`]);\n if (exists === undefined) {\n return {};\n }\n const version = versionFromTag(tag);\n const tags = await gitLines(cwd, [\"tag\", \"--sort=-v:refname\"]);\n const tagIndex = tags.indexOf(tag);\n const previousTag =\n event.previousTag ?? (tagIndex >= 0 ? tags[tagIndex + 1] : tags.find((candidate) => candidate !== tag));\n const range = previousTag === undefined ? tag : `${previousTag}..${tag}`;\n const log = await git(cwd, [\"log\", range, \"--pretty=format:%s\\t%an\\t%ae\\t%h\\t%cI\"]);\n const commits = (log ?? \"\").split(\"\\n\").filter((line) => line.length > 0);\n const features: Fact<string>[] = [];\n const fixes: Fact<string>[] = [];\n const breaking: Fact<string>[] = [];\n const contributors = new Map<string, string>();\n\n for (const line of commits) {\n const [subject, author, email, hash] = line.split(\"\\t\");\n if (subject === undefined || hash === undefined) {\n continue;\n }\n const parsed = parseConventional(subject);\n const display = parsed.display;\n const ref = `git log ${range} ${hash}`;\n const item = fact(display, { source: \"git\", ref, fetchedAt });\n if (parsed.breaking) {\n breaking.push(item);\n } else if (parsed.type === \"feat\") {\n features.push(item);\n } else if (parsed.type === \"fix\" || parsed.type === \"perf\") {\n fixes.push(item);\n }\n if (email !== undefined && author !== undefined && !isBot(author, email)) {\n contributors.set(email, author);\n }\n }\n\n const dateLine = await git(cwd, [\"log\", \"-1\", \"--format=%cI\", tag]);\n const date = (dateLine ?? fetchedAt).slice(0, 10);\n const names = [...contributors.values()];\n\n const release: NonNullable<PartialFacts[\"release\"]> = {\n version: fact(version, { source: \"git\", ref: `git tag ${tag}`, fetchedAt }),\n tag: fact(tag, { source: \"git\", ref: `git tag ${tag}`, fetchedAt }),\n date: fact(date, { source: \"git\", ref: `git log -1 --format=%cI ${tag}`, fetchedAt }),\n features,\n fixes,\n breaking,\n commitCount: fact(commits.length, {\n source: \"git\",\n ref: `git rev-list --count ${range}`,\n fetchedAt,\n }),\n };\n if (previousTag !== undefined) {\n release.previousVersion = fact(versionFromTag(previousTag), {\n source: \"git\",\n ref: `git tag ${previousTag}`,\n fetchedAt,\n });\n const kind = releaseKind(versionFromTag(previousTag), versionFromTag(tag));\n if (kind !== undefined) {\n release.kind = fact(kind, {\n source: \"git\",\n ref: `semver ${previousTag}..${tag}`,\n fetchedAt,\n });\n }\n }\n if (names.length > 0) {\n release.contributors = fact(names, {\n source: \"git\",\n ref: `git log ${range} unique authors`,\n fetchedAt,\n });\n }\n return { release };\n}\n\nexport function parseConventional(subject: string): {\n type: string | undefined;\n display: string;\n breaking: boolean;\n} {\n const match = /^(?<type>\\w+)(?<scope>\\([^)]+\\))?(?<bang>!)?:\\s*(?<rest>.+)$/.exec(subject);\n if (match === null || match.groups === undefined) {\n return { type: undefined, display: displaySubject(subject), breaking: false };\n }\n const type = match.groups.type;\n const rest = match.groups.rest ?? subject;\n const breaking = match.groups.bang === \"!\" || /BREAKING CHANGE:/.test(subject);\n return { type, display: displaySubject(rest), breaking };\n}\n\nexport function versionFromTag(tag: string): string {\n const at = tag.lastIndexOf(\"@\");\n if (at >= 0 && at < tag.length - 1) {\n return tag.slice(at + 1).replace(/^v/, \"\");\n }\n return tag.replace(/^v/, \"\");\n}\n\nexport async function gitCurrentTag(cwd: string): Promise<string | undefined> {\n return git(cwd, [\"describe\", \"--tags\", \"--abbrev=0\"]);\n}\n\nasync function git(cwd: string, args: string[]): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { cwd });\n const trimmed = stdout.trim();\n return trimmed.length === 0 ? undefined : trimmed;\n } catch {\n return undefined;\n }\n}\n\nasync function gitLines(cwd: string, args: string[]): Promise<string[]> {\n const out = await git(cwd, args);\n return out === undefined ? [] : out.split(\"\\n\").filter((line) => line.length > 0);\n}\n\nfunction isBot(author: string, email: string): boolean {\n const haystack = `${author} ${email}`.toLowerCase();\n return (\n author.endsWith(\"[bot]\") ||\n haystack.includes(\"dependabot\") ||\n haystack.includes(\"renovate\") ||\n haystack.includes(\"github-actions\")\n );\n}\n\nfunction displaySubject(text: string): string {\n const cleaned = cleanChangelogItem(text);\n const first = cleaned.at(0);\n if (first === undefined) {\n return cleaned;\n }\n return first.toUpperCase() + cleaned.slice(1);\n}\n\n/**\n * Repository slug and URL from `git remote get-url origin`.\n *\n * Kept separate from `collectGit`, which returns nothing without a tag. A monorepo root\n * often has no `homepage` or `repository` in its private package.json, which left the call\n * to action falling back to the workspace name. The remote is always there.\n */\nexport async function collectGitRemote(cwd: string): Promise<PartialFacts> {\n const remote = await git(cwd, [\"remote\", \"get-url\", \"origin\"]);\n if (remote === undefined) {\n return {};\n }\n const slug = githubSlug(remote.trim());\n if (slug === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const provenance = { source: \"git\" as const, ref: \"git remote get-url origin\", fetchedAt };\n return {\n project: {\n repo: fact(slug, provenance),\n url: fact(`https://github.com/${slug}`, provenance),\n },\n };\n}\n\nfunction githubSlug(url: string): string | undefined {\n const cleaned = url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n return /github\\.com[/:]([^/]+\\/[^/]+)$/.exec(cleaned)?.[1];\n}\n\n/**\n * How significant is this release, by semver alone?\n *\n * Compared against the previous tag rather than read from a changelog heading, so it is a fact\n * with a reference someone can re-run. Returns undefined when either tag is not semver, or when\n * the two are equal: a caller should treat \"unknown\" as \"announce it\", never as \"skip it\".\n */\nexport function releaseKind(\n previous: string,\n current: string,\n): \"major\" | \"minor\" | \"patch\" | undefined {\n const before = parseSemver(previous);\n const after = parseSemver(current);\n if (before === undefined || after === undefined) {\n return undefined;\n }\n if (after[0] !== before[0]) {\n return \"major\";\n }\n if (after[1] !== before[1]) {\n return \"minor\";\n }\n return after[2] === before[2] ? undefined : \"patch\";\n}\n\nfunction parseSemver(value: string): [number, number, number] | undefined {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(value.replace(/^v/, \"\"));\n if (match === null) {\n return undefined;\n }\n return [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n","// GitHub REST via fetch (token optional)\n// Spec: docs/PROJECT_PLAN.md §12.5\n// Docs checked 2026-09-11: https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28\n// GET /repos/{owner}/{repo}\n// GET /repos/{owner}/{repo}/releases/tags/{tag}\n// GET /repos/{owner}/{repo}/contributors\n// Headers: Accept application/vnd.github+json, X-GitHub-Api-Version 2022-11-28\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nconst API_VERSION = \"2022-11-28\";\nconst API_ROOT = \"https://api.github.com\";\n\nconst repoSchema = z.object({\n stargazers_count: z.number().int().nonnegative(),\n description: z.string().nullable().optional(),\n homepage: z.string().nullable().optional(),\n license: z.object({ spdx_id: z.string().nullable() }).nullable().optional(),\n});\n\nconst releaseSchema = z.object({\n body: z.string().nullable().optional(),\n});\n\nconst contributorsSchema = z.array(z.unknown());\n\nexport interface GithubCacheEntry {\n json: unknown;\n link: string | null;\n}\n\nexport interface GithubCollectOptions {\n repo: string;\n tag?: string;\n token?: string;\n fetchImpl?: typeof fetch;\n cache?: Map<string, GithubCacheEntry>;\n}\n\nexport async function collectGithub(options: GithubCollectOptions): Promise<PartialFacts> {\n const slug = parseRepo(options.repo);\n if (slug === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const fetchImpl = options.fetchImpl ?? fetch;\n const cache = options.cache ?? new Map<string, GithubCacheEntry>();\n const repoResponse = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}`,\n options.token,\n fetchImpl,\n cache,\n );\n if (repoResponse === undefined) {\n return {};\n }\n const repo = repoSchema.parse(repoResponse.json);\n const out: PartialFacts = {\n metrics: {\n stars: fact(repo.stargazers_count, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} stargazers_count`,\n fetchedAt,\n }),\n },\n project: {},\n };\n if (repo.description !== undefined && repo.description !== null && repo.description.length > 0) {\n out.project = {\n ...out.project,\n tagline: fact(stripEmoji(repo.description), {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} description`,\n fetchedAt,\n }),\n };\n }\n if (repo.homepage !== undefined && repo.homepage !== null && repo.homepage.length > 0) {\n out.project = {\n ...out.project,\n url: fact(repo.homepage, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} homepage`,\n fetchedAt,\n }),\n };\n }\n const license = repo.license?.spdx_id;\n if (license !== undefined && license !== null && license !== \"NOASSERTION\") {\n out.project = {\n ...out.project,\n license: fact(license, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} license.spdx_id`,\n fetchedAt,\n }),\n };\n }\n\n if (options.tag !== undefined) {\n const releaseResponse = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}/releases/tags/${encodeURIComponent(options.tag)}`,\n options.token,\n fetchImpl,\n cache,\n { notFoundOk: true },\n );\n if (releaseResponse !== undefined) {\n const release = releaseSchema.parse(releaseResponse.json);\n const features = featuresFromReleaseBody(release.body ?? \"\", options.tag, fetchedAt);\n if (features.length > 0) {\n out.release = { features };\n }\n }\n }\n\n const contributors = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}/contributors?per_page=1&anon=true`,\n options.token,\n fetchImpl,\n cache,\n { notFoundOk: true },\n );\n if (contributors !== undefined) {\n contributorsSchema.parse(contributors.json);\n const listed = Array.isArray(contributors.json) ? contributors.json.length : 0;\n const fromLink = lastPageFromLink(contributors.link);\n out.metrics = {\n ...out.metrics,\n contributorCount: fact(fromLink ?? listed, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo}/contributors`,\n fetchedAt,\n }),\n };\n }\n\n return out;\n}\n\nexport function parseRepo(value: string): { owner: string; repo: string } | undefined {\n const trimmed = value.trim().replace(/\\.git$/, \"\");\n const match = /^(?:https?:\\/\\/github\\.com\\/)?([A-Za-z0-9_.-]+)\\/([A-Za-z0-9_.-]+)$/.exec(trimmed);\n if (match === null || match[1] === undefined || match[2] === undefined) {\n return undefined;\n }\n return { owner: match[1], repo: match[2] };\n}\n\nfunction featuresFromReleaseBody(body: string, tag: string, fetchedAt: string): Fact<string>[] {\n const lines = body\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*[-*]\\s*/, \"\").trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n return lines.slice(0, 8).map((line) =>\n fact(line.replace(/\\.$/, \"\"), {\n source: \"github-api\",\n ref: `GET /repos/.../releases/tags/${tag} body`,\n fetchedAt,\n }),\n );\n}\n\nasync function githubGet(\n url: string,\n token: string | undefined,\n fetchImpl: typeof fetch,\n cache: Map<string, GithubCacheEntry>,\n opts: { notFoundOk?: boolean } = {},\n): Promise<GithubCacheEntry | undefined> {\n const cached = cache.get(url);\n if (cached !== undefined) {\n return cached;\n }\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": API_VERSION,\n \"User-Agent\": \"shipseal\",\n };\n if (token !== undefined && token.length > 0) {\n headers.Authorization = `Bearer ${token}`;\n }\n let response: Response;\n try {\n response = await fetchImpl(url, { headers });\n } catch (error) {\n throw new ShipsealError(\n \"github.network\",\n \"Could not reach the GitHub API.\",\n \"Check network access, then retry. Unauthenticated calls are optional; facts still come from git and package.json.\",\n { cause: error },\n );\n }\n if (response.status === 404 && opts.notFoundOk === true) {\n return undefined;\n }\n if (response.status === 403 || response.status === 429) {\n throw new ShipsealError(\n \"github.rate-limit\",\n \"GitHub API rate limit exceeded.\",\n \"Set GITHUB_TOKEN in the environment to raise the limit, then retry.\",\n );\n }\n if (!response.ok) {\n throw new ShipsealError(\n \"github.http\",\n `GitHub API returned HTTP ${String(response.status)} for ${url}.`,\n \"Confirm the repository exists and GITHUB_TOKEN can read it.\",\n );\n }\n const json: unknown = await response.json();\n const entry: GithubCacheEntry = { json, link: response.headers.get(\"link\") };\n cache.set(url, entry);\n return entry;\n}\n\nfunction lastPageFromLink(link: string | null): number | undefined {\n if (link === null) {\n return undefined;\n }\n const match = /[?&]page=(\\d+)>;\\s*rel=\"last\"/.exec(link);\n if (match === null || match[1] === undefined) {\n return undefined;\n }\n return Number.parseInt(match[1], 10);\n}\n","// npm weekly downloads\n// Spec: docs/PROJECT_PLAN.md §12.6\n// Docs checked 2026-09-11: https://github.com/npm/registry/blob/main/docs/download-counts.md\n// GET https://api.npmjs.org/downloads/point/{period}/{package}\n// period last-week. Scoped names are URL-encoded (@scope/pkg -> %40scope%2Fpkg).\n// 404 means the package is unpublished or unknown: return nothing.\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\n\nconst API_ROOT = \"https://api.npmjs.org/downloads/point/last-week\";\nconst REGISTRY_ROOT = \"https://registry.npmjs.org\";\n\nconst pointSchema = z.object({\n downloads: z.number().int().nonnegative(),\n start: z.string().optional(),\n end: z.string().optional(),\n package: z.string().optional(),\n});\n\nexport interface NpmCollectOptions {\n npmPackage: string;\n fetchImpl?: typeof fetch;\n cache?: Map<string, unknown>;\n}\n\nexport async function collectNpm(options: NpmCollectOptions): Promise<PartialFacts> {\n const name = options.npmPackage.trim();\n if (name.length === 0) {\n return {};\n }\n const url = `${API_ROOT}/${encodeURIComponent(name)}`;\n const cache = options.cache ?? new Map<string, unknown>();\n const cached = cache.get(url);\n const json = cached ?? (await npmGet(url, options.fetchImpl ?? fetch, cache));\n if (json === undefined) {\n return {};\n }\n const point = pointSchema.parse(json);\n return {\n metrics: {\n weeklyDownloads: fact(point.downloads, {\n source: \"npm-api\",\n ref: `GET /downloads/point/last-week/${name} downloads`,\n fetchedAt: new Date().toISOString(),\n }),\n },\n };\n}\n\nasync function npmGet(\n url: string,\n fetchImpl: typeof fetch,\n cache: Map<string, unknown>,\n): Promise<unknown | undefined> {\n let response: Response;\n try {\n response = await fetchImpl(url, { headers: { Accept: \"application/json\", \"User-Agent\": \"shipseal\" } });\n } catch (error) {\n throw new ShipsealError(\n \"npm.network\",\n \"Could not reach the npm downloads API.\",\n \"Check network access, then retry. Weekly downloads are optional; other facts still render.\",\n { cause: error },\n );\n }\n if (response.status === 404) {\n return undefined;\n }\n if (response.status === 403 || response.status === 429) {\n throw new ShipsealError(\n \"npm.rate-limit\",\n \"npm downloads API rate limit exceeded.\",\n \"Wait and retry. Milestone cards can still use stars and contributors without downloads.\",\n );\n }\n if (!response.ok) {\n throw new ShipsealError(\n \"npm.http\",\n `npm downloads API returned HTTP ${String(response.status)} for ${url}.`,\n \"Confirm the package name in package.json is published on npm.\",\n );\n }\n const json: unknown = await response.json();\n cache.set(url, json);\n return json;\n}\n\n/**\n * Is this name actually published?\n *\n * The downloads endpoint cannot answer this: it 404s for a package published minutes ago that\n * has no download data yet, which is exactly the case a first release is in. The registry\n * document is the authority.\n *\n * Only a definitive 404 counts as \"no\". A network error, a rate limit or anything else returns\n * undefined, so an unreachable registry never removes a call to action that was probably right.\n */\nexport async function npmPackageExists(\n name: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean | undefined> {\n const trimmed = name.trim();\n if (trimmed.length === 0) {\n return false;\n }\n let response: Response;\n try {\n response = await fetchImpl(`${REGISTRY_ROOT}/${encodeURIComponent(trimmed)}`, {\n method: \"HEAD\",\n headers: { accept: \"application/json\" },\n });\n } catch {\n return undefined;\n }\n if (response.status === 404) {\n return false;\n }\n return response.ok ? true : undefined;\n}\n","// package.json source\n// Spec: docs/PROJECT_PLAN.md §12.2\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nconst pkgSchema = z.object({\n private: z.boolean().optional(),\n name: z.string().optional(),\n bin: z.union([z.string(), z.record(z.string(), z.string())]).optional(),\n description: z.string().optional(),\n version: z.string().optional(),\n homepage: z.string().optional(),\n license: z.string().optional(),\n repository: z.union([z.string(), z.object({ url: z.string().optional() })]).optional(),\n});\n\nexport async function collectPackageJson(\n cwd: string,\n packagePath = \"package.json\",\n): Promise<PartialFacts> {\n const path = join(cwd, packagePath);\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return {};\n }\n const pkg = pkgSchema.safeParse(parsed);\n if (!pkg.success) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n // A private package.json is a workspace root and its name is plumbing, not a brand. Using\n // it put \"shipseal-monorepo 0.0.5\" on a real hero card. Fall back to the directory, and let\n // a README heading or the git remote win if either has something better.\n const rawName = pkg.data.private === true ? undefined : pkg.data.name;\n const project: PartialProject = {\n name: fact(stripScope(rawName ?? basenameFromPath(cwd)), {\n source: \"package-json\",\n ref: rawName === undefined ? `${packagePath} directory name` : `${packagePath}#name`,\n fetchedAt,\n }),\n };\n if (pkg.data.description !== undefined && pkg.data.description.length > 0) {\n project.tagline = fact(stripEmoji(pkg.data.description), {\n source: \"package-json\",\n ref: `${packagePath}#description`,\n fetchedAt,\n });\n }\n const url = pkg.data.homepage ?? repositoryUrl(pkg.data.repository);\n if (url !== undefined) {\n project.url = fact(url, {\n source: \"package-json\",\n ref: pkg.data.homepage !== undefined ? `${packagePath}#homepage` : `${packagePath}#repository`,\n fetchedAt,\n });\n }\n const repo = repoSlug(pkg.data.repository);\n if (repo !== undefined) {\n project.repo = fact(repo, {\n source: \"package-json\",\n ref: `${packagePath}#repository`,\n fetchedAt,\n });\n }\n // A private package is never on npm. Taking its name put \"npm i shipseal-monorepo\" on a\n // real release card, telling people to install a package that does not exist.\n if (pkg.data.name !== undefined && pkg.data.private !== true) {\n project.npmPackage = fact(pkg.data.name, {\n source: \"package-json\",\n ref: `${packagePath}#name`,\n fetchedAt,\n });\n }\n // A package with a bin is run, not imported. \"npm i shipseal\" told people to install a CLI\n // as a dependency, which is not how any of the docs say to use it.\n if (pkg.data.bin !== undefined && pkg.data.private !== true) {\n project.cli = fact(true, {\n source: \"package-json\",\n ref: `${packagePath}#bin`,\n fetchedAt,\n });\n }\n if (pkg.data.license !== undefined) {\n project.license = fact(pkg.data.license, {\n source: \"package-json\",\n ref: `${packagePath}#license`,\n fetchedAt,\n });\n }\n\n const out: PartialFacts = { project };\n if (pkg.data.version !== undefined) {\n out.release = {\n version: fact(pkg.data.version.replace(/^v/, \"\"), {\n source: \"package-json\",\n ref: `${packagePath}#version`,\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nfunction stripScope(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1] ?? name;\n}\n\nfunction basenameFromPath(cwd: string): string {\n const parts = cwd.split(/[/\\\\]/).filter((part) => part.length > 0);\n return parts[parts.length - 1] ?? \"project\";\n}\n\nfunction repositoryUrl(repository: z.infer<typeof pkgSchema>[\"repository\"]): string | undefined {\n if (typeof repository === \"string\") {\n return normalizeGitUrl(repository);\n }\n if (repository?.url !== undefined) {\n return normalizeGitUrl(repository.url);\n }\n return undefined;\n}\n\nfunction repoSlug(repository: z.infer<typeof pkgSchema>[\"repository\"]): string | undefined {\n const url = repositoryUrl(repository);\n if (url === undefined) {\n return undefined;\n }\n const match = /github\\.com[/:]([^/]+\\/[^/]+)$/.exec(url.replace(/\\.git$/, \"\"));\n return match?.[1];\n}\n\n// npm allows shorthand repository strings: \"owner/repo\", \"github:owner/repo\",\n// and the other hosts' prefixes. Expand the GitHub ones so repoSlug and the\n// GitHub source see a real URL. Without this, `milestone` could not read stars\n// for any project using the shorthand, which is the most common form.\nconst SHORTHAND = /^(?:github:)?([\\w.-]+\\/[\\w.-]+)$/;\n\nfunction normalizeGitUrl(url: string): string {\n const shorthand = SHORTHAND.exec(url);\n if (shorthand?.[1] !== undefined) {\n return `https://github.com/${shorthand[1].replace(/\\.git$/, \"\")}`;\n }\n const ssh = /^git@([^:]+):(.+)$/.exec(url);\n if (ssh !== null && ssh[1] !== undefined && ssh[2] !== undefined) {\n return `https://${ssh[1]}/${ssh[2].replace(/\\.git$/, \"\")}`;\n }\n return url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n}\n","// Orchestrate collectors into one Facts object\n// Spec: docs/PROJECT_PLAN.md §12\n\nimport { readdir } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport { mergeFacts } from \"../facts/merge.js\";\nimport type { Fact, Facts } from \"../facts/schema.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { collectBenchFile } from \"./bench-file.js\";\nimport { collectChangelog } from \"./changelog.js\";\nimport { collectGit, collectGitRemote, versionFromTag } from \"./git.js\";\nimport { collectGithub } from \"./github.js\";\nimport { collectNpm, npmPackageExists } from \"./npm.js\";\nimport { collectPackageJson } from \"./package-json.js\";\nimport { collectConfiguredSnippet, collectReadme } from \"./readme.js\";\n\nexport interface CollectOptions {\n cwd: string;\n event: ShipsealEvent;\n packagePath?: string;\n changelogPath?: string;\n snippet?: string | null;\n headline?: string | undefined;\n subheadline?: string | undefined;\n benchFile?: string;\n githubToken?: string;\n fetchImpl?: typeof fetch;\n skipNetwork?: boolean;\n}\n\nexport async function collectFacts(options: CollectOptions): Promise<Facts> {\n const pkg = await collectPackageJson(options.cwd, options.packagePath ?? \"package.json\");\n const tag = options.event.kind === \"release\" ? options.event.tag : undefined;\n const previousTag = options.event.kind === \"release\" ? options.event.previousTag : undefined;\n const gitEvent: { tag?: string; previousTag?: string } = {};\n if (tag !== undefined) {\n gitEvent.tag = tag;\n }\n if (previousTag !== undefined) {\n gitEvent.previousTag = previousTag;\n }\n const git = await collectGit(options.cwd, gitEvent);\n const version =\n git.release?.version?.value ??\n pkg.release?.version?.value ??\n (tag === undefined ? undefined : versionFromTag(tag));\n const remote = await collectGitRemote(options.cwd);\n const changelog = await collectBestChangelog(\n options.cwd,\n version,\n options.changelogPath ?? \"CHANGELOG.md\",\n options.packagePath,\n );\n const readme = await collectReadme(options.cwd);\n const snippet =\n options.snippet !== undefined && options.snippet !== null && options.snippet.length > 0\n ? await collectConfiguredSnippet(options.cwd, options.snippet)\n : {};\n\n // A private workspace root has no npm name, so the CTA fell back to the GitHub URL even\n // when the repo publishes a package one directory down. Sits before `pkg` so an explicit\n // root name, or one from --package, still wins.\n const workspacePkg =\n pkg.project?.npmPackage === undefined\n ? // Verify what was inferred, trust what was declared. A root name, or one from\n // --package, is the user saying so; this one is a guess worth checking.\n await collectWorkspaceNpmPackage(\n options.cwd,\n options.skipNetwork === true\n ? {}\n : { verify: async (name) => npmPackageExists(name, options.fetchImpl ?? fetch) },\n )\n : {};\n\n // A headline passed on the command line or set in config outranks the changelog marker,\n // which outranks anything deterministic copy would compose. Recorded as a fact either way,\n // so the manifest says the words were chosen rather than derived.\n const overrides: PartialFacts = {};\n for (const slot of [\"headline\", \"subheadline\"] as const) {\n const text = options[slot]?.trim();\n if (text !== undefined && text.length > 0) {\n overrides.release = {\n ...overrides.release,\n [slot]: fact(text, {\n source: \"user-config\",\n ref: `--${slot} or release.${slot}`,\n fetchedAt: new Date().toISOString(),\n }),\n };\n }\n }\n\n // mergeFacts fills holes, so the first source to supply a fact wins. Declared beats derived\n // throughout: package.json is the author saying so, the git remote is whatever this clone\n // happens to point at, which may be a fork, a mirror or an SSH alias.\n //\n // `remote` used to sit first, with a comment claiming that let an explicit package.json\n // homepage or repository win. It did the opposite, because first wins rather than last.\n //\n // Snippet order is explicit, then release notes, then README: a configured `release.snippet`\n // is the user saying so, a fence in the release notes is about this release, and the README's\n // first fence is usually just the install command. `snippet` used to sit last, which meant a\n // configured snippet was silently ignored whenever the README had any code block at all.\n const parts: PartialFacts[] = [overrides, pkg, workspacePkg, remote, git, snippet, changelog, readme];\n\n if (options.event.kind === \"bench\") {\n parts.push(await collectBenchFile(options.cwd, options.benchFile ?? \".shipseal/bench.json\"));\n }\n\n if (options.skipNetwork !== true) {\n const repo = pkg.project?.repo?.value ?? gitRepoFromParts(pkg, readme);\n if (repo !== undefined) {\n const githubOpts: Parameters<typeof collectGithub>[0] = { repo };\n const githubTag = git.release?.tag?.value ?? tag;\n if (githubTag !== undefined) {\n githubOpts.tag = githubTag;\n }\n if (options.githubToken !== undefined) {\n githubOpts.token = options.githubToken;\n }\n if (options.fetchImpl !== undefined) {\n githubOpts.fetchImpl = options.fetchImpl;\n }\n const github = await collectGithub(githubOpts);\n const githubWithoutFeatures: PartialFacts = {};\n if (github.project !== undefined) {\n githubWithoutFeatures.project = github.project;\n }\n if (github.metrics !== undefined) {\n githubWithoutFeatures.metrics = github.metrics;\n }\n parts.push(githubWithoutFeatures);\n const mergedPreview = mergeFacts(parts);\n if (\n options.event.kind === \"release\" &&\n (mergedPreview.release?.features.length ?? 0) === 0 &&\n github.release?.features !== undefined &&\n github.release.features.length > 0\n ) {\n parts.push({ release: { features: github.release.features } });\n }\n }\n const npmPackage = pkg.project?.npmPackage?.value;\n if (npmPackage !== undefined) {\n const npmOpts: Parameters<typeof collectNpm>[0] = { npmPackage };\n if (options.fetchImpl !== undefined) {\n npmOpts.fetchImpl = options.fetchImpl;\n }\n parts.push(await collectNpm(npmOpts));\n }\n }\n\n const facts = mergeFacts(parts);\n if (options.event.kind === \"release\" && facts.release === undefined) {\n throw new ShipsealError(\n \"facts.missing-release\",\n \"Could not collect release facts.\",\n \"Create a git tag, pass --tag, or add a matching version section to CHANGELOG.md.\",\n );\n }\n return facts;\n}\n\nasync function collectBestChangelog(\n cwd: string,\n version: string | undefined,\n changelogPath: string,\n packagePath: string | undefined,\n): Promise<PartialFacts> {\n const paths = [changelogPath];\n if (packagePath !== undefined) {\n const sibling = join(dirname(packagePath), \"CHANGELOG.md\");\n if (!paths.includes(sibling)) {\n paths.push(sibling);\n }\n }\n const collected = await Promise.all(paths.map((path) => collectChangelog(cwd, version, path)));\n const found = collected.find((facts) => changelogHasNotes(facts));\n if (found !== undefined) {\n return found;\n }\n\n // Monorepos keep the changelog beside the package, not at the repo root, and Changesets\n // writes it there. Without this, `release` on a workspace root silently fell back to raw\n // commit subjects even though a perfectly good changelog existed one directory down.\n const candidates = await workspaceChangelogs(cwd);\n const fromWorkspace = await Promise.all(\n candidates.map((candidate) => collectChangelog(cwd, version, candidate)),\n );\n return fromWorkspace.find((facts) => changelogHasNotes(facts)) ?? {};\n}\n\n/**\n * Find the one publishable package in a workspace.\n *\n * Only when there is exactly one candidate: two publishable packages make the CTA a guess, and\n * guessing which one to tell people to install is worse than falling back to the repository\n * URL. `--package` resolves the ambiguity explicitly.\n */\nasync function collectWorkspaceNpmPackage(\n cwd: string,\n options: { verify?: (name: string) => Promise<boolean | undefined> } = {},\n): Promise<PartialFacts> {\n const paths = await workspaceManifests(cwd);\n const manifests = await Promise.all(paths.map((path) => collectPackageJson(cwd, path)));\n const found = manifests\n .map((facts, index) => ({\n name: facts.project?.npmPackage?.value,\n cli: facts.project?.cli,\n path: paths[index] ?? \"\",\n }))\n .filter(\n (entry): entry is { name: string; cli: Fact<boolean> | undefined; path: string } =>\n entry.name !== undefined,\n );\n const only = found.length === 1 ? found[0] : undefined;\n if (only === undefined) {\n return {};\n }\n if (options.verify !== undefined && (await options.verify(only.name)) === false) {\n // Declared public but never published. \"npm i <name>\" would fail for every reader, so\n // leave npmPackage unset and let the call to action fall back to the repository URL.\n return {};\n }\n const project: PartialProject = {\n npmPackage: fact(only.name, {\n source: \"package-json\",\n ref: `${only.path}#name`,\n fetchedAt: new Date().toISOString(),\n }),\n };\n if (only.cli !== undefined) {\n project.cli = only.cli;\n }\n return { project };\n}\n\nasync function workspaceManifests(cwd: string): Promise<string[]> {\n return (await workspaceChangelogs(cwd)).map((path) =>\n path.replace(/CHANGELOG\\.md$/, \"package.json\"),\n );\n}\n\nasync function workspaceChangelogs(cwd: string): Promise<string[]> {\n const roots = [\"packages\", \"apps\"];\n const listings = await Promise.all(\n roots.map(async (root) => {\n let entries: Dirent[];\n try {\n entries = await readdir(join(cwd, root), { withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(root, entry.name, \"CHANGELOG.md\"));\n }),\n );\n return listings.flat().toSorted();\n}\n\nfunction changelogHasNotes(facts: PartialFacts): boolean {\n const release = facts.release;\n if (release === undefined) {\n return false;\n }\n return (\n (release.features?.length ?? 0) > 0 ||\n (release.fixes?.length ?? 0) > 0 ||\n (release.breaking?.length ?? 0) > 0\n );\n}\n\nfunction gitRepoFromParts(pkg: PartialFacts, readme: PartialFacts): string | undefined {\n return pkg.project?.repo?.value ?? pkg.project?.url?.value ?? readme.project?.url?.value;\n}\n","// ONLY file allowed to import Takumi (Rule R4). Verify API first (spike S1)\n// Spec: docs/PROJECT_PLAN.md §16\n// Docs checked 2026-09-11: https://takumi.kane.tw/docs , /docs/measure-api, /docs/typography-and-fonts, /docs/helpers\n//\n// This file must stay free of `node:` imports. The browser demo (/try) imports the renderer\n// through here, and one top-level Node builtin is enough for Vite to externalize the module,\n// throw on load, and leave the page blank. Disk access lives in `takumi-node.ts`.\n\nimport { Renderer, type Node } from \"takumi-js/node\";\nimport { container, text as textNode } from \"takumi-js/helpers\";\nimport { fromJsx as takumiFromJsx } from \"takumi-js/helpers/jsx\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type {\n LayoutNode,\n MeasureOptions,\n MeasureResult,\n MeasureTextOptions,\n RenderOptions,\n RendererAdapter,\n} from \"./adapter.js\";\n\nexport const GEIST_MONO_FAMILY = \"Geist Mono\";\n\n/** Path of the vendored font, relative to the package root. Resolved in `takumi-node.ts`. */\nexport const FONT_REL = \"assets/fonts/GeistMono[wght].ttf\";\n\n/** Both runtimes end here: one adapter, one registered font, whoever supplied the bytes. */\nexport async function createRendererWithFont(font: Uint8Array): Promise<RendererAdapter> {\n const renderer = new Renderer();\n await renderer.registerFont({\n name: GEIST_MONO_FAMILY,\n data: font,\n generic: \"monospace\",\n });\n return new TakumiRenderer(renderer);\n}\n\n/** The docs build aliases takumi-js/node to the WASM binding, keeping one adapter. */\nexport async function createBrowserTakumiRenderer(font: Uint8Array): Promise<RendererAdapter> {\n const { init } = await import(\"takumi-js/wasm/no-init\");\n const { default: wasmUrl } = await import(\"takumi-js/wasm-url\");\n await init({ module_or_path: wasmUrl });\n return createRendererWithFont(font);\n}\n\nexport interface LineCountNode {\n runs: ReadonlyArray<{ y: number }>;\n children: readonly LineCountNode[];\n}\n\nexport function countLines(node: LineCountNode): number {\n const ys = new Set<number>();\n const walk = (current: LineCountNode): void => {\n for (const run of current.runs) {\n ys.add(Math.round(run.y));\n }\n for (const child of current.children) {\n walk(child);\n }\n };\n walk(node);\n return ys.size;\n}\n\nexport function testCardNode(): LayoutNode {\n return container({\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: 64,\n backgroundColor: \"#0b0b0c\",\n },\n children: [\n textNode(\"Shipseal\", {\n fontFamily: \"Geist\",\n fontSize: 72,\n fontWeight: 700,\n color: \"#fafafa\",\n }),\n textNode(\"Every release, sealed and ready to share\", {\n fontFamily: GEIST_MONO_FAMILY,\n fontSize: 28,\n fontWeight: 400,\n color: \"#a1a1aa\",\n }),\n ],\n });\n}\n\nclass TakumiRenderer implements RendererAdapter {\n constructor(private readonly renderer: Renderer) {}\n\n async fromJsx(element: unknown): Promise<LayoutNode> {\n const result = await takumiFromJsx(asReactElementLike(element));\n return pack(result.node, result.css);\n }\n\n async render(node: LayoutNode, opts: RenderOptions): Promise<Uint8Array> {\n const packed = unpack(node);\n const extras: { css: string[]; images?: RenderOptions[\"images\"] } = {\n css: opts.css ?? packed.css,\n };\n if (opts.images !== undefined) {\n extras.images = opts.images;\n }\n const buffer = await renderWithFormat(this.renderer, packed.node, opts, extras);\n return Uint8Array.from(buffer);\n }\n\n async measure(node: LayoutNode, opts?: MeasureOptions): Promise<MeasureResult> {\n const packed = unpack(node);\n const measured = await this.renderer.measure(packed.node, measureOpts(opts));\n return {\n lines: countLines(measured),\n width: measured.width,\n height: measured.height,\n };\n }\n\n async measureText(value: string, opts: MeasureTextOptions): Promise<MeasureResult> {\n const measured = await this.renderer.measure(asNode(textMeasureNode(value, opts)));\n return {\n lines: countLines(measured),\n width: measured.width,\n height: measured.height,\n };\n }\n}\n\nfunction renderWithFormat(\n renderer: Renderer,\n node: Node,\n opts: RenderOptions,\n extras: { css: string[]; images?: RenderOptions[\"images\"] },\n): Promise<Buffer> {\n const width = opts.width;\n const height = opts.height;\n const css = extras.css;\n const images = extras.images;\n if (opts.format === \"webp\") {\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"webp\", css, images });\n }\n return renderer.render(node, { width, height, format: \"webp\", css });\n }\n if (opts.format === \"jpeg\") {\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"jpeg\", css, images });\n }\n return renderer.render(node, { width, height, format: \"jpeg\", css });\n }\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"png\", css, images });\n }\n return renderer.render(node, { width, height, format: \"png\", css });\n}\n\nfunction measureOpts(opts?: MeasureOptions): { width?: number; height?: number } {\n const out: { width?: number; height?: number } = {};\n if (opts?.width !== undefined) {\n out.width = opts.width;\n }\n if (opts?.height !== undefined) {\n out.height = opts.height;\n }\n return out;\n}\n\nfunction textMeasureNode(value: string, opts: MeasureTextOptions): LayoutNode {\n const style: {\n fontFamily: string;\n fontSize: number;\n lineHeight: number;\n whiteSpace: \"normal\" | \"pre\";\n maxWidth: number;\n fontWeight?: number;\n } = {\n fontFamily: opts.fontFamily,\n fontSize: opts.fontSize,\n lineHeight: opts.lineHeight,\n whiteSpace: opts.whiteSpace ?? \"normal\",\n maxWidth: opts.maxWidth,\n };\n if (opts.fontWeight !== undefined) {\n style.fontWeight = opts.fontWeight;\n }\n return textNode(value, style);\n}\n\nfunction asNode(node: LayoutNode): Node {\n return unpack(node).node;\n}\n\ntype PackedLayout = { readonly __shipseal: true; node: Node; css: string[] };\n\nfunction pack(node: Node, css: string[] = []): LayoutNode {\n const packed: PackedLayout = { __shipseal: true, node, css };\n return packed;\n}\n\nfunction unpack(node: LayoutNode): PackedLayout {\n if (isPacked(node)) {\n return node;\n }\n if (isTakumiNode(node)) {\n return { __shipseal: true, node, css: [] };\n }\n throw new ShipsealError(\n \"render.invalid-node\",\n \"render/measure received a value that is not a Takumi node tree.\",\n \"Pass a node built by the renderer adapter (fromJsx, measureText, or testCardNode).\",\n );\n}\n\nfunction isPacked(node: LayoutNode): node is PackedLayout {\n return typeof node === \"object\" && node !== null && \"__shipseal\" in node;\n}\n\nfunction isTakumiNode(node: LayoutNode): node is Node {\n return typeof node === \"object\" && node !== null && \"type\" in node;\n}\n\nfunction asReactElementLike(element: unknown): { type: unknown; props: unknown; key: string | null } {\n if (typeof element !== \"object\" || element === null || !(\"type\" in element)) {\n throw new ShipsealError(\n \"render.invalid-jsx\",\n \"fromJsx received a value that is not a JSX element.\",\n \"Return JSX from a template render function.\",\n );\n }\n const record = element;\n const type = \"type\" in record ? record.type : undefined;\n const props = \"props\" in record ? record.props : null;\n const key = \"key\" in record && typeof record.key === \"string\" ? record.key : null;\n return { type, props, key };\n}\n","// The Node half of the renderer: finding the vendored font on disk and loading it.\n// Spec: docs/PROJECT_PLAN.md §16\n//\n// This file exists so that `takumi.ts` holds no `node:` import. The browser demo imports the\n// renderer through `takumi.ts`, and a single top-level `node:fs` there is enough for Vite to\n// externalize the module, throw on load, and leave the page blank with no error shown.\n//\n// Rule 3 still holds: `takumi.ts` remains the only file that imports Takumi. This one imports\n// `takumi.ts`, never `takumi-js`.\n\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { RendererAdapter } from \"./adapter.js\";\nimport { FONT_REL, createRendererWithFont } from \"./takumi.js\";\n\nlet shared: Promise<RendererAdapter> | undefined;\n\nexport function getTakumiRenderer(): Promise<RendererAdapter> {\n shared ??= createTakumiRenderer();\n return shared;\n}\n\nexport async function createTakumiRenderer(): Promise<RendererAdapter> {\n const fontPath = join(resolvePackageRoot(), FONT_REL);\n const data = await readFile(fontPath);\n return createRendererWithFont(data);\n}\n\nexport function resolvePackageRoot(from = import.meta.url): string {\n let dir = dirname(fileURLToPath(from));\n for (;;) {\n if (existsSync(join(dir, \"package.json\")) && existsSync(join(dir, FONT_REL))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n throw new ShipsealError(\n \"render.font-missing\",\n `Could not find vendored font ${FONT_REL}.`,\n \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present next to package.json.\",\n );\n }\n dir = parent;\n }\n}\n","// Rule R1: reject any digits not from facts\n// Spec: docs/PROJECT_PLAN.md §13.3\n\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Copy } from \"./slots.js\";\n\nexport function allowedNumbers(facts: Facts): Set<string> {\n const allowed = new Set<string>();\n const visit = (value: unknown): void => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n addNumber(allowed, value);\n return;\n }\n if (typeof value === \"string\") {\n for (const match of value.match(/\\d+(?:\\.\\d+)*/g) ?? []) {\n allowed.add(match);\n }\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n visit(item);\n }\n return;\n }\n if (typeof value === \"object\" && value !== null) {\n if (\"value\" in value && \"provenance\" in value) {\n visit(value.value);\n return;\n }\n for (const nested of Object.values(value)) {\n visit(nested);\n }\n }\n };\n visit(facts);\n return allowed;\n}\n\nexport function unsourcedDigits(text: string, allowed: Set<string>): string[] {\n const found: string[] = [];\n const withoutGrouped = text.replace(/\\d{1,3}(?:,\\d{3})+/g, (match) => {\n const compact = match.replaceAll(\",\", \"\");\n if (!allowed.has(match) && !allowed.has(compact)) {\n found.push(match);\n }\n return \" \";\n });\n for (const match of withoutGrouped.match(/\\d+(?:\\.\\d+)*/g) ?? []) {\n if (!allowed.has(match)) {\n found.push(match);\n }\n }\n return found;\n}\n\nexport function guardCopy(copy: Copy, facts: Facts): { ok: true } | { ok: false; slot: string; digits: string[] } {\n const allowed = allowedNumbers(facts);\n const slots: Array<[string, string]> = [\n [\"headline\", copy.headline],\n [\"subheadline\", copy.subheadline],\n [\"cta\", copy.cta],\n ];\n if (copy.milestoneLine !== undefined) {\n slots.push([\"milestoneLine\", copy.milestoneLine]);\n }\n copy.highlights.forEach((line, index) => {\n slots.push([`highlights[${String(index)}]`, line]);\n });\n for (const [slot, text] of slots) {\n const digits = unsourcedDigits(text, allowed);\n if (digits.length > 0) {\n return { ok: false, slot, digits };\n }\n }\n return { ok: true };\n}\n\nfunction addNumber(allowed: Set<string>, value: number): void {\n allowed.add(String(value));\n if (Number.isInteger(value)) {\n allowed.add(value.toLocaleString(\"en-US\"));\n }\n}\n","// Optional LLM copy via OpenAI-compatible fetch (BYOK, no extra SDK)\n// Spec: docs/PROJECT_PLAN.md §13.3\n\nimport { z } from \"zod\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { COPY_LIMITS, MAX_HIGHLIGHTS, type Copy } from \"./slots.js\";\nimport { deterministicCopy } from \"./deterministic.js\";\nimport { guardCopy } from \"./number-guard.js\";\n\nconst llmCopySchema = z.object({\n headline: z.string(),\n subheadline: z.string(),\n highlights: z.array(z.string()).max(MAX_HIGHLIGHTS),\n cta: z.string(),\n});\n\nexport interface LlmCopyOptions {\n apiKey: string;\n model: string;\n maxRetries: number;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport async function llmCopy(\n facts: Facts,\n options: LlmCopyOptions,\n fallback = deterministicCopy(facts),\n): Promise<{ copy: Copy; mode: \"llm\" | \"deterministic\"; warning?: string }> {\n const payload = factsForLlm(facts);\n let lastError: string | undefined;\n const retries = Math.max(0, options.maxRetries);\n for (let attempt = 0; attempt <= retries; attempt += 1) {\n let parsed: z.infer<typeof llmCopySchema>;\n try {\n // Sequential retries are required: each attempt depends on the previous rejection.\n // eslint-disable-next-line no-await-in-loop\n const raw = await requestCopy(payload, options);\n parsed = llmCopySchema.parse(JSON.parse(raw));\n } catch (error) {\n lastError = error instanceof Error ? error.message : \"LLM request failed\";\n continue;\n }\n const expanded = expandPlaceholders(parsed, facts);\n const styled: Copy = {\n headline: stripStyle(expanded.headline).slice(0, COPY_LIMITS.headline),\n subheadline: stripStyle(expanded.subheadline).slice(0, COPY_LIMITS.subheadline),\n highlights: expanded.highlights.map((line) => stripStyle(line).slice(0, COPY_LIMITS.highlight)),\n cta: stripStyle(expanded.cta).slice(0, COPY_LIMITS.cta),\n };\n const guarded = guardCopy(styled, facts);\n if (!guarded.ok) {\n lastError = `Number guard rejected ${guarded.slot}: ${guarded.digits.join(\", \")}`;\n continue;\n }\n return { copy: styled, mode: \"llm\" };\n }\n return {\n copy: fallback,\n mode: \"deterministic\",\n warning: lastError ?? \"LLM copy failed; using deterministic copy\",\n };\n}\n\nfunction factsForLlm(facts: Facts): Record<string, unknown> {\n return {\n project: {\n name: facts.project.name.value,\n tagline: facts.project.tagline?.value,\n npmPackage: facts.project.npmPackage?.value,\n url: facts.project.url?.value,\n },\n release: facts.release === undefined\n ? undefined\n : {\n version: \"{version}\",\n features: facts.release.features.map((item) => item.value),\n fixes: facts.release.fixes.map((item) => item.value),\n breaking: facts.release.breaking.map((item) => item.value),\n },\n metrics: {\n stars: facts.metrics?.stars === undefined ? undefined : \"{stars}\",\n weeklyDownloads: facts.metrics?.weeklyDownloads === undefined ? undefined : \"{weeklyDownloads}\",\n contributorCount: facts.metrics?.contributorCount === undefined ? undefined : \"{contributorCount}\",\n },\n };\n}\n\nfunction expandPlaceholders(copy: z.infer<typeof llmCopySchema>, facts: Facts): z.infer<typeof llmCopySchema> {\n const map: Record<string, string> = {\n \"{version}\": facts.release?.version.value ?? \"\",\n \"{stars}\": facts.metrics?.stars === undefined ? \"\" : formatCount(facts.metrics.stars.value),\n \"{weeklyDownloads}\":\n facts.metrics?.weeklyDownloads === undefined ? \"\" : formatCount(facts.metrics.weeklyDownloads.value),\n \"{contributorCount}\":\n facts.metrics?.contributorCount === undefined ? \"\" : formatCount(facts.metrics.contributorCount.value),\n };\n const expand = (text: string): string => {\n let out = text;\n for (const [token, value] of Object.entries(map)) {\n out = out.replaceAll(token, value);\n }\n return out;\n };\n return {\n headline: expand(copy.headline),\n subheadline: expand(copy.subheadline),\n highlights: copy.highlights.map(expand),\n cta: expand(copy.cta),\n };\n}\n\nfunction stripStyle(text: string): string {\n return text.replaceAll(\"\\u2014\", \":\").replaceAll(\"\\u2013\", \"-\").replaceAll(\"!\", \".\");\n}\n\nfunction formatCount(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nasync function requestCopy(facts: Record<string, unknown>, options: LlmCopyOptions): Promise<string> {\n const base = (options.baseUrl ?? \"https://api.openai.com/v1\").replace(/\\/$/, \"\");\n const fetchImpl = options.fetchImpl ?? fetch;\n const response = await fetchImpl(`${base}/chat/completions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: options.model,\n response_format: { type: \"json_object\" },\n messages: [\n {\n role: \"system\",\n content:\n \"Write short release-card copy as JSON with keys headline, subheadline, highlights, cta. No em dashes, no exclamation marks. Use placeholders like {version} for numbers. Never invent numbers.\",\n },\n { role: \"user\", content: JSON.stringify(facts) },\n ],\n }),\n });\n if (!response.ok) {\n throw new ShipsealError(\n \"copy.llm-http\",\n `LLM provider returned HTTP ${String(response.status)}.`,\n \"Check SHIPSEAL_LLM_API_KEY, copy.model, and SHIPSEAL_LLM_BASE_URL.\",\n );\n }\n const json: unknown = await response.json();\n const message = z\n .object({\n choices: z.array(z.object({ message: z.object({ content: z.string() }) })).min(1),\n })\n .parse(json);\n const first = message.choices[0];\n if (first === undefined) {\n throw new ShipsealError(\"copy.llm-empty\", \"LLM returned no choices.\", \"Retry, or run with --no-copy.\");\n }\n return first.message.content;\n}\n","// Build manifest.json with facts, computed values, warnings\n// Spec: docs/PROJECT_PLAN.md §17.2\n\nimport type { Brand } from \"../brand/schema.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { GenerateResult } from \"../core/generate.js\";\n\nexport interface ManifestFile {\n path: string;\n template: string;\n format: string;\n width: number;\n height: number;\n bytes: number;\n sha256: string;\n}\n\nexport interface Manifest {\n shipseal: string;\n event: ShipsealEvent;\n generatedAt: string;\n brand: { name: string; theme: Brand[\"theme\"]; source: string };\n copy: { mode: \"deterministic\" | \"llm\" };\n files: ManifestFile[];\n facts: Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }>;\n computed: Record<string, { value: unknown; computedFrom: string[] }>;\n warnings: GenerateResult[\"warnings\"];\n missing: GenerateResult[\"missing\"];\n}\n\nexport function buildManifest(input: {\n result: GenerateResult;\n event: ShipsealEvent;\n brand: Brand;\n shipsealVersion: string;\n}): Manifest {\n return {\n shipseal: input.shipsealVersion,\n event: input.event,\n generatedAt: input.result.generatedAt,\n brand: {\n name: input.brand.name,\n theme: input.brand.theme,\n source: \".shipseal/brand.json\",\n },\n copy: { mode: input.result.copyMode },\n files: input.result.files.map((file) => ({\n path: file.fileName,\n template: file.template,\n format: file.format,\n width: file.width,\n height: file.height,\n bytes: file.bytes.byteLength,\n sha256: file.sha256,\n })),\n facts: flattenFacts(input.result.facts),\n computed: input.result.computed,\n warnings: input.result.warnings,\n missing: input.result.missing,\n };\n}\n\nexport function flattenFacts(\n facts: Facts,\n): Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }> {\n const out: Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }> = {};\n const walk = (prefix: string, value: unknown): void => {\n if (isFact(value)) {\n out[prefix] = {\n value: value.value,\n source: value.provenance.source,\n ref: value.provenance.ref,\n fetchedAt: value.provenance.fetchedAt,\n };\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n walk(`${prefix}[${String(index)}]`, item);\n });\n return;\n }\n if (typeof value === \"object\" && value !== null) {\n for (const [key, nested] of Object.entries(value)) {\n walk(prefix.length === 0 ? key : `${prefix}.${key}`, nested);\n }\n }\n };\n walk(\"project\", facts.project);\n if (facts.story !== undefined) {\n walk(\"story\", facts.story);\n }\n if (facts.release !== undefined) {\n walk(\"release\", facts.release);\n }\n if (facts.metrics !== undefined) {\n walk(\"metrics\", facts.metrics);\n }\n if (facts.bench !== undefined) {\n walk(\"bench\", facts.bench);\n }\n if (facts.milestone !== undefined) {\n walk(\"milestone\", facts.milestone);\n }\n return out;\n}\n\nfunction isFact(\n value: unknown,\n): value is { value: unknown; provenance: { source: string; ref: string; fetchedAt: string } } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n if (!(\"value\" in value) || !(\"provenance\" in value)) {\n return false;\n }\n const provenance = value.provenance;\n return (\n typeof provenance === \"object\" &&\n provenance !== null &&\n \"source\" in provenance &&\n \"ref\" in provenance &&\n \"fetchedAt\" in provenance\n );\n}\n","// Write pack files to disk\n// Spec: docs/PROJECT_PLAN.md §17.1\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { GenerateResult } from \"../core/generate.js\";\nimport { buildManifest, type Manifest } from \"./manifest.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\n\nexport async function writePack(input: {\n outDir: string;\n eventId: string;\n result: GenerateResult;\n event: ShipsealEvent;\n brand: Brand;\n shipsealVersion: string;\n}): Promise<{ dir: string; manifest: Manifest }> {\n const dir = join(input.outDir, input.eventId);\n await mkdir(dir, { recursive: true });\n await Promise.all(input.result.files.map((file) => writeFile(join(dir, file.fileName), file.bytes)));\n const manifest = buildManifest({\n result: input.result,\n event: input.event,\n brand: input.brand,\n shipsealVersion: input.shipsealVersion,\n });\n await writeFile(join(dir, \"manifest.json\"), `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n return { dir, manifest };\n}\n\nexport function resolveOutputDir(cwd: string, configured: string): string {\n return isAbsolute(configured) ? configured : join(cwd, configured);\n}\n\nexport function eventId(event: ShipsealEvent, generatedAt = \"\"): string {\n if (event.kind === \"release\") {\n return event.tag;\n }\n if (event.kind === \"milestone\") {\n return `milestone-${event.metric}-${String(event.threshold)}`;\n }\n const day = generatedAt.slice(0, 10);\n return /^\\d{4}-\\d{2}-\\d{2}$/.test(day) ? `bench-${day}` : \"bench\";\n}\n","// Upload assets to a GitHub release and write the Actions job summary\n// Spec: docs/PROJECT_PLAN.md §19.4\n// Docs checked 2026-09-11: `gh release upload <tag> <files>... --clobber`\n// gh is preinstalled on GitHub-hosted runners.\n\nimport { execFile } from \"node:child_process\";\nimport { appendFile } from \"node:fs/promises\";\nimport { promisify } from \"node:util\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { Manifest } from \"./manifest.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GhExec = (\n file: string,\n args: string[],\n options: { env: NodeJS.ProcessEnv },\n) => Promise<{ stdout: string; stderr: string }>;\n\nexport async function uploadReleaseAssets(options: {\n tag: string;\n files: string[];\n repo?: string;\n token?: string;\n exec?: GhExec;\n}): Promise<void> {\n if (options.files.length === 0) {\n return;\n }\n const exec = options.exec ?? execFileAsync;\n const args = [\"release\", \"upload\", options.tag, ...options.files, \"--clobber\"];\n if (options.repo !== undefined) {\n args.push(\"--repo\", options.repo);\n }\n const env = { ...process.env };\n if (options.token !== undefined) {\n env.GH_TOKEN = options.token;\n env.GITHUB_TOKEN = options.token;\n }\n try {\n await exec(\"gh\", args, { env });\n } catch (error) {\n throw new ShipsealError(\n \"github.upload\",\n `Could not upload assets to GitHub release ${options.tag}.`,\n \"Confirm gh is installed, GITHUB_TOKEN can write contents, and the release exists.\",\n { cause: error },\n );\n }\n}\n\nexport async function appendJobSummary(path: string, manifest: Manifest, dir: string): Promise<void> {\n await appendFile(path, `${jobSummaryMarkdown(manifest, dir)}\\n`, \"utf8\");\n}\n\nexport function jobSummaryMarkdown(manifest: Manifest, dir: string): string {\n const lines = [\n \"## Shipseal\",\n \"\",\n `Generated **${String(manifest.files.length)}** files in \\`${dir}\\`.`,\n \"\",\n ];\n const repo = process.env.GITHUB_REPOSITORY;\n const tag = manifest.event.kind === \"release\" ? manifest.event.tag : undefined;\n if (repo !== undefined && tag !== undefined) {\n for (const file of manifest.files) {\n const url = `https://github.com/${repo}/releases/download/${tag}/${file.path}`;\n lines.push(``, \"\");\n }\n } else {\n lines.push(\"| File | Template | Format |\", \"|---|---|---|\");\n for (const file of manifest.files) {\n lines.push(`| ${file.path} | ${file.template} | ${file.format} |`);\n }\n lines.push(\"\");\n }\n lines.push(\"### Facts\", \"\");\n for (const [key, entry] of Object.entries(manifest.facts)) {\n lines.push(`- \\`${key}\\`: ${JSON.stringify(entry.value)} (${entry.source})`);\n }\n if (Object.keys(manifest.computed).length > 0) {\n lines.push(\"\", \"### Computed\", \"\");\n for (const [key, entry] of Object.entries(manifest.computed)) {\n lines.push(`- \\`${key}\\`: ${JSON.stringify(entry.value)}`);\n }\n }\n if (manifest.warnings.length > 0) {\n lines.push(\"\", \"### Warnings\", \"\");\n for (const warning of manifest.warnings) {\n lines.push(`- ${warning.template} ${warning.format} ${warning.slot}: ${warning.action}`);\n }\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n","// Shared helpers for release, milestone, and bench commands\n\nimport { readFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { Brand } from \"../brand/schema.js\";\nimport { mergeConfig } from \"../config/load.js\";\nimport { DEFAULT_CONFIG, type Config } from \"../config/schema.js\";\nimport { llmCopy } from \"../copy/llm.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport type { GenerateResult } from \"../core/generate.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { FORMAT_IDS, type FormatId } from \"../formats.js\";\nimport { eventId, resolveOutputDir, writePack } from \"../outputs/files.js\";\nimport { appendJobSummary, uploadReleaseAssets } from \"../outputs/github-release.js\";\nimport type { Manifest } from \"../outputs/manifest.js\";\nimport { resolvePackageRoot } from \"../render/takumi-node.js\";\n\nexport interface SharedFlags {\n cwd: string;\n formats?: string;\n themes?: string;\n copy?: boolean;\n out?: string;\n strict?: boolean;\n dryRun?: boolean;\n package?: string;\n upload?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport function overlayFormats(config: Config, flags: SharedFlags): Config {\n const overlay: Config = { ...config };\n if (flags.formats !== undefined) {\n overlay.formats = parseFormats(flags.formats);\n }\n if (flags.out !== undefined) {\n overlay.outputDir = flags.out;\n }\n return mergeConfig(DEFAULT_CONFIG, overlay);\n}\n\nexport function parseFormats(list: string): FormatId[] {\n const formats: FormatId[] = [];\n for (const part of list.split(\",\")) {\n const id = part.trim();\n if (id.length === 0) {\n continue;\n }\n const match = FORMAT_IDS.find((format) => format === id);\n if (match === undefined) {\n throw new ShipsealError(\n \"release.bad-format\",\n `Unknown format \"${id}\".`,\n `Use a comma-separated list from: ${FORMAT_IDS.join(\", \")}.`,\n );\n }\n formats.push(match);\n }\n return formats;\n}\n\nexport function resolveThemes(flag: string | undefined, brandTheme: Brand[\"theme\"]): Array<\"dark\" | \"light\"> {\n if (flag === \"both\") {\n return [\"dark\", \"light\"];\n }\n if (flag === \"dark\" || flag === \"light\") {\n return [flag];\n }\n return [brandTheme];\n}\n\nexport async function resolveCopy(\n facts: Facts,\n config: Config,\n noCopy: boolean,\n fallback: Copy,\n): Promise<{ copy: Copy; copyMode: \"deterministic\" | \"llm\"; warning?: string }> {\n if (noCopy || config.copy?.llm !== true) {\n return { copy: fallback, copyMode: \"deterministic\" };\n }\n const apiKey = process.env.SHIPSEAL_LLM_API_KEY;\n if (apiKey === undefined || apiKey.length === 0) {\n throw new ShipsealError(\n \"copy.missing-key\",\n \"copy.llm is enabled but SHIPSEAL_LLM_API_KEY is not set.\",\n \"Set SHIPSEAL_LLM_API_KEY, or pass --no-copy for deterministic copy.\",\n );\n }\n const llmOpts: Parameters<typeof llmCopy>[1] = {\n apiKey,\n model: config.copy.model ?? \"gpt-4o-mini\",\n maxRetries: config.copy.maxRetries ?? 2,\n };\n if (process.env.SHIPSEAL_LLM_BASE_URL !== undefined) {\n llmOpts.baseUrl = process.env.SHIPSEAL_LLM_BASE_URL;\n }\n const result = await llmCopy(facts, llmOpts, fallback);\n const out: { copy: Copy; copyMode: \"deterministic\" | \"llm\"; warning?: string } = {\n copy: result.copy,\n copyMode: result.mode,\n };\n if (result.warning !== undefined) {\n out.warning = result.warning;\n }\n return out;\n}\n\nexport async function loadLogos(cwd: string, brand: Brand): Promise<{ light?: Uint8Array; dark?: Uint8Array } | undefined> {\n if (brand.logo === undefined) {\n return undefined;\n }\n const logos: { light?: Uint8Array; dark?: Uint8Array } = {\n light: await readLogo(cwd, brand.logo.light),\n };\n if (brand.logo.dark !== undefined) {\n logos.dark = await readLogo(cwd, brand.logo.dark);\n }\n return logos;\n}\n\nasync function readLogo(cwd: string, path: string): Promise<Uint8Array> {\n const resolved = isAbsolute(path) ? path : join(cwd, path);\n return new Uint8Array(await readFile(resolved));\n}\n\nexport function readShipsealVersion(): string {\n const raw: unknown = JSON.parse(readFileSync(join(resolvePackageRoot(), \"package.json\"), \"utf8\"));\n if (typeof raw === \"object\" && raw !== null && \"version\" in raw && typeof raw.version === \"string\") {\n return raw.version;\n }\n return \"0.0.0\";\n}\n\nexport function collectEnv(flags: SharedFlags): {\n skipNetwork: boolean;\n githubToken?: string;\n packagePath?: string;\n fetchImpl?: typeof fetch;\n} {\n const skipNetwork = flags.dryRun === true && process.env.GITHUB_TOKEN === undefined;\n const out: ReturnType<typeof collectEnv> = { skipNetwork };\n if (process.env.GITHUB_TOKEN !== undefined) {\n out.githubToken = process.env.GITHUB_TOKEN;\n }\n if (flags.package !== undefined) {\n out.packagePath = flags.package;\n }\n if (flags.fetchImpl !== undefined) {\n out.fetchImpl = flags.fetchImpl;\n }\n return out;\n}\n\nexport async function finishPack(input: {\n flags: SharedFlags;\n config: Config;\n event: ShipsealEvent;\n result: GenerateResult;\n brand: Brand;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n facts: Facts;\n}): Promise<{\n dryRun: false;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir: string;\n manifest: Manifest;\n warnings: GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}> {\n const generatedAt = input.result.generatedAt;\n const written = await writePack({\n outDir: resolveOutputDir(\n input.flags.cwd,\n input.flags.out ?? input.config.outputDir ?? \".shipseal/output\",\n ),\n eventId: eventId(input.event, generatedAt),\n result: input.result,\n event: input.event,\n brand: input.brand,\n shipsealVersion: readShipsealVersion(),\n });\n if (input.flags.upload === true && input.event.kind === \"release\") {\n const files = input.result.files.map((file) => join(written.dir, file.fileName));\n const uploadOpts: Parameters<typeof uploadReleaseAssets>[0] = { tag: input.event.tag, files };\n if (process.env.GITHUB_REPOSITORY !== undefined) {\n uploadOpts.repo = process.env.GITHUB_REPOSITORY;\n }\n if (process.env.GITHUB_TOKEN !== undefined) {\n uploadOpts.token = process.env.GITHUB_TOKEN;\n }\n await uploadReleaseAssets(uploadOpts);\n }\n const summaryPath = process.env.GITHUB_STEP_SUMMARY;\n if (summaryPath !== undefined && summaryPath.length > 0) {\n await appendJobSummary(summaryPath, written.manifest, written.dir);\n }\n const exitCode: 0 | 1 | 2 = input.flags.strict === true && input.result.warnings.length > 0 ? 2 : 0;\n const done: {\n dryRun: false;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir: string;\n manifest: Manifest;\n warnings: GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n } = {\n dryRun: false,\n facts: input.facts,\n copy: input.copy,\n copyMode: input.copyMode,\n dir: written.dir,\n manifest: written.manifest,\n warnings: input.result.warnings,\n exitCode,\n };\n if (input.copyWarning !== undefined) {\n done.copyWarning = input.copyWarning;\n }\n return done;\n}\n","// bench: before/after cards from bench JSON\n// Spec: docs/PROJECT_PLAN.md §18.4\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { benchCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport interface BenchFlags extends SharedFlags {\n file?: string;\n}\n\nexport interface BenchResult {\n dryRun: boolean;\n facts: Awaited<ReturnType<typeof collectFacts>>;\n copy: import(\"../copy/slots.js\").Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runBench(flags: BenchFlags): Promise<BenchResult> {\n const cwd = flags.cwd;\n const config = overlayFormats(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const file = flags.file ?? config.bench?.file ?? \".shipseal/bench.json\";\n const event: ShipsealEvent = { kind: \"bench\", file };\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event,\n skipNetwork: true,\n benchFile: file,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n const facts = await collectFacts(collectOpts);\n const resolved = await resolveCopy(facts, config, flags.copy === false, benchCopy(facts));\n\n if (flags.dryRun === true) {\n const dry: BenchResult = {\n dryRun: true,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n return finishPack(packInput);\n}\n","// doctor: environment and config checks\n// Spec: docs/PROJECT_PLAN.md §18.5\n\nimport { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { brandSchema } from \"../brand/schema.js\";\nimport { FORMATS } from \"../formats.js\";\nimport { createTakumiRenderer, resolvePackageRoot } from \"../render/takumi-node.js\";\nimport { testCardNode } from \"../render/takumi.js\";\n\nconst execFileAsync = promisify(execFile);\nconst MIN_NODE_MAJOR = 22;\n\nexport type CheckStatus = \"pass\" | \"fail\" | \"info\";\n\nexport interface DoctorCheck {\n name: string;\n status: CheckStatus;\n message: string;\n fix?: string;\n}\n\nexport interface DoctorResult {\n ok: boolean;\n checks: DoctorCheck[];\n}\n\nexport async function runDoctor(cwd: string): Promise<DoctorResult> {\n const checks: DoctorCheck[] = [];\n checks.push(checkNode());\n checks.push(await checkGit(cwd));\n checks.push(await checkShallow(cwd));\n checks.push(await checkBrand(cwd));\n checks.push(await checkFont());\n checks.push(await checkLogo(cwd));\n checks.push(checkGithubToken());\n checks.push(await checkRender());\n\n return {\n ok: checks.every((check) => check.status !== \"fail\"),\n checks,\n };\n}\n\nfunction checkNode(): DoctorCheck {\n const version = process.versions.node;\n const major = Number.parseInt(version.split(\".\")[0] ?? \"0\", 10);\n if (major >= MIN_NODE_MAJOR) {\n return { name: \"node\", status: \"pass\", message: `Node.js ${version}` };\n }\n return {\n name: \"node\",\n status: \"fail\",\n message: `Node.js ${version} is below the minimum of ${MIN_NODE_MAJOR}.`,\n fix: `Install Node.js ${MIN_NODE_MAJOR} or newer.`,\n };\n}\n\nasync function checkGit(cwd: string): Promise<DoctorCheck> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"--version\"], { cwd });\n return { name: \"git\", status: \"pass\", message: stdout.trim() };\n } catch {\n return {\n name: \"git\",\n status: \"fail\",\n message: \"git is not available on PATH.\",\n fix: \"Install git and ensure it is on PATH.\",\n };\n }\n}\n\nasync function checkShallow(cwd: string): Promise<DoctorCheck> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--is-shallow-repository\"], {\n cwd,\n });\n if (stdout.trim() === \"true\") {\n return {\n name: \"clone-depth\",\n status: \"fail\",\n message: \"This git clone is shallow, so release facts will be incomplete.\",\n fix: \"Re-clone with a full history, or in GitHub Actions set fetch-depth: 0.\",\n };\n }\n return { name: \"clone-depth\", status: \"pass\", message: \"Full git history is available.\" };\n } catch {\n return {\n name: \"clone-depth\",\n status: \"info\",\n message: \"Could not determine whether the clone is shallow.\",\n };\n }\n}\n\nasync function checkBrand(cwd: string): Promise<DoctorCheck> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n if (!existsSync(path)) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \".shipseal/brand.json is missing.\",\n fix: \"Run shipseal init to detect a brand kit.\",\n };\n }\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = brandSchema.safeParse(raw);\n if (!parsed.success) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \"brand.json did not match the v1 schema.\",\n fix: parsed.error.issues.map((issue) => issue.message).join(\"; \"),\n };\n }\n return { name: \"brand.json\", status: \"pass\", message: `Brand ${parsed.data.name} is valid.` };\n } catch (error) {\n if (error instanceof SyntaxError) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \"brand.json is not valid JSON.\",\n fix: \"Fix the JSON syntax, or re-run shipseal init --force.\",\n };\n }\n throw error;\n }\n}\n\nasync function checkFont(): Promise<DoctorCheck> {\n try {\n const root = resolvePackageRoot();\n const fontPath = join(root, \"assets\", \"fonts\", \"GeistMono[wght].ttf\");\n if (!existsSync(fontPath)) {\n return {\n name: \"fonts\",\n status: \"fail\",\n message: \"Vendored Geist Mono file is missing.\",\n fix: \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present.\",\n };\n }\n return { name: \"fonts\", status: \"pass\", message: `Geist Mono found at ${fontPath}` };\n } catch {\n return {\n name: \"fonts\",\n status: \"fail\",\n message: \"Could not resolve the vendored Geist Mono font.\",\n fix: \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present.\",\n };\n }\n}\n\nasync function checkLogo(cwd: string): Promise<DoctorCheck> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n if (!existsSync(path)) {\n return {\n name: \"logo\",\n status: \"info\",\n message: \"Skipped; brand.json is missing.\",\n };\n }\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = brandSchema.safeParse(raw);\n if (!parsed.success || parsed.data.logo === undefined) {\n return { name: \"logo\", status: \"info\", message: \"No logo path in brand.json.\" };\n }\n const light = join(cwd, parsed.data.logo.light);\n if (!existsSync(light)) {\n return {\n name: \"logo\",\n status: \"fail\",\n message: `Logo file ${parsed.data.logo.light} is not readable.`,\n fix: \"Point brand.json logo.light at an existing SVG or PNG, or re-run init.\",\n };\n }\n return { name: \"logo\", status: \"pass\", message: `Logo readable at ${parsed.data.logo.light}` };\n}\n\nfunction checkGithubToken(): DoctorCheck {\n if (process.env.GITHUB_TOKEN !== undefined && process.env.GITHUB_TOKEN.length > 0) {\n return { name: \"GITHUB_TOKEN\", status: \"info\", message: \"GITHUB_TOKEN is set.\" };\n }\n return {\n name: \"GITHUB_TOKEN\",\n status: \"info\",\n message: \"GITHUB_TOKEN is not set. Unauthenticated GitHub API calls have a low rate limit.\",\n };\n}\n\nasync function checkRender(): Promise<DoctorCheck> {\n try {\n const renderer = await createTakumiRenderer();\n const png = await renderer.render(testCardNode(), {\n width: FORMATS.og.width,\n height: FORMATS.og.height,\n format: \"png\",\n });\n if (png.length < 8 || png[0] !== 0x89 || png[1] !== 0x50) {\n return {\n name: \"takumi\",\n status: \"fail\",\n message: \"Takumi rendered bytes that are not a PNG.\",\n fix: \"File an issue with the doctor output and your OS/arch.\",\n };\n }\n return {\n name: \"takumi\",\n status: \"pass\",\n message: `Rendered a ${FORMATS.og.width}x${FORMATS.og.height} test card (${png.length} bytes).`,\n };\n } catch (error) {\n return {\n name: \"takumi\",\n status: \"fail\",\n message: error instanceof Error ? error.message : \"Takumi failed to render a test card.\",\n fix: \"Check that the native Takumi binary installed for this platform.\",\n };\n }\n}\n","// CSS color parsing, oklch to sRGB hex, and contrast (no dependency)\n// Spec: docs/PROJECT_PLAN.md §10.3 and §25 (S7 oklch converter)\n\nconst HEX = /^#([\\da-f]{3}|[\\da-f]{6}|[\\da-f]{8})$/i;\n\nexport function parseCssColor(value: string): string | undefined {\n const trimmed = value.trim();\n const hex = normalizeHex(trimmed);\n if (hex !== undefined) {\n return hex;\n }\n const oklch = parseOklch(trimmed);\n if (oklch !== undefined) {\n return oklchToHex(oklch.l, oklch.c, oklch.h);\n }\n const rgb = parseRgb(trimmed);\n if (rgb !== undefined) {\n return rgbToHex(rgb[0], rgb[1], rgb[2]);\n }\n const hsl = parseHsl(trimmed);\n if (hsl !== undefined) {\n return rgbToHex(...hslToRgb(hsl[0], hsl[1], hsl[2]));\n }\n return undefined;\n}\n\nexport function normalizeHex(value: string): string | undefined {\n const match = HEX.exec(value.trim());\n if (match === null) {\n return undefined;\n }\n const raw = match[1];\n if (raw === undefined) {\n return undefined;\n }\n if (raw.length === 3) {\n return `#${raw[0]}${raw[0]}${raw[1]}${raw[1]}${raw[2]}${raw[2]}`.toLowerCase();\n }\n return `#${raw.slice(0, 6).toLowerCase()}`;\n}\n\nexport function oklchToHex(l: number, c: number, h: number): string {\n const hr = (h * Math.PI) / 180;\n const a = c * Math.cos(hr);\n const b = c * Math.sin(hr);\n const coneL = l + 0.3963377774 * a + 0.2158037573 * b;\n const coneM = l - 0.1055613458 * a - 0.0638541728 * b;\n const coneS = l - 0.0894841775 * a - 1.291485548 * b;\n const l3 = coneL * coneL * coneL;\n const m3 = coneM * coneM * coneM;\n const s3 = coneS * coneS * coneS;\n const r = 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3;\n const g = -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3;\n const bLin = -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3;\n return rgbToHex(srgbEncode(r) * 255, srgbEncode(g) * 255, srgbEncode(bLin) * 255);\n}\n\nexport function contrastRatio(hexA: string, hexB: string): number {\n const a = relativeLuminance(hexA);\n const b = relativeLuminance(hexB);\n const [hi, lo] = a > b ? [a, b] : [b, a];\n return (hi + 0.05) / (lo + 0.05);\n}\n\nexport const LARGE_TEXT_CONTRAST = 3;\n\nexport function ensureForegroundContrast(\n background: string,\n foreground: string,\n): { foreground: string; adjusted: boolean } {\n if (contrastRatio(background, foreground) >= LARGE_TEXT_CONTRAST) {\n return { foreground, adjusted: false };\n }\n const light = \"#fafafa\";\n const dark = \"#0b0b0c\";\n const lightRatio = contrastRatio(background, light);\n const darkRatio = contrastRatio(background, dark);\n return { foreground: lightRatio >= darkRatio ? light : dark, adjusted: true };\n}\n\nexport function readableOnBackground(background: string, candidate: string): boolean {\n return contrastRatio(background, candidate) >= LARGE_TEXT_CONTRAST;\n}\n\nfunction srgbEncode(channel: number): number {\n const abs = Math.abs(channel);\n const encoded = abs <= 0.0031308 ? 12.92 * abs : 1.055 * abs ** (1 / 2.4) - 0.055;\n return Math.sign(channel) * encoded;\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return `#${toByte(r)}${toByte(g)}${toByte(b)}`;\n}\n\nfunction toByte(n: number): string {\n return Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, \"0\");\n}\n\nfunction relativeLuminance(hex: string): number {\n const rgb = hexToRgb(hex);\n if (rgb === undefined) {\n return 0;\n }\n const lin = rgb.map((channel) => {\n const s = channel / 255;\n return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * (lin[0] ?? 0) + 0.7152 * (lin[1] ?? 0) + 0.0722 * (lin[2] ?? 0);\n}\n\nexport function isNeutralHex(hex: string): boolean {\n const rgb = hexToRgb(hex);\n if (rgb === undefined) {\n return true;\n }\n const max = Math.max(rgb[0], rgb[1], rgb[2]);\n const min = Math.min(rgb[0], rgb[1], rgb[2]);\n return max - min < 16;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] | undefined {\n const normalized = normalizeHex(hex);\n if (normalized === undefined) {\n return undefined;\n }\n const r = Number.parseInt(normalized.slice(1, 3), 16);\n const g = Number.parseInt(normalized.slice(3, 5), 16);\n const b = Number.parseInt(normalized.slice(5, 7), 16);\n return [r, g, b];\n}\n\nfunction parseOklch(value: string): { l: number; c: number; h: number } | undefined {\n const match = /^oklch\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const body = match[1];\n if (body === undefined) {\n return undefined;\n }\n const parts = splitCssArgs(body);\n if (parts.length < 3) {\n return undefined;\n }\n const l = parseLightness(parts[0] ?? \"\");\n const c = parseNumber(parts[1] ?? \"\");\n const h = parseHue(parts[2] ?? \"\");\n if (l === undefined || c === undefined || h === undefined) {\n return undefined;\n }\n return { l, c, h };\n}\n\nfunction parseRgb(value: string): [number, number, number] | undefined {\n const match = /^rgba?\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const parts = splitCssArgs(match[1] ?? \"\");\n if (parts.length < 3) {\n return undefined;\n }\n const r = parseRgbChannel(parts[0] ?? \"\");\n const g = parseRgbChannel(parts[1] ?? \"\");\n const b = parseRgbChannel(parts[2] ?? \"\");\n if (r === undefined || g === undefined || b === undefined) {\n return undefined;\n }\n return [r, g, b];\n}\n\nfunction parseHsl(value: string): [number, number, number] | undefined {\n const match = /^hsla?\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const parts = splitCssArgs(match[1] ?? \"\");\n if (parts.length < 3) {\n return undefined;\n }\n const h = parseHue(parts[0] ?? \"\");\n const s = parsePercent(parts[1] ?? \"\");\n const l = parsePercent(parts[2] ?? \"\");\n if (h === undefined || s === undefined || l === undefined) {\n return undefined;\n }\n return [h, s, l];\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n const sat = s / 100;\n const light = l / 100;\n const c = (1 - Math.abs(2 * light - 1)) * sat;\n const hp = (((h % 360) + 360) % 360) / 60;\n const x = c * (1 - Math.abs((hp % 2) - 1));\n let r = 0;\n let g = 0;\n let b = 0;\n if (hp < 1) {\n r = c;\n g = x;\n } else if (hp < 2) {\n r = x;\n g = c;\n } else if (hp < 3) {\n g = c;\n b = x;\n } else if (hp < 4) {\n g = x;\n b = c;\n } else if (hp < 5) {\n r = x;\n b = c;\n } else {\n r = c;\n b = x;\n }\n const m = light - c / 2;\n return [(r + m) * 255, (g + m) * 255, (b + m) * 255];\n}\n\nfunction splitCssArgs(body: string): string[] {\n return body\n .split(/[\\s,]+/)\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n}\n\nfunction parseLightness(token: string): number | undefined {\n if (token.endsWith(\"%\")) {\n const n = Number.parseFloat(token.slice(0, -1));\n return Number.isFinite(n) ? n / 100 : undefined;\n }\n return parseNumber(token);\n}\n\nfunction parseHue(token: string): number | undefined {\n if (token === \"none\") {\n return 0;\n }\n if (token.endsWith(\"deg\")) {\n return parseNumber(token.slice(0, -3));\n }\n if (token.endsWith(\"rad\")) {\n const n = parseNumber(token.slice(0, -3));\n return n === undefined ? undefined : (n * 180) / Math.PI;\n }\n if (token.endsWith(\"turn\")) {\n const n = parseNumber(token.slice(0, -4));\n return n === undefined ? undefined : n * 360;\n }\n if (token.endsWith(\"grad\")) {\n const n = parseNumber(token.slice(0, -4));\n return n === undefined ? undefined : n * 0.9;\n }\n return parseNumber(token);\n}\n\nfunction parsePercent(token: string): number | undefined {\n if (!token.endsWith(\"%\")) {\n return parseNumber(token);\n }\n return parseNumber(token.slice(0, -1));\n}\n\nfunction parseRgbChannel(token: string): number | undefined {\n if (token.endsWith(\"%\")) {\n const n = parseNumber(token.slice(0, -1));\n return n === undefined ? undefined : (n / 100) * 255;\n }\n return parseNumber(token);\n}\n\nfunction parseNumber(token: string): number | undefined {\n if (token === \"none\") {\n return 0;\n }\n const n = Number.parseFloat(token);\n return Number.isFinite(n) ? n : undefined;\n}\n","// CSS :root variable extraction\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { parseCssColor } from \"./color.js\";\nimport type { ExtractedColors } from \"./tailwind.js\";\n\n// The trailing semicolon is optional: the last declaration before `}` usually has none,\n// which silently dropped one color from almost every real stylesheet.\nconst PROP =\n /--(primary|brand|accent|background|foreground|muted-foreground|muted)\\s*:\\s*([^;}]+)[;}]?/g;\n\n/** Any declaration, used to resolve `var(--brand-500)` style indirection. */\nconst ANY_PROP = /(--[\\w-]+)\\s*:\\s*([^;}]+)[;}]?/g;\n\n/**\n * Selectors that carry theme tokens in real projects. `:root` alone missed shadcn's\n * `[data-theme]` blocks, plain `html {}`, and `.light`.\n */\nconst SELECTORS = [\n /:root\\s*\\{/g,\n /(?:^|[\\s,}])html\\s*\\{/g,\n /\\.light\\b[^{]*\\{/g,\n /\\[data-theme=[\"']?light[\"']?\\][^{]*\\{/g,\n /\\.dark\\b[^{]*\\{/g,\n /\\[data-theme=[\"']?dark[\"']?\\][^{]*\\{/g,\n];\n\nexport function extractCssRootColors(css: string): ExtractedColors {\n const vars = allVariables(css);\n const found: Record<string, string> = {};\n // Later selectors win, so a dark block overrides a light one, as it does in a browser.\n for (const selector of SELECTORS) {\n Object.assign(found, extractBlockColors(css, selector, vars));\n }\n return mapFoundColors(found);\n}\n\nfunction allVariables(css: string): Record<string, string> {\n const vars: Record<string, string> = {};\n ANY_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = ANY_PROP.exec(css)) !== null) {\n const name = match[1];\n const value = match[2];\n if (name !== undefined && value !== undefined) {\n vars[name] = value.trim();\n }\n }\n return vars;\n}\n\n/**\n * Resolve a declaration to a hex color.\n *\n * Handles two things a plain color parser does not. First, `var(--brand-500)` indirection,\n * up to three hops within the same file. Second, bare channel lists: shadcn writes\n * `--background: 0 0% 100%` and applies it as `hsl(var(--background))`, so the value is only\n * a color once wrapped. Percent signs on the last two channels mean HSL, three plain\n * numbers mean RGB.\n */\nfunction resolveColor(raw: string, vars: Record<string, string>, depth = 0): string | undefined {\n const value = raw.trim();\n if (depth < 3) {\n const ref = /^var\\(\\s*(--[\\w-]+)\\s*(?:,[^)]*)?\\)$/.exec(value);\n const target = ref?.[1] === undefined ? undefined : vars[ref[1]];\n if (target !== undefined) {\n return resolveColor(target, vars, depth + 1);\n }\n }\n const direct = parseCssColor(value);\n if (direct !== undefined) {\n return direct;\n }\n const parts = value.split(/[\\s/]+/).filter((p) => p.length > 0);\n if (parts.length === 3) {\n if (parts[1]?.endsWith(\"%\") === true && parts[2]?.endsWith(\"%\") === true) {\n return parseCssColor(`hsl(${parts[0]} ${parts[1]} ${parts[2]})`);\n }\n if (parts.every((p) => /^\\d+(\\.\\d+)?$/.test(p))) {\n return parseCssColor(`rgb(${parts[0]} ${parts[1]} ${parts[2]})`);\n }\n }\n return undefined;\n}\n\nfunction extractBlockColors(\n css: string,\n blockRe: RegExp,\n vars: Record<string, string>,\n): Record<string, string> {\n const found: Record<string, string> = {};\n blockRe.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = blockRe.exec(css)) !== null) {\n const open = css.indexOf(\"{\", match.index);\n if (open === -1) {\n break;\n }\n const close = matchingBrace(css, open);\n if (close === -1) {\n break;\n }\n const body = css.slice(open + 1, close);\n PROP.lastIndex = 0;\n let prop: RegExpExecArray | null;\n while ((prop = PROP.exec(body)) !== null) {\n const name = prop[1];\n const raw = prop[2];\n if (name === undefined || raw === undefined) {\n continue;\n }\n const hex = resolveColor(raw, vars);\n if (hex !== undefined) {\n found[name] = hex;\n }\n }\n }\n return found;\n}\n\nfunction mapFoundColors(found: Record<string, string>): ExtractedColors {\n const out: ExtractedColors = {};\n const background = found.background;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n const muted = found[\"muted-foreground\"] ?? found.muted;\n if (muted !== undefined) {\n out.muted = muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n if (found.accent !== undefined) {\n out.accent = found.accent;\n }\n return out;\n}\n\nfunction matchingBrace(source: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < source.length; i += 1) {\n const ch = source[i];\n if (ch === \"{\") {\n depth += 1;\n } else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return i;\n }\n }\n }\n return -1;\n}\n","// W3C Design Tokens reader\n// Spec: docs/PROJECT_PLAN.md §10.1\n\nimport { parseCssColor } from \"./color.js\";\nimport type { ExtractedColors } from \"./tailwind.js\";\n\nexport function extractDtcgColors(tokens: unknown): ExtractedColors {\n const found: Record<string, string> = {};\n walk(tokens, [], found);\n const out: ExtractedColors = {};\n const background = found.background ?? found.bg;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground ?? found.fg;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n if (found.muted !== undefined) {\n out.muted = found.muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n const accent = found.accent ?? found.secondary;\n if (accent !== undefined) {\n out.accent = accent;\n }\n return out;\n}\n\nfunction walk(node: unknown, path: string[], found: Record<string, string>): void {\n if (!isRecord(node)) {\n return;\n }\n if (node.$type === \"color\") {\n const hex = colorValue(node.$value);\n const leaf = path[path.length - 1];\n if (hex !== undefined && leaf !== undefined && found[leaf] === undefined) {\n found[leaf] = hex;\n }\n return;\n }\n for (const [key, value] of Object.entries(node)) {\n if (key.startsWith(\"$\")) {\n continue;\n }\n walk(value, [...path, key], found);\n }\n}\n\nfunction colorValue(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n return parseCssColor(value);\n }\n if (isRecord(value) && typeof value.hex === \"string\") {\n return parseCssColor(value.hex);\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","// Static Tailwind v3 config + v4 @theme color extraction\n// Spec: docs/PROJECT_PLAN.md §10.3, spike S7\n\nimport { parseCssColor } from \"./color.js\";\n\nexport interface ExtractedColors {\n background?: string;\n foreground?: string;\n muted?: string;\n primary?: string;\n accent?: string;\n}\n\nconst COLOR_PROP = /--color-([a-zA-Z0-9-]+)\\s*:\\s*([^;]+);/g;\nconst CUSTOM_PROP = /--([a-zA-Z0-9-]+)\\s*:\\s*([^;]+);/g;\nconst SKIP_PREFIXES = new Set([\"chart\", \"sidebar\", \"ring\", \"border\", \"input\", \"destructive\"]);\n\nexport function extractTailwindV4Colors(css: string): ExtractedColors {\n const blocks = themeBlocks(css);\n const custom = collectCustomProperties(css);\n const fromTheme: Record<string, string> = {};\n for (const block of blocks) {\n COLOR_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = COLOR_PROP.exec(block)) !== null) {\n const name = match[1];\n const raw = match[2];\n if (name === undefined || raw === undefined || shouldSkip(name)) {\n continue;\n }\n fromTheme[name] = raw.trim();\n }\n }\n const resolved: Record<string, string> = {};\n for (const [name, raw] of Object.entries(fromTheme)) {\n const hex = resolveToHex(raw, custom, 0);\n if (hex !== undefined) {\n resolved[name] = hex;\n }\n }\n return mapBrandColors(resolved);\n}\n\nexport function extractTailwindV3Colors(source: string): ExtractedColors {\n const found: Record<string, string> = {};\n const re =\n /\\b(primary|brand|accent|background|foreground|muted|secondary)\\b\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(source)) !== null) {\n const name = match[1];\n const raw = match[2];\n if (name === undefined || raw === undefined) {\n continue;\n }\n const hex = parseCssColor(raw);\n if (hex !== undefined) {\n found[name] = hex;\n }\n }\n return mapBrandColors(found);\n}\n\nfunction themeBlocks(css: string): string[] {\n const blocks: string[] = [];\n const re = /@theme(?:\\s+inline)?\\s*\\{/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(css)) !== null) {\n const open = css.indexOf(\"{\", match.index);\n if (open === -1) {\n break;\n }\n const close = matchingBrace(css, open);\n if (close === -1) {\n break;\n }\n blocks.push(css.slice(open + 1, close));\n }\n return blocks;\n}\n\nfunction matchingBrace(source: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < source.length; i += 1) {\n const ch = source[i];\n if (ch === \"{\") {\n depth += 1;\n } else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return i;\n }\n }\n }\n return -1;\n}\n\nfunction collectCustomProperties(css: string): Map<string, string> {\n const props = new Map<string, string>();\n CUSTOM_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = CUSTOM_PROP.exec(css)) !== null) {\n const name = match[1];\n const value = match[2];\n if (name !== undefined && value !== undefined) {\n props.set(`--${name}`, value.trim());\n }\n }\n return props;\n}\n\nfunction resolveToHex(\n raw: string,\n custom: Map<string, string>,\n depth: number,\n): string | undefined {\n if (depth > 3) {\n return undefined;\n }\n const direct = parseCssColor(raw);\n if (direct !== undefined) {\n return direct;\n }\n const varMatch = /^var\\(\\s*(--[a-zA-Z0-9-]+)\\s*(?:,[^)]+)?\\)$/.exec(raw);\n if (varMatch === null) {\n return undefined;\n }\n const ref = varMatch[1];\n if (ref === undefined) {\n return undefined;\n }\n const next = custom.get(ref);\n if (next === undefined) {\n return undefined;\n }\n return resolveToHex(next, custom, depth + 1);\n}\n\nfunction shouldSkip(name: string): boolean {\n const root = name.split(\"-\")[0];\n return root !== undefined && SKIP_PREFIXES.has(root);\n}\n\nfunction mapBrandColors(found: Record<string, string>): ExtractedColors {\n const out: ExtractedColors = {};\n const background = found.background ?? found.bg;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground ?? found.fg;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n const muted = found[\"muted-foreground\"] ?? found.muted;\n if (muted !== undefined) {\n out.muted = muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n const accent = found.accent ?? found.secondary;\n if (accent !== undefined) {\n out.accent = accent;\n }\n return out;\n}\n","// Colour detection, free of every `node:` import so the browser demo runs the same code the CLI\n// does. Spec: docs/REVIEW_2026-09-15.md R0.\n//\n// Splitting this out is what makes /try show a visitor's own colors. `detect.ts` keeps the parts\n// that need disk or zlib (logo files, PNG sampling, README parsing); the colour work is pure\n// text and reaches both surfaces.\n\nimport type { Brand } from \"./schema.js\";\nimport { isNeutralHex, parseCssColor, readableOnBackground } from \"./color.js\";\nimport { extractCssRootColors } from \"./css-vars.js\";\nimport { extractDtcgColors } from \"./dtcg.js\";\nimport type { ProjectFiles } from \"./files.js\";\nimport { extractTailwindV3Colors, extractTailwindV4Colors, type ExtractedColors } from \"./tailwind.js\";\nimport { DEFAULT_BRAND_COLORS } from \"./schema.js\";\n\nexport interface FieldSource {\n field: string;\n source: string;\n}\n\n/** Sampling a PNG logo needs zlib, so the caller supplies it when it can. */\nexport type LogoColor = (files: ProjectFiles, path: string) => Promise<string | undefined>;\n\n/** Path helpers, kept local so this module never imports `node:path`. */\nfunction basename(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\nfunction relative(from: string, path: string): string {\n const prefix = from.endsWith(\"/\") ? from : `${from}/`;\n return path.startsWith(prefix) ? path.slice(prefix.length) : path;\n}\n\nexport async function detectColorsFrom(\n files: ProjectFiles,\n cwd: string,\n logoPath: string | undefined,\n sources: FieldSource[],\n notes: string[],\n logoColor: LogoColor = () => Promise.resolve(undefined),\n): Promise<Brand[\"colors\"]> {\n const merged: ExtractedColors = {};\n const paths = await files.list();\n\n const cssFiles = paths.filter((file) => file.endsWith(\".css\"));\n const cssContents = await Promise.all(\n cssFiles.map(async (file) => ({ file, css: await files.read(file) })),\n );\n for (const { file, css } of cssContents) {\n if (css === undefined) {\n continue;\n }\n const fromTheme = extractTailwindV4Colors(css);\n const fromRoot = extractCssRootColors(css);\n const rel = relative(cwd, file);\n applyColors(merged, fromTheme, sources, `Tailwind v4 @theme in ${rel}`);\n applyColors(merged, fromRoot, sources, `:root variables in ${rel}`);\n }\n\n const configFiles = paths.filter((file) => basename(file).startsWith(\"tailwind.config.\"));\n const configContents = await Promise.all(\n configFiles.map(async (file) => ({ file, source: await files.read(file) })),\n );\n for (const { file, source } of configContents) {\n if (source === undefined) {\n continue;\n }\n applyColors(\n merged,\n extractTailwindV3Colors(source),\n sources,\n `Tailwind config ${relative(cwd, file)}`,\n );\n }\n\n const tokenFile = paths.find((file) => file.endsWith(\".tokens.json\"));\n if (tokenFile !== undefined) {\n const raw = await files.read(tokenFile);\n if (raw !== undefined) {\n try {\n const parsed: unknown = JSON.parse(raw);\n applyColors(merged, extractDtcgColors(parsed), sources, relative(cwd, tokenFile));\n } catch (error) {\n if (error instanceof SyntaxError) {\n notes.push(`Could not parse design tokens file ${relative(cwd, tokenFile)}.`);\n } else {\n throw error;\n }\n }\n }\n }\n\n if (merged.primary === undefined && logoPath !== undefined) {\n const fromPng = logoPath.endsWith(\".png\") ? await logoColor(files, logoPath) : undefined;\n if (fromPng !== undefined) {\n merged.primary = fromPng;\n sources.push({ field: \"colors.primary\", source: `dominant color in ${logoPath}` });\n }\n const svg = logoPath.endsWith(\".svg\") ? await files.read(logoPath) : undefined;\n if (svg !== undefined) {\n const fromLogo = firstNonNeutralSvgColor(svg);\n if (fromLogo !== undefined) {\n merged.primary = fromLogo;\n sources.push({ field: \"colors.primary\", source: `SVG fill in ${logoPath}` });\n }\n }\n }\n\n // Say which colors are built-in defaults rather than anything found in this project.\n // Every other detected field prints its source, so staying silent here would let a user\n // read Shipseal's own red as their brand color.\n const fellBack = ([\"background\", \"foreground\", \"muted\", \"primary\", \"accent\"] as const).filter(\n (field) => merged[field] === undefined,\n );\n if (fellBack.length > 0) {\n notes.push(\n `Using built-in defaults for ${fellBack.map((f) => `colors.${f}`).join(\", \")}. ` +\n \"Nothing in this project set them. Edit .shipseal/brand.json to use your own.\",\n );\n }\n\n return {\n background: merged.background ?? DEFAULT_BRAND_COLORS.background,\n foreground: merged.foreground ?? DEFAULT_BRAND_COLORS.foreground,\n muted: merged.muted ?? DEFAULT_BRAND_COLORS.muted,\n primary: merged.primary ?? DEFAULT_BRAND_COLORS.primary,\n accent: merged.accent ?? DEFAULT_BRAND_COLORS.accent,\n };\n}\n\nfunction applyColors(\n target: ExtractedColors,\n incoming: ExtractedColors,\n sources: FieldSource[],\n source: string,\n): void {\n const keys = [\"background\", \"foreground\", \"muted\", \"primary\", \"accent\"] as const;\n for (const key of keys) {\n const value = incoming[key];\n if (value !== undefined && target[key] === undefined) {\n target[key] = value;\n sources.push({ field: `colors.${key}`, source });\n }\n }\n}\n\nexport function applyReadableMuted(\n colors: Brand[\"colors\"],\n sources: FieldSource[],\n notes: string[],\n): void {\n if (colors.muted === undefined || readableOnBackground(colors.background, colors.muted)) {\n return;\n }\n colors.muted = DEFAULT_BRAND_COLORS.muted;\n notes.push(\n `Muted text color failed WCAG AA large-text contrast (3:1) against background, so it was set to ${DEFAULT_BRAND_COLORS.muted}.`,\n );\n upsertSource(sources, \"colors.muted\", \"contrast adjustment\");\n}\n\nexport function applyReadableAccent(\n colors: Brand[\"colors\"],\n sources: FieldSource[],\n notes: string[],\n): void {\n if (colors.accent === undefined || readableOnBackground(colors.background, colors.accent)) {\n return;\n }\n colors.accent = colors.primary ?? DEFAULT_BRAND_COLORS.primary;\n notes.push(\"Accent failed contrast against background, so it uses the primary color.\");\n upsertSource(sources, \"colors.accent\", \"contrast adjustment\");\n}\n\nexport function upsertSource(sources: FieldSource[], field: string, source: string): void {\n const existing = sources.find((entry) => entry.field === field);\n if (existing !== undefined) {\n existing.source = source;\n return;\n }\n sources.push({ field, source });\n}\n\nfunction firstNonNeutralSvgColor(svg: string): string | undefined {\n const re = /(?:fill|stroke)=\"([^\"]+)\"/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(svg)) !== null) {\n const raw = match[1];\n if (raw === undefined || raw === \"none\" || raw === \"currentColor\") {\n continue;\n }\n const hex = parseCssColor(raw);\n if (hex !== undefined && !isNeutralHex(hex)) {\n return hex;\n }\n }\n return undefined;\n}\n","// Logo discovery\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst DIRECTORIES = [\"\", \"assets\", \"assets/brand\", \"public\", \"public/brand\", \".github\", \"docs\", \"static\", \"branding\"];\nconst ICON_NAMES = [\"icon.svg\", \"icon.png\"];\nconst NAMES = [\"logo.svg\", \"logo.png\", \"logo-light.svg\", \"logo-light.png\"];\nconst FALLBACKS = [...ICON_NAMES, \"favicon.svg\"];\n\nexport function findLogo(cwd: string): string | undefined {\n for (const dir of DIRECTORIES) {\n for (const name of NAMES) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return relative;\n }\n }\n }\n for (const dir of DIRECTORIES) {\n for (const name of FALLBACKS) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return relative;\n }\n }\n }\n return undefined;\n}\n\nexport function findLogoPair(cwd: string): { light: string; dark?: string } | undefined {\n const light = findLogo(cwd);\n if (light === undefined) {\n return undefined;\n }\n const darkNames = [\"logo-dark.svg\", \"logo-dark.png\"];\n for (const dir of DIRECTORIES) {\n for (const name of darkNames) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return { light, dark: relative };\n }\n }\n }\n return { light };\n}\n","// Minimal PNG reader for brand color detection.\n// Spec: docs/PROJECT_PLAN.md §10.3 (logo color detection)\n//\n// Logos are the only PNGs this reads, so it covers what logo exporters emit: 8 and 16 bit\n// depths, color types 0, 2, 3, 4 and 6, no interlacing. Anything else returns undefined and\n// the caller reports the color as not found rather than guessing. Decoding is done here\n// instead of with a library because `pngjs` would be a runtime dependency for one small job.\n\nimport { inflateSync } from \"node:zlib\";\n\nconst SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n\n/** Channels per pixel for each PNG color type. Index is the color type. */\nconst CHANNELS: Record<number, number> = { 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 };\n\nexport interface DecodedPng {\n width: number;\n height: number;\n /** Row-major RGBA, four bytes per pixel. */\n pixels: Uint8Array;\n}\n\nexport function decodePng(buffer: Buffer): DecodedPng | undefined {\n if (buffer.length < 8 || !buffer.subarray(0, 8).equals(SIGNATURE)) {\n return undefined;\n }\n\n let width = 0;\n let height = 0;\n let bitDepth = 0;\n let colorType = 0;\n let interlace = 0;\n let palette: Buffer | undefined;\n let paletteAlpha: Buffer | undefined;\n const idat: Buffer[] = [];\n\n let offset = 8;\n while (offset + 8 <= buffer.length) {\n const length = buffer.readUInt32BE(offset);\n const type = buffer.toString(\"ascii\", offset + 4, offset + 8);\n const start = offset + 8;\n const end = start + length;\n if (end > buffer.length) {\n return undefined;\n }\n\n if (type === \"IHDR\") {\n width = buffer.readUInt32BE(start);\n height = buffer.readUInt32BE(start + 4);\n bitDepth = buffer[start + 8] ?? 0;\n colorType = buffer[start + 9] ?? 0;\n interlace = buffer[start + 12] ?? 0;\n } else if (type === \"PLTE\") {\n palette = buffer.subarray(start, end);\n } else if (type === \"tRNS\") {\n paletteAlpha = buffer.subarray(start, end);\n } else if (type === \"IDAT\") {\n idat.push(buffer.subarray(start, end));\n } else if (type === \"IEND\") {\n break;\n }\n\n offset = end + 4; // skip the CRC\n }\n\n const channels = CHANNELS[colorType];\n if (\n width === 0 ||\n height === 0 ||\n channels === undefined ||\n interlace !== 0 ||\n (bitDepth !== 8 && bitDepth !== 16) ||\n idat.length === 0 ||\n (colorType === 3 && palette === undefined)\n ) {\n return undefined;\n }\n\n // Guard against a malformed header claiming an enormous image.\n if (width * height > 64_000_000) {\n return undefined;\n }\n\n let raw: Buffer;\n try {\n raw = inflateSync(Buffer.concat(idat));\n } catch {\n return undefined;\n }\n\n const bytesPerSample = bitDepth / 8;\n const bpp = channels * bytesPerSample;\n const stride = width * bpp;\n if (raw.length < height * (stride + 1)) {\n return undefined;\n }\n\n const unfiltered = unfilter(raw, height, stride, bpp);\n if (unfiltered === undefined) {\n return undefined;\n }\n\n return { width, height, pixels: toRgba(unfiltered, width, height, colorType, bytesPerSample, palette, paletteAlpha) };\n}\n\n/** Reverse the per-scanline filters defined in the PNG spec. */\nfunction unfilter(raw: Buffer, height: number, stride: number, bpp: number): Buffer | undefined {\n const out = Buffer.alloc(height * stride);\n let pos = 0;\n for (let y = 0; y < height; y++) {\n const filter = raw[pos];\n pos += 1;\n if (filter === undefined || filter > 4) {\n return undefined;\n }\n const rowStart = y * stride;\n const prevStart = rowStart - stride;\n for (let x = 0; x < stride; x++) {\n const value = raw[pos + x] ?? 0;\n const a = x >= bpp ? (out[rowStart + x - bpp] ?? 0) : 0;\n const b = y > 0 ? (out[prevStart + x] ?? 0) : 0;\n const c = x >= bpp && y > 0 ? (out[prevStart + x - bpp] ?? 0) : 0;\n let restored: number;\n switch (filter) {\n case 1: {\n restored = value + a;\n break;\n }\n case 2: {\n restored = value + b;\n break;\n }\n case 3: {\n restored = value + Math.floor((a + b) / 2);\n break;\n }\n case 4: {\n restored = value + paeth(a, b, c);\n break;\n }\n default: {\n restored = value;\n }\n }\n out[rowStart + x] = restored & 0xff;\n }\n pos += stride;\n }\n return out;\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n if (pa <= pb && pa <= pc) {\n return a;\n }\n return pb <= pc ? b : c;\n}\n\nfunction toRgba(\n data: Buffer,\n width: number,\n height: number,\n colorType: number,\n bytesPerSample: number,\n palette: Buffer | undefined,\n paletteAlpha: Buffer | undefined,\n): Uint8Array {\n const pixels = new Uint8Array(width * height * 4);\n const channels = CHANNELS[colorType] ?? 4;\n const bpp = channels * bytesPerSample;\n\n for (let i = 0; i < width * height; i++) {\n // For 16 bit samples the high byte is a close enough approximation for color picking.\n const at = (channel: number): number => data[i * bpp + channel * bytesPerSample] ?? 0;\n const out = i * 4;\n switch (colorType) {\n case 0: {\n const g = at(0);\n pixels[out] = g;\n pixels[out + 1] = g;\n pixels[out + 2] = g;\n pixels[out + 3] = 255;\n break;\n }\n case 2: {\n pixels[out] = at(0);\n pixels[out + 1] = at(1);\n pixels[out + 2] = at(2);\n pixels[out + 3] = 255;\n break;\n }\n case 3: {\n const index = at(0);\n pixels[out] = palette?.[index * 3] ?? 0;\n pixels[out + 1] = palette?.[index * 3 + 1] ?? 0;\n pixels[out + 2] = palette?.[index * 3 + 2] ?? 0;\n pixels[out + 3] = paletteAlpha?.[index] ?? 255;\n break;\n }\n case 4: {\n const g = at(0);\n pixels[out] = g;\n pixels[out + 1] = g;\n pixels[out + 2] = g;\n pixels[out + 3] = at(1);\n break;\n }\n default: {\n pixels[out] = at(0);\n pixels[out + 1] = at(1);\n pixels[out + 2] = at(2);\n pixels[out + 3] = at(3);\n }\n }\n }\n return pixels;\n}\n\n/**\n * Most common non-neutral color in a logo, as a hex string.\n *\n * Nearly transparent pixels are ignored so a transparent background does not win, and greys\n * are ignored because a logo's black wordmark is not its brand color. Colors are bucketed\n * into 16 levels per channel so anti-aliased edges group with the solid fill they belong to,\n * then the winning bucket reports the average of the real pixels inside it rather than the\n * bucket centre, which would drift the hue.\n */\nexport function dominantNonNeutralColor(png: DecodedPng): string | undefined {\n const buckets = new Map<number, { count: number; r: number; g: number; b: number }>();\n\n for (let i = 0; i < png.pixels.length; i += 4) {\n const a = png.pixels[i + 3] ?? 0;\n if (a < 128) {\n continue;\n }\n const r = png.pixels[i] ?? 0;\n const g = png.pixels[i + 1] ?? 0;\n const b = png.pixels[i + 2] ?? 0;\n if (Math.max(r, g, b) - Math.min(r, g, b) < 16) {\n continue; // grey, including pure black and white\n }\n const key = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);\n const bucket = buckets.get(key);\n if (bucket === undefined) {\n buckets.set(key, { count: 1, r, g, b });\n } else {\n bucket.count += 1;\n bucket.r += r;\n bucket.g += g;\n bucket.b += b;\n }\n }\n\n let best: { count: number; r: number; g: number; b: number } | undefined;\n for (const bucket of buckets.values()) {\n if (best === undefined || bucket.count > best.count) {\n best = bucket;\n }\n }\n if (best === undefined) {\n return undefined;\n }\n\n const channel = (total: number): string =>\n Math.round(total / best.count)\n .toString(16)\n .padStart(2, \"0\");\n return `#${channel(best.r)}${channel(best.g)}${channel(best.b)}`;\n}\n","// Brand detection pipeline\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { z } from \"zod\";\nimport { ensureForegroundContrast } from \"./color.js\";\nimport {\n applyReadableAccent,\n applyReadableMuted,\n detectColorsFrom,\n upsertSource,\n type FieldSource,\n} from \"./detect-colors.js\";\nimport type { ProjectFiles } from \"./files.js\";\nimport { findLogoPair } from \"./logo.js\";\nimport { decodePng, dominantNonNeutralColor } from \"./png.js\";\n// One implementation only. detect.ts previously carried its own copies of these, which\n// drifted from the ones in sources/readme.ts and read a YAML comment as the project name.\nimport { extractH1, extractTagline } from \"../sources/readme.js\";\nimport {\n DEFAULT_BRAND_FONTS,\n type Brand,\n} from \"./schema.js\";\n\n\n\n\n\n/** Path helpers, kept local so this module stays free of `node:path` and reaches the browser. */\nfunction basename(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\n\nexport interface BrandDetection {\n brand: Brand;\n sources: FieldSource[];\n notes: string[];\n}\n\nconst packageSchema = z.object({\n private: z.boolean().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n homepage: z.string().optional(),\n repository: z.union([z.string(), z.object({ url: z.string().optional() })]).optional(),\n});\n\n\n/**\n * Detection over any source. `root` is only used to make reported paths readable, so the\n * GitHub implementation can pass the repository slug.\n */\nexport async function detectBrandFrom(files: ProjectFiles, cwd = \".\"): Promise<BrandDetection> {\n const sources: FieldSource[] = [];\n const notes: string[] = [];\n const pkg = await readPackage(files);\n const readme = await files.read(\"README.md\");\n\n const name = detectName(pkg, readme, cwd, sources);\n const tagline = detectTagline(pkg, readme, sources);\n const url = await detectUrl(files, pkg, cwd, sources);\n const logo = findLogoPair(cwd);\n if (logo !== undefined) {\n sources.push({ field: \"logo\", source: logo.light });\n }\n\n const colors = await detectColorsFrom(files, cwd, logo?.light, sources, notes, dominantLogoColor);\n const contrast = ensureForegroundContrast(colors.background, colors.foreground);\n if (contrast.adjusted) {\n colors.foreground = contrast.foreground;\n notes.push(\n `Foreground failed WCAG AA large-text contrast (3:1) against background, so it was set to ${contrast.foreground}.`,\n );\n upsertSource(sources, \"colors.foreground\", \"contrast adjustment\");\n }\n applyReadableMuted(colors, sources, notes);\n applyReadableAccent(colors, sources, notes);\n\n const brand: Brand = {\n version: 1,\n name,\n colors,\n fonts: {\n heading: { ...DEFAULT_BRAND_FONTS.heading },\n body: { ...DEFAULT_BRAND_FONTS.body },\n mono: { ...DEFAULT_BRAND_FONTS.mono },\n },\n radius: 16,\n theme: \"dark\",\n style: \"minimal\",\n tokens: null,\n };\n if (tagline !== undefined) {\n brand.tagline = tagline;\n }\n if (url !== undefined) {\n brand.url = url;\n }\n if (logo !== undefined) {\n brand.logo = logo.dark === undefined ? { light: logo.light } : { light: logo.light, dark: logo.dark };\n }\n sources.push({ field: \"fonts\", source: \"built-in Geist / vendored Geist Mono\" });\n return { brand, sources, notes };\n}\n\nfunction detectName(\n pkg: z.infer<typeof packageSchema> | undefined,\n readme: string | undefined,\n cwd: string,\n sources: FieldSource[],\n): string {\n // A private package.json is a workspace root, and its name is plumbing, not a brand.\n // The shipseal repo's own root is \"shipseal-monorepo\", which is not what to put on a card.\n if (pkg?.name !== undefined && pkg.private !== true) {\n const fromPkg = stripScope(pkg.name);\n const h1 = readme === undefined ? undefined : extractH1(readme);\n if (h1 !== undefined && h1.toLowerCase() === fromPkg.toLowerCase() && h1 !== fromPkg) {\n sources.push({ field: \"name\", source: \"README.md H1\" });\n return h1;\n }\n sources.push({ field: \"name\", source: \"package.json#name\" });\n return fromPkg;\n }\n const h1 = readme === undefined ? undefined : extractH1(readme);\n if (h1 !== undefined) {\n sources.push({ field: \"name\", source: \"README.md H1\" });\n return h1;\n }\n sources.push({ field: \"name\", source: \"directory name\" });\n const fromDir = basename(cwd);\n return fromDir.length > 0 ? fromDir : \"project\";\n}\n\nfunction detectTagline(\n pkg: z.infer<typeof packageSchema> | undefined,\n readme: string | undefined,\n sources: FieldSource[],\n): string | undefined {\n if (pkg?.description !== undefined && pkg.description.trim().length > 0) {\n sources.push({ field: \"tagline\", source: \"package.json#description\" });\n return pkg.description.trim();\n }\n if (readme !== undefined) {\n const tagline = extractTagline(readme);\n if (tagline !== undefined) {\n sources.push({ field: \"tagline\", source: \"README.md first paragraph\" });\n return tagline;\n }\n }\n return undefined;\n}\n\nasync function detectUrl(\n files: ProjectFiles,\n pkg: z.infer<typeof packageSchema> | undefined,\n cwd: string,\n sources: FieldSource[],\n): Promise<string | undefined> {\n if (pkg?.homepage !== undefined && pkg.homepage.length > 0) {\n sources.push({ field: \"url\", source: \"package.json#homepage\" });\n return pkg.homepage;\n }\n const repo = repositoryUrl(pkg?.repository);\n if (repo !== undefined) {\n sources.push({ field: \"url\", source: \"package.json#repository\" });\n return repo;\n }\n const remote = await files.gitRemote?.();\n if (remote !== undefined) {\n sources.push({ field: \"url\", source: \"git remote origin\" });\n return remote;\n }\n return undefined;\n}\n\n\n\n\n\n\nasync function readPackage(files: ProjectFiles): Promise<z.infer<typeof packageSchema> | undefined> {\n const raw = await files.read(\"package.json\");\n if (raw === undefined) {\n return undefined;\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n const result = packageSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n } catch (error) {\n if (error instanceof SyntaxError) {\n return undefined;\n }\n throw error;\n }\n}\n\n\n\n\n\nfunction stripScope(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1] ?? name;\n}\n\n\nfunction repositoryUrl(repository: z.infer<typeof packageSchema>[\"repository\"]): string | undefined {\n if (typeof repository === \"string\") {\n return normalizeGitUrl(repository);\n }\n if (repository?.url !== undefined) {\n return normalizeGitUrl(repository.url);\n }\n return undefined;\n}\n\nexport function normalizeGitUrl(url: string): string {\n const ssh = /^git@([^:]+):(.+)$/.exec(url);\n if (ssh !== null && ssh[1] !== undefined && ssh[2] !== undefined) {\n return `https://${ssh[1]}/${ssh[2].replace(/\\.git$/, \"\")}`;\n }\n return url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n}\n\n/**\n * Dominant non-neutral color of a PNG logo, or undefined when the file cannot be read or\n * carries no color. Detection reports the color as not found rather than falling back to a\n * built-in default that would be presented to the user as \"your brand\".\n */\nasync function dominantLogoColor(files: ProjectFiles, path: string): Promise<string | undefined> {\n const buffer = await files.readBinary(path);\n if (buffer === undefined) {\n return undefined;\n }\n const png = decodePng(Buffer.from(buffer));\n if (png === undefined) {\n return undefined;\n }\n return dominantNonNeutralColor(png);\n}\n\n","// The disk half of brand detection. Split out so `detect.ts` carries no `node:` import and the\n// browser demo can run the same detection over the GitHub API (review R0). The split mirrors\n// `render/takumi.ts` and `render/takumi-node.ts`, for the same reason: one top-level Node\n// builtin is enough for Vite to externalise a module and serve /try a blank page.\n\nimport { execFile } from \"node:child_process\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { detectBrandFrom, normalizeGitUrl, type BrandDetection } from \"./detect.js\";\nimport type { ProjectFiles } from \"./files.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"coverage\",\n \".next\",\n \".astro\",\n \"out\",\n \"vendor\",\n]);\n\nexport async function detectBrand(cwd: string): Promise<BrandDetection> {\n return detectBrandFrom(diskFiles(cwd), cwd);\n}\n\n/** The disk implementation of the port, used by the CLI. Paths stay absolute here. */\nexport function diskFiles(cwd: string, maxDepth = 4): ProjectFiles {\n return {\n list: () => listFiles(cwd, maxDepth),\n read: async (path) => {\n try {\n return await readFile(isAbsolute(path) ? path : join(cwd, path), \"utf8\");\n } catch {\n return undefined;\n }\n },\n gitRemote: () => gitRemote(cwd),\n readBinary: async (path) => {\n try {\n return await readFile(isAbsolute(path) ? path : join(cwd, path));\n } catch {\n return undefined;\n }\n },\n };\n}\n\nasync function listFiles(root: string, maxDepth: number): Promise<string[]> {\n const out: string[] = [];\n const walk = async (dir: string, depth: number): Promise<void> => {\n if (depth < 0) {\n return;\n }\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n const nested: Promise<void>[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") && entry.name !== \".github\") {\n continue;\n }\n const path = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n nested.push(walk(path, depth - 1));\n } else {\n out.push(path);\n }\n }\n await Promise.all(nested);\n };\n await walk(root, maxDepth);\n return out;\n}\n\nasync function gitRemote(cwd: string): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd });\n return normalizeGitUrl(stdout.trim());\n } catch (error) {\n if (error instanceof Error) {\n return undefined;\n }\n throw error;\n }\n}\n","// init: detect brand, write .shipseal/brand.json + config.json, render sample\n// Spec: docs/PROJECT_PLAN.md §18.1\n\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\nimport { join } from \"node:path\";\nimport type { BrandDetection } from \"../brand/detect.js\";\nimport { detectBrand } from \"../brand/detect-node.js\";\nimport { brandSchema } from \"../brand/schema.js\";\nimport { DEFAULT_CONFIG, configSchema } from \"../config/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { generate } from \"../core/generate.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\n\nexport interface InitOptions {\n cwd: string;\n yes: boolean;\n force: boolean;\n}\n\nexport interface InitResult {\n brandPath: string;\n configPath: string;\n samplePath: string;\n detection: BrandDetection;\n}\n\nexport async function runInit(options: InitOptions): Promise<InitResult> {\n const detection = await detectBrand(options.cwd);\n const brandDir = join(options.cwd, \".shipseal\");\n const brandPath = join(brandDir, \"brand.json\");\n const configPath = join(brandDir, \"config.json\");\n\n if (!options.force && (existsSync(brandPath) || existsSync(configPath))) {\n throw new ShipsealError(\n \"init.exists\",\n \".shipseal/brand.json or config.json already exists.\",\n \"Re-run with --force to overwrite, or edit the files by hand.\",\n );\n }\n\n if (!options.yes) {\n const accepted = await confirmInit(detection);\n if (!accepted) {\n throw new ShipsealError(\n \"init.cancelled\",\n \"Init cancelled; no files were written.\",\n \"Re-run shipseal init and confirm, or pass --yes to accept detections.\",\n );\n }\n }\n\n const brand = brandSchema.parse(detection.brand);\n const config = configSchema.parse(DEFAULT_CONFIG);\n await mkdir(brandDir, { recursive: true });\n await writeFile(brandPath, `${JSON.stringify(brand, null, 2)}\\n`, \"utf8\");\n await writeFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\n await ensureGitignore(options.cwd);\n\n const sampleDir = join(brandDir, \"output\", \"sample\");\n await mkdir(sampleDir, { recursive: true });\n const samplePath = join(sampleDir, \"release-hero-og.png\");\n const renderer = await createTakumiRenderer();\n // Render the real release-hero template with the brand just detected. This used to be a\n // hard-coded card that said \"Shipseal\" for every user, which made the tool look like it had\n // ignored their project. The point of the sample is to show them their own brand.\n const fetchedAt = new Date().toISOString();\n const provenance = { source: \"brand\" as const, ref: \".shipseal/brand.json\", fetchedAt };\n const sampleFacts: Facts = {\n project: { name: fact(brand.name, provenance) },\n };\n if (brand.tagline !== undefined) {\n sampleFacts.project.tagline = fact(brand.tagline, provenance);\n }\n if (brand.url !== undefined) {\n sampleFacts.project.url = fact(brand.url, provenance);\n }\n const sample = await generate({\n event: { kind: \"release\", tag: \"v1.0.0\" },\n facts: sampleFacts,\n brand,\n config: { ...config, formats: [\"og\"], release: { ...config.release, templates: [\"release-hero\"] } },\n copy: deterministicCopy(sampleFacts),\n copyMode: \"deterministic\",\n renderer,\n themes: [brand.theme],\n generatedAt: fetchedAt,\n });\n const first = sample.files[0];\n if (first === undefined) {\n throw new ShipsealError(\n \"init.sample-failed\",\n \"Could not render the sample card.\",\n \"Run shipseal doctor to check fonts and the renderer.\",\n );\n }\n await writeFile(samplePath, first.bytes);\n\n return { brandPath, configPath, samplePath, detection };\n}\n\nasync function confirmInit(detection: BrandDetection): Promise<boolean> {\n if (!input.isTTY) {\n throw new ShipsealError(\n \"init.unattended\",\n \"stdin is not a TTY, so init cannot ask for confirmation.\",\n \"Re-run with --yes to accept the detected brand and write files.\",\n );\n }\n output.write(\"Detected brand:\\n\");\n for (const field of detection.sources) {\n output.write(` ${field.field}: from ${field.source}\\n`);\n }\n for (const note of detection.notes) {\n output.write(` note: ${note}\\n`);\n }\n const rl = createInterface({ input, output });\n try {\n const answer = await rl.question(\"Write .shipseal/brand.json and config.json? [y/N] \");\n return answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\";\n } finally {\n rl.close();\n }\n}\n\nasync function ensureGitignore(cwd: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n const entry = \".shipseal/output/\";\n if (!existsSync(path)) {\n await writeFile(path, `${entry}\\n`, \"utf8\");\n return;\n }\n const current = await readFile(path, \"utf8\");\n if (current.split(/\\r?\\n/).some((line) => line.trim() === entry || line.trim() === \".shipseal/output\")) {\n return;\n }\n const prefix = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n await writeFile(path, `${current}${prefix}${entry}\\n`, \"utf8\");\n}\n","// milestone: card for highest crossed threshold\n// Spec: docs/PROJECT_PLAN.md §18.3\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { milestoneCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport type MilestoneMetric = \"stars\" | \"downloads\" | \"contributors\";\n\nexport interface MilestoneFlags extends SharedFlags {\n metric?: string;\n threshold?: string;\n}\n\nexport interface MilestoneResult {\n dryRun: boolean;\n skipped: boolean;\n message?: string;\n facts: Facts;\n copy?: import(\"../copy/slots.js\").Copy;\n copyMode?: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runMilestone(flags: MilestoneFlags): Promise<MilestoneResult> {\n const cwd = flags.cwd;\n const config = overlayFormats(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const placeholder: ShipsealEvent = { kind: \"milestone\", metric: \"stars\", threshold: 0 };\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event: placeholder,\n skipNetwork: env.skipNetwork,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n if (env.githubToken !== undefined) {\n collectOpts.githubToken = env.githubToken;\n }\n if (env.fetchImpl !== undefined) {\n collectOpts.fetchImpl = env.fetchImpl;\n }\n const collected = await collectFacts(collectOpts);\n const selected = selectMilestone(collected, config, parseMetric(flags.metric), parseThreshold(flags.threshold));\n if (selected === undefined) {\n return {\n dryRun: flags.dryRun === true,\n skipped: true,\n message: \"No milestone threshold crossed. Nothing to generate.\",\n facts: collected,\n warnings: [],\n exitCode: 0,\n };\n }\n\n const fetchedAt = new Date().toISOString();\n const metricKey = selected.metric === \"downloads\" ? \"downloads\" : selected.metric;\n const facts: Facts = {\n ...collected,\n milestone: {\n metric: fact(selected.metric, { source: \"user-config\", ref: \"shipseal milestone --metric\", fetchedAt }),\n threshold: fact(selected.threshold, {\n source: \"user-config\",\n ref: `config.json milestones.${metricKey}`,\n fetchedAt,\n }),\n },\n };\n const event: ShipsealEvent = { kind: \"milestone\", metric: selected.metric, threshold: selected.threshold };\n const fallback = milestoneCopy(facts, selected.metric, selected.threshold);\n const resolved = await resolveCopy(facts, config, flags.copy === false, fallback);\n\n if (flags.dryRun === true) {\n const dry: MilestoneResult = {\n dryRun: true,\n skipped: false,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n const packed = await finishPack(packInput);\n return { ...packed, skipped: false };\n}\n\nexport function highestCrossed(thresholds: number[], current: number): number | undefined {\n const crossed = thresholds.filter((item) => current >= item).toSorted((a, b) => b - a);\n return crossed[0];\n}\n\nexport function selectMilestone(\n facts: Facts,\n config: Config,\n metric: MilestoneMetric | undefined,\n threshold: number | undefined,\n): { metric: MilestoneMetric; threshold: number } | undefined {\n const metrics: MilestoneMetric[] = metric === undefined ? [\"stars\", \"downloads\", \"contributors\"] : [metric];\n const candidates: Array<{ metric: MilestoneMetric; threshold: number }> = [];\n for (const item of metrics) {\n const current = currentValue(facts, item);\n if (current === undefined) {\n if (metric !== undefined) {\n throw missingMetric(item);\n }\n continue;\n }\n const list = thresholdsFor(config, item);\n if (threshold !== undefined) {\n if (metric !== undefined || list.includes(threshold)) {\n return { metric: item, threshold };\n }\n continue;\n }\n const crossed = highestCrossed(list, current);\n if (crossed !== undefined) {\n candidates.push({ metric: item, threshold: crossed });\n }\n }\n return candidates.toSorted(\n (a, b) => b.threshold - a.threshold || metrics.indexOf(a.metric) - metrics.indexOf(b.metric),\n )[0];\n}\n\nfunction currentValue(facts: Facts, metric: MilestoneMetric): number | undefined {\n if (metric === \"stars\") {\n return facts.metrics?.stars?.value;\n }\n if (metric === \"downloads\") {\n return facts.metrics?.weeklyDownloads?.value;\n }\n return facts.metrics?.contributorCount?.value;\n}\n\nfunction thresholdsFor(config: Config, metric: MilestoneMetric): number[] {\n if (metric === \"stars\") {\n return config.milestones?.stars ?? [];\n }\n if (metric === \"downloads\") {\n return config.milestones?.downloads ?? [];\n }\n return config.milestones?.contributors ?? [];\n}\n\nfunction parseMetric(value: string | undefined): MilestoneMetric | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === \"stars\" || value === \"downloads\" || value === \"contributors\") {\n return value;\n }\n throw new ShipsealError(\n \"milestone.bad-metric\",\n `Unknown metric \"${value}\".`,\n \"Use --metric stars, --metric downloads, or --metric contributors.\",\n );\n}\n\nfunction parseThreshold(value: string | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const parsed = Number.parseInt(value, 10);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new ShipsealError(\n \"milestone.bad-threshold\",\n `Invalid threshold \"${value}\".`,\n \"Pass a positive integer, for example --threshold 1000.\",\n );\n }\n return parsed;\n}\n\nfunction missingMetric(metric: MilestoneMetric): ShipsealError {\n if (metric === \"stars\") {\n return new ShipsealError(\n \"milestone.missing-stars\",\n \"Could not read GitHub stars for this repo.\",\n \"Set GITHUB_TOKEN, or confirm package.json repository points at a public GitHub repo.\",\n );\n }\n if (metric === \"downloads\") {\n return new ShipsealError(\n \"milestone.missing-downloads\",\n \"Could not read npm weekly downloads for this package.\",\n \"Confirm package.json name is published on npm, then retry without --dry-run.\",\n );\n }\n return new ShipsealError(\n \"milestone.missing-contributors\",\n \"Could not read the GitHub contributor count for this repo.\",\n \"Set GITHUB_TOKEN, or confirm package.json repository points at a public GitHub repo.\",\n );\n}\n","// release: generate the release pack\n// Spec: docs/PROJECT_PLAN.md §18.2\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig, mergeConfig } from \"../config/load.js\";\nimport { DEFAULT_CONFIG, type Config } from \"../config/schema.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport interface ReleaseFlags extends SharedFlags {\n tag?: string;\n from?: string;\n templates?: string;\n headline?: string;\n subheadline?: string;\n}\n\n/** Lowest kind worth announcing, most significant first. */\nconst ANNOUNCE_ORDER = [\"major\", \"minor\", \"patch\"] as const;\n\nexport interface ReleaseResult {\n dryRun: boolean;\n skipped?: boolean;\n message?: string;\n facts: Awaited<ReturnType<typeof collectFacts>>;\n copy: import(\"../copy/slots.js\").Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runRelease(flags: ReleaseFlags): Promise<ReleaseResult> {\n const cwd = flags.cwd;\n const config = overlayReleaseConfig(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const tag = flags.tag ?? (await gitCurrentTag(cwd));\n if (tag === undefined) {\n throw new ShipsealError(\n \"release.no-tag\",\n \"No git tag found for this release.\",\n \"Create a git tag, or pass --tag vX.Y.Z.\",\n );\n }\n const event: ShipsealEvent =\n flags.from === undefined\n ? { kind: \"release\", tag }\n : { kind: \"release\", tag, previousTag: flags.from };\n\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event,\n skipNetwork: env.skipNetwork,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n if (config.release?.changelogPath !== undefined) {\n collectOpts.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collectOpts.snippet = config.release.snippet;\n }\n if (env.githubToken !== undefined) {\n collectOpts.githubToken = env.githubToken;\n }\n if (env.fetchImpl !== undefined) {\n collectOpts.fetchImpl = env.fetchImpl;\n }\n const headline = flags.headline ?? config.release?.headline ?? undefined;\n if (headline !== undefined) {\n collectOpts.headline = headline;\n }\n const subheadline = flags.subheadline ?? config.release?.subheadline ?? undefined;\n if (subheadline !== undefined) {\n collectOpts.subheadline = subheadline;\n }\n const facts = await collectFacts(collectOpts);\n\n // Below the configured threshold there is nothing worth posting. Reported the same way\n // `milestone` reports an uncrossed threshold: exit 0, `skipped` true, and say why.\n const announce = config.release?.announce ?? \"patch\";\n const kind = facts.release?.kind?.value;\n if (kind !== undefined && ANNOUNCE_ORDER.indexOf(kind) > ANNOUNCE_ORDER.indexOf(announce)) {\n return {\n dryRun: flags.dryRun === true,\n skipped: true,\n message: `This is a ${kind} release and release.announce is \"${announce}\". Nothing to generate.`,\n facts,\n copy: deterministicCopy(facts, config.release?.maxHighlights, brand.name),\n copyMode: \"deterministic\",\n warnings: [],\n exitCode: 0,\n };\n }\n\n const noCopy = flags.copy === false;\n const resolved = await resolveCopy(facts, config, noCopy, deterministicCopy(facts, config.release?.maxHighlights, brand.name));\n\n if (flags.dryRun === true) {\n const dry: ReleaseResult = {\n dryRun: true,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n return finishPack(packInput);\n}\n\nfunction overlayReleaseConfig(config: Config, flags: ReleaseFlags): Config {\n const overlay = overlayFormats(config, flags);\n if (flags.templates === undefined) {\n return overlay;\n }\n return mergeConfig(DEFAULT_CONFIG, {\n ...overlay,\n release: {\n ...overlay.release,\n templates: flags.templates\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0),\n },\n });\n}\n","// Release stories: an ordered set of pages built from release facts, each rendered by the\n// `story-page` template. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n//\n// Page order is fixed: cover, one page per change, an optional code page, an optional\n// comparison of supplied screenshots, then the upgrade page.\n\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { cleanLine, deterministicCopy, firstSentence } from \"../copy/deterministic.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact, Facts, StoryPage } from \"../facts/schema.js\";\nimport { ShipsealError } from \"./errors.js\";\nimport { generate, type GenerateInput, type GenerateResult } from \"./generate.js\";\n\nconst DEFAULT_CHANGE_PAGES = 4;\nconst STORY_FORMATS = \"portrait, square, og, github-social, x, linkedin, or producthunt\";\n\nexport function storyFacts(\n facts: Facts,\n config: Config,\n brand: Pick<Brand, \"name\" | \"tagline\">,\n generatedAt: string,\n): Facts {\n const release = facts.release;\n if (release === undefined) {\n throw new ShipsealError(\n \"story.no-release\",\n \"No release facts are available for a story.\",\n \"Choose a published release or pass --tag to a local repository.\",\n );\n }\n const copy = deterministicCopy(facts, config.release?.maxHighlights, brand.name);\n const configured = (value: string, ref: string): Fact<string> =>\n fact(value, { source: \"user-config\", ref, fetchedAt: generatedAt });\n\n const changes = [...release.breaking, ...release.features, ...release.fixes];\n // The cover headline carries the provenance of the change it was taken from, so a card\n // number or claim is always traceable back to the release notes.\n const headlineSource =\n release.headline ??\n changes.find((item) => cleanLine(firstSentence(item.value)) === copy.headline) ??\n release.version;\n const pages: StoryPage[] = [\n {\n kind: \"cover\",\n title: fact(copy.headline, headlineSource.provenance),\n // The brand file is a declared source like any other, so prefer its tagline over the\n // \"Release notes\" placeholder. Only fall back when nothing describes the project.\n body:\n release.subheadline ??\n facts.project.tagline ??\n (brand.tagline === undefined\n ? fact(\"Release notes\", release.tag.provenance)\n : fact(brand.tagline, {\n source: \"user-config\",\n ref: \"brand.json#tagline\",\n fetchedAt: generatedAt,\n })),\n },\n ];\n\n for (const item of changes.slice(0, config.release?.maxHighlights ?? DEFAULT_CHANGE_PAGES)) {\n // The title is the entry's first sentence, so the body is what follows it. Passing the\n // whole entry would print that sentence twice on the same page.\n const collapsed = item.value.replaceAll(/\\s+/g, \" \").trim();\n const sentence = firstSentence(collapsed);\n const remainder = collapsed.slice(sentence.length).trim();\n pages.push({\n kind: \"change\",\n title: fact(cleanLine(sentence), item.provenance),\n body: fact(remainder.length > 0 ? cleanLine(remainder) : \"\", item.provenance),\n });\n }\n\n if (release.codeSnippet !== undefined) {\n pages.push({\n kind: \"code\",\n title: fact(\"Code example\", release.codeSnippet.provenance),\n body: fact(release.codeSnippet.value.code, release.codeSnippet.provenance),\n });\n }\n\n const options = config.release?.story;\n if (options?.before !== undefined && options.after !== undefined) {\n pages.push({\n kind: \"comparison\",\n title: configured(\"Before and after\", \"release.story.before + release.story.after\"),\n body: configured(\"Supplied screenshots\", \"release.story\"),\n before: configured(options.before, \"release.story.before\"),\n after: configured(options.after, \"release.story.after\"),\n });\n }\n\n const hasUpgrade = options?.upgrade !== undefined && options.upgrade.trim().length > 0;\n let upgrade: Fact<string>;\n if (hasUpgrade && options?.upgrade !== undefined) {\n // Trimmed, not cleaned: this is a command the maintainer expects to be copied and run.\n // cleanLine capitalises the first letter and collapses newlines, which breaks both a\n // `pnpm add ...` line and a multi-line block.\n upgrade = configured(options.upgrade.trim(), \"release.story.upgrade\");\n } else {\n // Never infer an upgrade command from a package name: the release may be breaking, and\n // an invented command is a number-shaped claim the manifest cannot back.\n const repo = facts.project.repo;\n upgrade =\n repo === undefined\n ? fact(copy.cta, facts.project.url?.provenance ?? facts.project.name.provenance)\n : fact(\n `Read the release notes at github.com/${repo.value}/releases/tag/${encodeURIComponent(release.tag.value)}`,\n repo.provenance,\n );\n }\n pages.push({\n kind: \"upgrade\",\n title: fact(hasUpgrade ? \"How to upgrade\" : \"Get the release\", upgrade.provenance),\n body: upgrade,\n });\n\n return { ...facts, story: pages };\n}\n\nexport async function generateStory(input: GenerateInput): Promise<GenerateResult> {\n const facts = storyFacts(input.facts, input.config, input.brand, input.generatedAt);\n const pages = facts.story ?? [];\n const result: GenerateResult = {\n files: [],\n warnings: [],\n missing: [],\n facts,\n copy: input.copy,\n copyMode: \"deterministic\",\n generatedAt: input.generatedAt,\n computed: {},\n };\n const formats = input.config.formats ?? [\"portrait\"];\n if (formats.length === 0 || formats.includes(\"readme-banner\")) {\n throw new ShipsealError(\n \"story.bad-format\",\n \"The story format selection contains no supported output or includes readme-banner.\",\n `Use ${STORY_FORMATS}.`,\n );\n }\n\n for (const [index, page] of pages.entries()) {\n // One renderer instance is shared across pages, so renders are sequential by design.\n // eslint-disable-next-line no-await-in-loop\n const rendered = await generate({\n ...input,\n facts: { ...facts, story: [page] },\n config: {\n ...input.config,\n formats,\n release: { ...input.config.release, templates: [\"story-page\"] },\n },\n });\n const id = `story-${String(index + 1).padStart(2, \"0\")}-${page.kind}`;\n result.files.push(\n ...rendered.files.map((file) => ({\n ...file,\n fileName: file.fileName.replace(\"story-page\", id),\n })),\n );\n result.warnings.push(\n ...rendered.warnings.map((warning) => ({\n ...warning,\n slot: `page-${String(index + 1)}.${warning.slot}`,\n })),\n );\n result.missing.push(...rendered.missing);\n result.computed[`story.pages[${String(index)}]`] = {\n value: {\n kind: page.kind,\n files: result.files\n .filter((file) => file.fileName.startsWith(id))\n .map((file) => file.fileName),\n },\n computedFrom: [`story[${String(index)}].title`, `story[${String(index)}].body`],\n };\n }\n\n if (facts.release?.codeSnippet === undefined) {\n result.missing.push({\n template: \"story-page\",\n fact: \"release.codeSnippet\",\n effect: \"code page omitted\",\n });\n }\n if (pages.every((page) => page.kind !== \"change\")) {\n result.missing.push({\n template: \"story-page\",\n fact: \"release.features\",\n effect: \"change pages omitted because release notes have no changes\",\n });\n }\n return result;\n}\n","// Carousel PDF and ZIP writers. Both are hand-rolled rather than pulled in as dependencies:\n// the output is image streams and stored entries, which needs no compression library\n// (AGENTS.md rule 6). Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { GeneratedFile } from \"../core/generate.js\";\n\nconst encode = (value: string): Uint8Array => new TextEncoder().encode(value);\n\nconst isJpeg = (bytes: Uint8Array): boolean => bytes[0] === 255 && bytes[1] === 216;\n\nexport function joinBytes(parts: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n result.set(part, offset);\n offset += part.length;\n }\n return result;\n}\n\n/**\n * Image-only PDF: each JPEG becomes one page as a DCTDecode stream, so the page is the exact\n * rendered layout rather than a reflow of it. Pages are placed at half the pixel size, which\n * puts a 1080x1350 render on a 540x675pt page at 144dpi.\n *\n * Object numbering: 1 is the catalog, 2 the page tree, then each page contributes three\n * objects (page, image, content stream) at 3 + index * 3.\n */\nexport function carouselPdf(\n pages: Pick<GeneratedFile, \"bytes\" | \"width\" | \"height\">[],\n): Uint8Array {\n if (pages.length === 0 || pages.some((page) => !isJpeg(page.bytes))) {\n throw new ShipsealError(\n \"pdf.invalid-pages\",\n \"A carousel requires nonempty JPEG pages.\",\n \"Render the story as JPEG before building the PDF.\",\n );\n }\n const objects: Uint8Array[] = [\n encode(\"<< /Type /Catalog /Pages 2 0 R >>\"),\n encode(\n `<< /Type /Pages /Count ${String(pages.length)} /Kids [${pages\n .map((_, index) => `${String(3 + index * 3)} 0 R`)\n .join(\" \")}] >>`,\n ),\n ];\n for (const [index, page] of pages.entries()) {\n const id = 3 + index * 3;\n const width = page.width / 2;\n const height = page.height / 2;\n objects.push(\n encode(\n `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${String(width)} ${String(height)}] ` +\n `/Resources << /XObject << /Image ${String(id + 1)} 0 R >> >> ` +\n `/Contents ${String(id + 2)} 0 R >>`,\n ),\n );\n // Takumi renders RGB, so DeviceRGB matches every JPEG it produces.\n objects.push(\n joinBytes([\n encode(\n `<< /Type /XObject /Subtype /Image /Width ${String(page.width)} ` +\n `/Height ${String(page.height)} /ColorSpace /DeviceRGB /BitsPerComponent 8 ` +\n `/Filter /DCTDecode /Length ${String(page.bytes.length)} >>\\nstream\\n`,\n ),\n page.bytes,\n encode(\"\\nendstream\"),\n ]),\n );\n const content = `q ${String(width)} 0 0 ${String(height)} 0 0 cm /Image Do Q`;\n objects.push(\n encode(`<< /Length ${String(encode(content).length)} >>\\nstream\\n${content}\\nendstream`),\n );\n }\n\n const header = encode(\"%PDF-1.4\\n%Shipseal\\n\");\n const parts: Uint8Array[] = [header];\n const offsets: number[] = [];\n let position = header.length;\n for (const [index, object] of objects.entries()) {\n offsets.push(position);\n const bytes = joinBytes([encode(`${String(index + 1)} 0 obj\\n`), object, encode(\"\\nendobj\\n\")]);\n parts.push(bytes);\n position += bytes.length;\n }\n const size = objects.length + 1;\n parts.push(\n encode(\n `xref\\n0 ${String(size)}\\n0000000000 65535 f \\n` +\n offsets.map((offset) => `${String(offset).padStart(10, \"0\")} 00000 n \\n`).join(\"\") +\n `trailer\\n<< /Size ${String(size)} /Root 1 0 R >>\\n` +\n `startxref\\n${String(position)}\\n%%EOF\\n`,\n ),\n );\n return joinBytes(parts);\n}\n\nfunction crc32(bytes: Uint8Array): number {\n let value = 0xffffffff;\n for (const byte of bytes) {\n value ^= byte;\n for (let bit = 0; bit < 8; bit += 1) {\n value = (value >>> 1) ^ ((value & 1) === 1 ? 0xedb88320 : 0);\n }\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\n/**\n * ZIP with STORE and no compression: PNG and JPEG are already compressed, so deflating them\n * costs time and saves nothing. Every timestamp is the fixed DOS date 1980-01-01 (0x0021) so\n * the same inputs always produce the same archive bytes.\n */\nexport function zipFiles(files: Array<{ name: string; bytes: Uint8Array }>): Uint8Array {\n const FIXED_DOS_DATE = 33;\n const names = new Set<string>();\n const local: Uint8Array[] = [];\n const central: Uint8Array[] = [];\n let offset = 0;\n\n for (const file of files) {\n if (!/^[a-zA-Z0-9_.-]+$/.test(file.name) || names.has(file.name)) {\n throw new ShipsealError(\n \"zip.bad-name\",\n \"An archive file name is unsafe or duplicated.\",\n \"Use unique file names without path separators.\",\n );\n }\n names.add(file.name);\n const name = encode(file.name);\n const checksum = crc32(file.bytes);\n\n // Local file header: signature, version needed, flags, method, time, date, crc,\n // compressed size, uncompressed size, name length, extra length.\n const header = new Uint8Array(30);\n const headerView = new DataView(header.buffer);\n headerView.setUint32(0, 0x04034b50, true);\n headerView.setUint16(4, 20, true);\n headerView.setUint16(12, FIXED_DOS_DATE, true);\n headerView.setUint32(14, checksum, true);\n headerView.setUint32(18, file.bytes.length, true);\n headerView.setUint32(22, file.bytes.length, true);\n headerView.setUint16(26, name.length, true);\n local.push(header, name, file.bytes);\n\n // Central directory entry: as above, plus version made by and the local header offset.\n const entry = new Uint8Array(46);\n const entryView = new DataView(entry.buffer);\n entryView.setUint32(0, 0x02014b50, true);\n entryView.setUint16(4, 20, true);\n entryView.setUint16(6, 20, true);\n entryView.setUint16(14, FIXED_DOS_DATE, true);\n entryView.setUint32(16, checksum, true);\n entryView.setUint32(20, file.bytes.length, true);\n entryView.setUint32(24, file.bytes.length, true);\n entryView.setUint16(28, name.length, true);\n entryView.setUint32(42, offset, true);\n central.push(entry, name);\n offset += header.length + name.length + file.bytes.length;\n }\n\n // End of central directory: entry counts, directory size, directory offset.\n const end = new Uint8Array(22);\n const endView = new DataView(end.buffer);\n endView.setUint32(0, 0x06054b50, true);\n endView.setUint16(8, files.length, true);\n endView.setUint16(10, files.length, true);\n endView.setUint32(12, central.reduce((sum, part) => sum + part.length, 0), true);\n endView.setUint32(16, offset, true);\n return joinBytes([...local, ...central, end]);\n}\n","// One pack builder shared by `shipseal preview`, `shipseal story` and the browser demo, so\n// every surface renders the same bytes. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { z } from \"zod\";\nimport { brandSchema, type Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { generate, type GenerateInput } from \"../core/generate.js\";\nimport { generateStory } from \"../core/story.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { V1_FORMAT_IDS, type FormatId } from \"../formats.js\";\nimport { carouselPdf, zipFiles } from \"../outputs/downloads.js\";\nimport { buildManifest } from \"../outputs/manifest.js\";\nimport type { RendererAdapter } from \"../render/adapter.js\";\n\n/** Every format the `story-page` template declares, in the order the selector lists them. */\nconst STORY_FORMATS: FormatId[] = [\n \"portrait\",\n \"square\",\n \"og\",\n \"github-social\",\n \"x\",\n \"linkedin\",\n \"producthunt\",\n];\n\nconst encodeJson = (value: unknown): Uint8Array =>\n new TextEncoder().encode(`${JSON.stringify(value, null, 2)}\\n`);\n\nexport const selectionSchema = z\n .object({\n pack: z.enum([\"story\", \"release\"]).default(\"story\"),\n style: brandSchema.shape.style,\n theme: z.enum([\"dark\", \"light\"]),\n accent: brandSchema.shape.colors.shape.primary,\n headline: z.string().max(500).default(\"\"),\n upgrade: z.string().max(4000).default(\"\"),\n format: z\n .enum([...STORY_FORMATS, \"all\"])\n .default(\"portrait\"),\n })\n .strict();\nexport type StudioSelection = z.infer<typeof selectionSchema>;\n\nexport function selectedConfig(config: Config, selection: StudioSelection): Config {\n const formats: FormatId[] =\n selection.format === \"all\"\n ? selection.pack === \"story\"\n ? [...STORY_FORMATS]\n : [...V1_FORMAT_IDS]\n : [selection.format];\n const landscape = new Set<string>(V1_FORMAT_IDS);\n if (selection.pack === \"release\" && formats.some((format) => !landscape.has(format))) {\n throw new ShipsealError(\n \"preview.format\",\n \"The standard release templates do not support this format.\",\n \"Choose a landscape format or switch to a story pack.\",\n );\n }\n return {\n ...config,\n formats,\n release: {\n ...config.release,\n headline: selection.headline || null,\n story: { ...config.release?.story, upgrade: selection.upgrade },\n },\n output: { imageFormat: \"png\" },\n };\n}\n\nexport function selectedBrand(brand: Brand, selection: StudioSelection): Brand {\n // `theme` stays as stored: it is the native polarity of the palette, not the requested\n // render theme, which travels separately in GenerateInput.themes.\n return {\n ...brand,\n style: selection.style,\n colors: { ...brand.colors, primary: selection.accent },\n };\n}\n\nexport async function buildStudioPack(input: {\n facts: Facts;\n brand: Brand;\n config: Config;\n selection: StudioSelection;\n renderer: RendererAdapter;\n version: string;\n generatedAt: string;\n logos?: GenerateInput[\"logos\"];\n images?: GenerateInput[\"images\"];\n brandSource?: string;\n}) {\n const release = input.facts.release;\n if (release === undefined) {\n throw new ShipsealError(\n \"preview.no-release\",\n \"No release is selected.\",\n \"Load a repository release first.\",\n );\n }\n const config = selectedConfig(input.config, input.selection);\n const brand = selectedBrand(input.brand, input.selection);\n const facts: Facts = { ...input.facts, release: { ...release } };\n if (input.selection.headline) {\n facts.release = {\n ...release,\n headline: fact(input.selection.headline, {\n source: \"user-config\",\n ref: \"release.headline\",\n fetchedAt: input.generatedAt,\n }),\n };\n }\n\n const event = { kind: \"release\" as const, tag: release.tag.value };\n const request: GenerateInput = {\n event,\n facts,\n brand,\n config,\n copy: deterministicCopy(facts, config.release?.maxHighlights, brand.name),\n copyMode: \"deterministic\",\n renderer: input.renderer,\n themes: [input.selection.theme],\n generatedAt: input.generatedAt,\n };\n if (input.logos !== undefined) {\n request.logos = input.logos;\n }\n if (input.images !== undefined) {\n request.images = input.images;\n }\n\n const result = await (input.selection.pack === \"story\" ? generateStory : generate)(request);\n const manifest = buildManifest({ result, event, brand, shipsealVersion: input.version });\n manifest.brand.source = input.brandSource ?? \".shipseal/brand.json + preview selections\";\n const downloads = result.files.map((file) => ({ name: file.fileName, bytes: file.bytes }));\n\n if (input.selection.pack === \"story\") {\n // The PDF pages are re-rendered as JPEG: a carousel embeds DCTDecode streams directly,\n // so the same layout is reused rather than reflowed.\n const pdfFormat = config.formats?.[0] ?? \"portrait\";\n const jpeg = await generateStory({\n ...request,\n config: { ...config, formats: [pdfFormat], output: { imageFormat: \"jpeg\" } },\n });\n const pdf = carouselPdf(jpeg.files);\n downloads.push({ name: \"story.pdf\", bytes: pdf });\n manifest.computed[\"story.pdf\"] = {\n value: { format: pdfFormat, pages: jpeg.files.length, bytes: pdf.length },\n computedFrom: [\"story\"],\n };\n }\n\n downloads.push(\n { name: \"brand.json\", bytes: encodeJson(brand) },\n { name: \"config.json\", bytes: encodeJson(config) },\n { name: \"manifest.json\", bytes: encodeJson(manifest) },\n );\n return { result, manifest, downloads, archive: zipFiles(downloads), brand, config };\n}\n","// `shipseal story`: an ordered release story as images, a PDF carousel and a ZIP.\n// Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { GenerateInput } from \"../core/generate.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { buildStudioPack, selectionSchema } from \"../studio/pack.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport { loadLogos, readShipsealVersion } from \"./shared.js\";\n\nconst STORY_IMAGE_LABELS = [\"before\", \"after\"] as const;\nconst MAX_STORY_IMAGE_BYTES = 5_000_000;\n\ntype StoryImage = NonNullable<GenerateInput[\"images\"]>[number];\n\n/**\n * Screenshots are supplied by the maintainer, never generated or captured here: no headless\n * browser is a hard rule (AGENTS.md rule 2).\n */\nasync function readStoryImage(cwd: string, label: string, path: string): Promise<StoryImage> {\n let data: Uint8Array;\n try {\n data = await readFile(resolve(cwd, path));\n } catch (error) {\n throw new ShipsealError(\n \"story.image-missing\",\n `Could not read the ${label} screenshot: ${path}.`,\n \"Set release.story.before and release.story.after to existing PNG or JPEG files.\",\n { cause: error },\n );\n }\n const png = data[0] === 137 && data[1] === 80 && data[2] === 78 && data[3] === 71;\n const jpeg = data[0] === 255 && data[1] === 216;\n if ((!png && !jpeg) || data.length > MAX_STORY_IMAGE_BYTES) {\n throw new ShipsealError(\n \"story.image-invalid\",\n `The ${label} screenshot is not a supported image or exceeds the size limit.`,\n \"Use a PNG or JPEG smaller than 5 MB.\",\n );\n }\n return { src: `story-${label}`, data };\n}\n\nexport async function loadStoryImages(cwd: string, config: Config): Promise<StoryImage[]> {\n const configured = STORY_IMAGE_LABELS.flatMap((label) => {\n const path = config.release?.story?.[label];\n return path === undefined ? [] : [{ label, path }];\n });\n return Promise.all(configured.map((image) => readStoryImage(cwd, image.label, image.path)));\n}\n\nexport interface StoryFlags {\n cwd: string;\n tag?: string;\n format?: string;\n style?: string;\n theme?: string;\n headline?: string;\n out?: string;\n strict?: boolean;\n package?: string;\n}\n\nexport async function runStory(flags: StoryFlags) {\n const brand = await loadBrand(flags.cwd);\n const config = await loadConfig(flags.cwd);\n const tag = flags.tag ?? (await gitCurrentTag(flags.cwd));\n if (tag === undefined) {\n throw new ShipsealError(\n \"story.no-tag\",\n \"No release tag was found.\",\n \"Pass --tag with an existing release tag.\",\n );\n }\n // safeParse, not parse: a bad --style or --format is user input at the CLI boundary and\n // has to come back as a typed error, not a raw zod issue dump.\n const parsed = selectionSchema.safeParse({\n pack: \"story\",\n style: flags.style ?? brand.style,\n theme: flags.theme ?? brand.theme,\n accent: brand.colors.primary ?? \"#ff4d4d\",\n headline: flags.headline ?? config.release?.headline ?? \"\",\n upgrade: config.release?.story?.upgrade ?? \"\",\n format: flags.format ?? \"portrait\",\n });\n if (!parsed.success) {\n const fields = [...new Set(parsed.error.issues.map((issue) => issue.path.join(\".\")))];\n throw new ShipsealError(\n \"story.bad-options\",\n `These story options are not valid: ${fields.join(\", \")}.`,\n \"Use --format portrait, square, og, github-social, x, linkedin, producthunt or all; --style minimal, editorial or terminal; --theme dark or light.\",\n { cause: parsed.error },\n );\n }\n const selection = parsed.data;\n\n const collectOptions: Parameters<typeof collectFacts>[0] = {\n cwd: flags.cwd,\n event: { kind: \"release\", tag },\n skipNetwork: true,\n };\n if (flags.package !== undefined) {\n collectOptions.packagePath = flags.package;\n }\n if (config.release?.changelogPath !== undefined) {\n collectOptions.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collectOptions.snippet = config.release.snippet;\n }\n const facts = await collectFacts(collectOptions);\n\n const input: Parameters<typeof buildStudioPack>[0] = {\n facts,\n brand,\n config,\n selection,\n renderer: await createTakumiRenderer(),\n version: readShipsealVersion(),\n generatedAt: new Date().toISOString(),\n images: await loadStoryImages(flags.cwd, config),\n brandSource: \".shipseal/brand.json + story flags\",\n };\n const logos = await loadLogos(flags.cwd, brand);\n if (logos !== undefined) {\n input.logos = logos;\n }\n const pack = await buildStudioPack(input);\n\n const dir = resolve(\n flags.cwd,\n flags.out ?? config.outputDir ?? \".shipseal/output\",\n `story-${tag.replaceAll(/[^a-zA-Z0-9_.-]/g, \"-\")}`,\n );\n await mkdir(dir, { recursive: true });\n await Promise.all(pack.downloads.map((file) => writeFile(join(dir, file.name), file.bytes)));\n await writeFile(join(dir, \"story.zip\"), pack.archive);\n return {\n dir,\n manifest: pack.manifest,\n exitCode: flags.strict === true && pack.manifest.warnings.length > 0 ? 2 : 0,\n };\n}\n","// Local preview server: renders release and story packs on demand and saves the\n// choices back into .shipseal. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, rename, writeFile } from \"node:fs/promises\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { join } from \"node:path\";\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { cleanLine, firstSentence } from \"../copy/deterministic.js\";\nimport { ShipsealError, formatError } from \"../core/errors.js\";\nimport { createTakumiRenderer, resolvePackageRoot } from \"../render/takumi-node.js\";\nimport type { StudioOutput, StudioState } from \"../studio/client.js\";\nimport { buildStudioPack, selectedBrand, selectedConfig, selectionSchema } from \"../studio/pack.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport { loadLogos, readShipsealVersion } from \"./shared.js\";\nimport { loadStoryImages } from \"./story.js\";\n\n/** Localhost only, so the page is served inline rather than from a template file. */\nconst PAGE = `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Shipseal preview</title>\n</head><body style=\"margin:0;background:#0c0c0f\"><main id=\"studio\"></main><script type=\"module\">\nimport { mountStudio } from '/studio-client.js';\nconst token = new URL(location.href).searchParams.get('token');\nasync function api(path, value) {\n const response = await fetch(path, {\n method: value === undefined ? 'GET' : 'POST',\n headers: { 'Content-Type': 'application/json', 'X-Shipseal-Token': token },\n ...(value === undefined ? {} : { body: JSON.stringify(value) }),\n });\n const body = await response.json();\n if (!response.ok) throw new Error(body.error);\n return body;\n}\nmountStudio(document.getElementById('studio'), {\n mode: 'local',\n load: () => api('/api/state'),\n render: (value) => api('/api/render', value),\n save: (value) => api('/api/save', value),\n});\n</script></body></html>`;\n\nconst PAGE_HEADERS = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n \"Referrer-Policy\": \"no-referrer\",\n \"Content-Security-Policy\":\n \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob:; connect-src 'self'; frame-ancestors 'none'\",\n};\n\nfunction json(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n });\n response.end(JSON.stringify(value));\n}\n\nasync function readSelection(request: IncomingMessage) {\n let text = \"\";\n for await (const value of request) {\n if (!Buffer.isBuffer(value)) {\n throw new ShipsealError(\n \"preview.body\",\n \"The request body is not valid bytes.\",\n \"Reload the preview.\",\n );\n }\n text += value.toString(\"utf8\");\n if (text.length > 16_384) {\n throw new ShipsealError(\n \"preview.body-size\",\n \"The preview request is too large.\",\n \"Shorten the headline or upgrade instructions.\",\n );\n }\n }\n try {\n const raw: unknown = JSON.parse(text);\n return selectionSchema.parse(raw);\n } catch (error) {\n throw new ShipsealError(\n \"preview.selection\",\n \"The preview options are invalid.\",\n \"Reload the preview and choose supported options.\",\n { cause: error },\n );\n }\n}\n\n/** Write through a temporary file so an interrupted save never truncates the original. */\nasync function writeAtomic(destination: string, value: unknown): Promise<void> {\n const temporary = `${destination}.${randomUUID()}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n await rename(temporary, destination);\n}\n\nexport async function startPreview(options: {\n cwd: string;\n tag?: string;\n port?: number;\n package?: string;\n}) {\n const resolvedTag = options.tag ?? (await gitCurrentTag(options.cwd));\n if (resolvedTag === undefined) {\n throw new ShipsealError(\n \"preview.no-tag\",\n \"No release tag was found.\",\n \"Pass --tag with an existing release tag.\",\n );\n }\n // Declared as string so the request handler below reads it without renarrowing.\n const tag: string = resolvedTag;\n // Startup validates the workspace before printing a URL the user is told to open.\n await loadBrand(options.cwd);\n const token = randomUUID();\n let origin = \"\";\n\n async function handle(request: IncomingMessage, response: ServerResponse): Promise<void> {\n if (request.headers.host !== new URL(origin).host) {\n json(response, 403, {\n error: \"Invalid preview host. Open the localhost URL printed by Shipseal.\",\n });\n return;\n }\n const url = new URL(request.url ?? \"/\", origin);\n if (request.method === \"GET\" && url.pathname === \"/\") {\n response.writeHead(200, PAGE_HEADERS);\n response.end(PAGE);\n return;\n }\n if (request.method === \"GET\" && url.pathname === \"/studio-client.js\") {\n const script = await readFile(join(resolvePackageRoot(), \"dist\", \"studio-client.js\"));\n response.writeHead(200, { \"Content-Type\": \"text/javascript\", \"Cache-Control\": \"no-store\" });\n response.end(script);\n return;\n }\n if (\n request.headers[\"x-shipseal-token\"] !== token ||\n (request.method === \"POST\" && request.headers.origin !== origin)\n ) {\n json(response, 403, {\n error:\n \"This preview request is not authorized. Reload the localhost URL printed by Shipseal.\",\n });\n return;\n }\n\n const brand = await loadBrand(options.cwd);\n const config = await loadConfig(options.cwd);\n const collect: Parameters<typeof collectFacts>[0] = {\n cwd: options.cwd,\n event: { kind: \"release\", tag },\n skipNetwork: true,\n };\n if (options.package !== undefined) {\n collect.packagePath = options.package;\n }\n if (config.release?.changelogPath !== undefined) {\n collect.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collect.snippet = config.release.snippet;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/api/state\") {\n const facts = await collectFacts(collect);\n const state: StudioState = {\n name: brand.name,\n style: brand.style,\n theme: brand.theme,\n accent: brand.colors.primary ?? \"#ff4d4d\",\n headline: config.release?.headline ?? \"\",\n upgrade: config.release?.story?.upgrade ?? \"\",\n headlines: [...(facts.release?.breaking ?? []), ...(facts.release?.features ?? [])].map(\n (item) => cleanLine(firstSentence(item.value)),\n ),\n notes: [\n \"Local facts come from your checkout. Change files and refresh this page to reload them. Screenshots use release.story.before and release.story.after in config.json.\",\n ],\n releases: [{ tag, label: tag }],\n tag,\n };\n json(response, 200, state);\n return;\n }\n if (request.method !== \"POST\") {\n json(response, 404, { error: \"Preview route not found.\" });\n return;\n }\n\n const selection = await readSelection(request);\n if (url.pathname === \"/api/save\") {\n const nextConfig = selectedConfig(config, selection);\n // Pack-specific sizes are preview choices, so ordinary release formats are preserved.\n nextConfig.formats = config.formats;\n await Promise.all([\n writeAtomic(join(options.cwd, \".shipseal\", \"brand.json\"), selectedBrand(brand, selection)),\n writeAtomic(join(options.cwd, \".shipseal\", \"config.json\"), nextConfig),\n ]);\n json(response, 200, { saved: true });\n return;\n }\n if (url.pathname !== \"/api/render\") {\n json(response, 404, { error: \"Preview route not found.\" });\n return;\n }\n\n const facts = await collectFacts(collect);\n const packInput: Parameters<typeof buildStudioPack>[0] = {\n facts,\n brand,\n config,\n selection,\n renderer: await createTakumiRenderer(),\n generatedAt: new Date().toISOString(),\n version: readShipsealVersion(),\n images: await loadStoryImages(options.cwd, config),\n };\n const logos = await loadLogos(options.cwd, brand);\n if (logos !== undefined) {\n packInput.logos = logos;\n }\n const pack = await buildStudioPack(packInput);\n const output: StudioOutput = {\n files: pack.result.files.map((file) => ({\n name: file.fileName,\n data: Buffer.from(file.bytes).toString(\"base64\"),\n width: file.width,\n height: file.height,\n })),\n archive: Buffer.from(pack.archive).toString(\"base64\"),\n manifest: pack.manifest,\n };\n const pdf = pack.downloads.find((file) => file.name === \"story.pdf\");\n if (pdf !== undefined) {\n output.pdf = Buffer.from(pdf.bytes).toString(\"base64\");\n }\n json(response, 200, output);\n }\n\n const server = createServer((request, response) => {\n void handle(request, response).catch((error: unknown) => {\n json(response, 400, {\n error:\n error instanceof ShipsealError\n ? formatError(error)\n : `${error instanceof Error ? error.message : \"Preview failed\"}. Check the files and retry.`,\n });\n });\n });\n await new Promise<void>((accept, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 4175, \"127.0.0.1\", () => {\n server.removeListener(\"error\", reject);\n accept();\n });\n });\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n throw new ShipsealError(\n \"preview.listen\",\n \"The preview server could not start.\",\n \"Choose another --port and retry.\",\n );\n }\n origin = `http://127.0.0.1:${String(address.port)}`;\n return { server, url: `${origin}/?token=${token}`, token };\n}\n\nexport async function runPreview(options: Parameters<typeof startPreview>[0]): Promise<void> {\n let preview: Awaited<ReturnType<typeof startPreview>>;\n try {\n preview = await startPreview(options);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\") {\n throw new ShipsealError(\n \"preview.port\",\n \"The preview port is already in use.\",\n \"Pass --port with another available port.\",\n { cause: error },\n );\n }\n throw error;\n }\n process.stdout.write(`Preview: ${preview.url}\\nPress Ctrl+C to stop.\\n`);\n await new Promise<void>((accept) => {\n const stop = () => {\n preview.server.close();\n preview.server.closeAllConnections();\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n preview.server.once(\"close\", () => {\n process.removeListener(\"SIGINT\", stop);\n process.removeListener(\"SIGTERM\", stop);\n accept();\n });\n });\n}\n","#!/usr/bin/env node\n// CLI entry: parse args, dispatch to commands/*\n// Spec: docs/PROJECT_PLAN.md §18\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { cac } from \"cac\";\nimport { runBench, type BenchFlags } from \"./commands/bench.js\";\nimport { runDoctor } from \"./commands/doctor.js\";\nimport { runInit } from \"./commands/init.js\";\nimport { runMilestone, type MilestoneFlags } from \"./commands/milestone.js\";\nimport { runRelease, type ReleaseFlags } from \"./commands/release.js\";\nimport { runStory } from \"./commands/story.js\";\nimport { runPreview } from \"./commands/preview.js\";\nimport { ShipsealError, formatError } from \"./core/errors.js\";\nimport { resolvePackageRoot } from \"./render/takumi-node.js\";\n\nexport async function runCli(argv = process.argv): Promise<number> {\n process.exitCode = 0;\n const cli = cac(\"shipseal\");\n cli.option(\"--cwd <path>\", \"Working directory\", { default: process.cwd() });\n cli.option(\"--json\", \"Machine-readable JSON output\");\n cli.option(\"--quiet\", \"Suppress non-error output\");\n cli.option(\"--verbose\", \"Verbose output\");\n\n cli\n .command(\"init\", \"Detect brand and write .shipseal/brand.json + config.json\")\n .option(\"--yes\", \"Accept detections without prompting\")\n .option(\"--force\", \"Overwrite existing brand.json and config.json\")\n .action(async (flags: Record<string, unknown>) => {\n const result = await runInit({\n cwd: stringFlag(flags.cwd, process.cwd()),\n yes: flags.yes === true,\n force: flags.force === true,\n });\n if (flags.json === true) {\n process.stdout.write(`${JSON.stringify(result.detection.brand, null, 2)}\\n`);\n return;\n }\n if (flags.quiet !== true) {\n process.stdout.write(`Wrote ${result.brandPath}\\n`);\n process.stdout.write(`Wrote ${result.configPath}\\n`);\n process.stdout.write(`Sample card: ${result.samplePath}\\n`);\n for (const field of result.detection.sources) {\n process.stdout.write(` ${field.field}: ${field.source}\\n`);\n }\n // Notes carry the \"this is a built-in default, not your brand\" disclosures.\n // The interactive prompt already shows them, and --yes skips that prompt, so\n // without this the user never learns which colors were not detected.\n for (const note of result.detection.notes) {\n process.stdout.write(` note: ${note}\\n`);\n }\n }\n });\n\n cli.command(\"story\", \"Generate an ordered release story, PDF carousel and ZIP\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--format <format>\", \"portrait, square, og, github-social, x, linkedin, producthunt, or all\")\n .option(\"--style <style>\", \"minimal, editorial, or terminal\")\n .option(\"--theme <theme>\", \"dark or light\")\n .option(\"--headline <text>\", \"Override the cover headline\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--no-copy\", \"Use source text only (stories always use deterministic copy)\")\n .action(async (flags: Record<string, unknown>) => {\n const options: Parameters<typeof runStory>[0] = { cwd: stringFlag(flags.cwd, process.cwd()), strict: flags.strict === true };\n for (const key of [\"tag\", \"format\", \"style\", \"theme\", \"headline\", \"out\", \"package\"] as const) {\n const value = optionalString(flags[key]); if (value !== undefined) options[key] = value;\n }\n const result = await runStory(options);\n process.exitCode = result.exitCode;\n if (flags.json === true) writeJson(result);\n else if (flags.quiet !== true) writeHumanResult({ ...result, dryRun: false, facts: result.manifest.facts, warnings: result.manifest.warnings });\n });\n\n cli.command(\"preview\", \"Preview release and story packs locally, then save your choices\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--port <port>\", \"Localhost port (default: 4175)\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const options: Parameters<typeof runPreview>[0] = { cwd: stringFlag(flags.cwd, process.cwd()) };\n for (const key of [\"tag\", \"package\"] as const) { const value = optionalString(flags[key]); if (value !== undefined) options[key] = value; }\n if (flags.port !== undefined) {\n const port = Number(flags.port);\n if (!Number.isInteger(port) || port < 0 || port > 65535) throw new ShipsealError(\"preview.port\", \"The preview port is invalid.\", \"Pass an integer from 0 through 65535.\");\n options.port = port;\n }\n await runPreview(options);\n });\n\n cli.command(\"doctor\", \"Check Node, git, brand, fonts, and Takumi\").action(async (flags: Record<string, unknown>) => {\n const result = await runDoctor(stringFlag(flags.cwd, process.cwd()));\n if (flags.json === true) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else if (flags.quiet !== true) {\n for (const check of result.checks) {\n const mark = check.status === \"pass\" ? \"ok\" : check.status === \"fail\" ? \"FAIL\" : \"info\";\n process.stdout.write(`[${mark}] ${check.name}: ${check.message}\\n`);\n if (check.fix !== undefined && check.status === \"fail\") {\n process.stdout.write(` Fix: ${check.fix}\\n`);\n }\n }\n }\n if (!result.ok) {\n process.exitCode = 1;\n }\n });\n\n cli\n .command(\"release\", \"Generate the release pack\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--from <tag>\", \"Previous tag\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--templates <list>\", \"Comma-separated templates\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .option(\"--headline <text>\", \"Headline for the cards, overriding the changelog\")\n .option(\"--subheadline <text>\", \"Subheadline for the cards\")\n .option(\"--upload\", \"Upload PNG files to the GitHub release\")\n .action(async (flags: Record<string, unknown>) => {\n const releaseFlags: ReleaseFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(releaseFlags, flags);\n const tag = optionalString(flags.tag);\n if (tag !== undefined) {\n releaseFlags.tag = tag;\n }\n const headline = optionalString(flags.headline);\n if (headline !== undefined) {\n releaseFlags.headline = headline;\n }\n const subheadline = optionalString(flags.subheadline);\n if (subheadline !== undefined) {\n releaseFlags.subheadline = subheadline;\n }\n const from = optionalString(flags.from);\n if (from !== undefined) {\n releaseFlags.from = from;\n }\n const templates = optionalString(flags.templates);\n if (templates !== undefined) {\n releaseFlags.templates = templates;\n }\n const result = await runRelease(releaseFlags);\n process.exitCode = result.exitCode;\n writeCommandOutput(flags, result);\n });\n\n cli\n .command(\"milestone\", \"Generate a milestone card for the highest crossed threshold\")\n .option(\"--metric <stars|downloads|contributors>\", \"Metric to check\")\n .option(\"--threshold <n>\", \"Force a specific threshold\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const milestoneFlags: MilestoneFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(milestoneFlags, flags);\n const metric = optionalString(flags.metric);\n if (metric !== undefined) {\n milestoneFlags.metric = metric;\n }\n const threshold = optionalString(flags.threshold);\n if (threshold !== undefined) {\n milestoneFlags.threshold = threshold;\n }\n const result = await runMilestone(milestoneFlags);\n process.exitCode = result.exitCode;\n if (flags.json === true) {\n writeJson(resultToJson(result));\n return;\n }\n if (flags.quiet === true) {\n return;\n }\n if (result.skipped) {\n process.stdout.write(`${result.message ?? \"No milestone threshold crossed.\"}\\n`);\n return;\n }\n writeHumanResult(result);\n });\n\n cli\n .command(\"bench\", \"Generate benchmark cards from bench JSON\")\n .option(\"--file <path>\", \"Path to bench JSON\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const benchFlags: BenchFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(benchFlags, flags);\n const file = optionalString(flags.file);\n if (file !== undefined) {\n benchFlags.file = file;\n }\n const result = await runBench(benchFlags);\n process.exitCode = result.exitCode;\n writeCommandOutput(flags, result);\n });\n\n cli.help();\n cli.version(readVersion());\n\n try {\n cli.parse(argv, { run: false });\n await cli.runMatchedCommand();\n return typeof process.exitCode === \"number\" ? process.exitCode : 0;\n } catch (error) {\n if (error instanceof ShipsealError) {\n process.stderr.write(`${formatError(error)}\\n`);\n return 1;\n }\n if (error instanceof Error) {\n process.stderr.write(`${error.message}\\n`);\n return 1;\n }\n throw error;\n }\n}\n\nfunction stringFlag(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value.length > 0 ? value : fallback;\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction applySharedFlags(target: { formats?: string; themes?: string; copy?: boolean; out?: string; package?: string; upload?: boolean }, flags: Record<string, unknown>): void {\n const formats = optionalString(flags.formats);\n if (formats !== undefined) {\n target.formats = formats;\n }\n const themes = optionalString(flags.themes);\n if (themes !== undefined) {\n target.themes = themes;\n }\n if (flags.copy === false) {\n target.copy = false;\n }\n const out = optionalString(flags.out);\n if (out !== undefined) {\n target.out = out;\n }\n const pkg = optionalString(flags.package);\n if (pkg !== undefined) {\n target.package = pkg;\n }\n if (flags.upload === true) {\n target.upload = true;\n }\n}\n\nfunction writeCommandOutput(\n flags: Record<string, unknown>,\n result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n manifest?: unknown;\n copyWarning?: string;\n warnings: Array<{ template: string; format: string; slot: string; action: string }>;\n skipped?: boolean;\n message?: string;\n },\n): void {\n if (flags.json === true) {\n writeJson(resultToJson(result));\n return;\n }\n if (flags.quiet === true) {\n return;\n }\n writeHumanResult(result);\n}\n\nfunction resultToJson(result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n manifest?: unknown;\n skipped?: boolean;\n message?: string;\n}): Record<string, unknown> {\n const payload: Record<string, unknown> = {};\n if (result.skipped === true) {\n payload.skipped = true;\n }\n if (result.message !== undefined) {\n payload.message = result.message;\n }\n if (result.dir !== undefined) {\n payload.dir = result.dir;\n }\n if (result.manifest !== undefined) {\n payload.manifest = result.manifest;\n } else {\n payload.facts = result.facts;\n }\n return payload;\n}\n\nfunction writeHumanResult(result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n copyWarning?: string;\n warnings: Array<{ template: string; format: string; slot: string; action: string }>;\n skipped?: boolean;\n message?: string;\n}): void {\n if (result.skipped === true) {\n process.stdout.write(`${result.message ?? \"Nothing to generate.\"}\\n`);\n return;\n }\n if (result.dryRun) {\n process.stdout.write(`${JSON.stringify(result.facts, null, 2)}\\n`);\n return;\n }\n if (result.dir !== undefined) {\n process.stdout.write(`Wrote ${result.dir}\\n`);\n }\n if (result.copyWarning !== undefined) {\n process.stdout.write(`Copy: ${result.copyWarning}\\n`);\n }\n for (const warning of result.warnings) {\n process.stdout.write(`Warning: ${warning.template} ${warning.format} ${warning.slot} ${warning.action}\\n`);\n }\n}\n\nfunction writeJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction readVersion(): string {\n const raw: unknown = JSON.parse(readFileSync(join(resolvePackageRoot(), \"package.json\"), \"utf8\"));\n if (typeof raw === \"object\" && raw !== null && \"version\" in raw && typeof raw.version === \"string\") {\n return raw.version;\n }\n return \"0.0.0\";\n}\n\nif (shouldRun(process.argv[1])) {\n void runCli().then((code) => {\n process.exit(code);\n });\n}\n\nfunction shouldRun(invoked: string | undefined): boolean {\n if (invoked === undefined) {\n return false;\n }\n const normalized = invoked.replaceAll(\"\\\\\", \"/\");\n return (\n normalized.endsWith(\"/cli.js\") ||\n normalized.endsWith(\"/cli.ts\") ||\n normalized.endsWith(\"/shipseal\")\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAGA,IAAa,gBAAb,cAAmC,MAAM;CACvC,AAAS;CACT,AAAS;CAET,YAAY,MAAc,SAAiB,KAAa,SAA+B;EACrF,MAAM,SAAS,OAAO;EACtB,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,MAAM;CACb;AACF;AAEA,SAAgB,YAAY,OAA8B;CACxD,OAAO,GAAG,MAAM,QAAQ,SAAS,MAAM;AACzC;;;;ACZA,MAAa,iBAAiB,EAC3B,OAAO,CAAC,CACR,MAAM,oBAAoB,2CAA2C;AAExE,MAAa,iBAAiB,EAAE,OAAO;CACrC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACxB,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG;CACzC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;AACnC,CAAC;AAED,MAAa,cAAc,EAAE,OAAO;CAClC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,SAAS,EAAE,QAAQ,CAAC;CACpB,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACtB,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS;CACzB,MAAM,EACH,OAAO;EACN,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;EACvB,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACnC,CAAC,CAAC,CACD,SAAS;CACZ,QAAQ,EAAE,OAAO;EACf,YAAY;EACZ,YAAY;EACZ,OAAO,eAAe,SAAS;EAC/B,SAAS,eAAe,SAAS;EACjC,QAAQ,eAAe,SAAS;CAClC,CAAC;CACD,OAAO,EAAE,OAAO;EACd,SAAS;EACT,MAAM;EACN,MAAM;CACR,CAAC;CACD,QAAQ,EAAE,OAAO,CAAC,CAAC,YAAY;CAC/B,OAAO,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC;CAC/B,OAAO,EAAE,KAAK;EAAC;EAAW;EAAa;CAAU,CAAC;CAClD,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;AAC9B,CAAC;AAID,MAAa,uBAAuB;CAClC,YAAY;CACZ,YAAY;CACZ,OAAO;CACP,SAAS;CACT,QAAQ;AACV;AAEA,MAAa,sBAAsB;CACjC,SAAS;EAAE,QAAQ;EAAS,QAAQ;CAAI;CACxC,MAAM;EAAE,QAAQ;EAAS,QAAQ;CAAI;CACrC,MAAM;EAAE,QAAQ;EAAc,QAAQ;CAAI;AAC5C;;;;ACnDA,eAAsB,UAAU,KAA6B;CAC3D,MAAM,OAAO,KAAK,KAAK,aAAa,YAAY;CAChD,IAAI;EACF,MAAM,MAAe,KAAK,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC;EAC5D,OAAO,YAAY,MAAM,GAAG;CAC9B,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,MAAM,IAAI,cACR,iBACA,kCACA,gEACF;EAEF,MAAM;CACR;AACF;;;;ACpBA,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAYA,MAAM,sBAAsB;AAE5B,MAAa,UAAoC;CAC/C,IAAI;EAAE,IAAI;EAAM,OAAO;EAAM,QAAQ;EAAK,UAAU;CAAoB;CACxE,iBAAiB;EACf,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,UAAU;CACZ;CACA,GAAG;EAAE,IAAI;EAAK,OAAO;EAAM,QAAQ;EAAK,UAAU;CAAoB;CACtE,UAAU;EAAE,IAAI;EAAY,OAAO;EAAM,QAAQ;EAAK,UAAU;CAAoB;CACpF,QAAQ;EAAE,IAAI;EAAU,OAAO;EAAM,QAAQ;EAAM,UAAU;CAAoB;CACjF,UAAU;EAAE,IAAI;EAAY,OAAO;EAAM,QAAQ;EAAM,UAAU;CAAoB;CACrF,aAAa;EACX,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,UAAU;CACZ;CACA,iBAAiB;EACf,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,UAAU;CACZ;AACF;AAEA,MAAa,gBAAgB;CAAC;CAAM;CAAiB;CAAK;AAAU;;;;AC9CpE,MAAa,eAAe,EAAE,OAAO;CACnC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,SAAS,EAAE,QAAQ,CAAC;CACpB,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;CAC/B,SAAS,EAAE,MAAM,EAAE,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS;CAC9C,SAAS,EACN,OAAO;EACN,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS;EACxC,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EACpD,eAAe,EAAE,OAAO,CAAC,CAAC,SAAS;EACnC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EACxC,UAAU,EAAE,KAAK;GAAC;GAAS;GAAS;EAAO,CAAC,CAAC,CAAC,SAAS;EACvD,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EACzC,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EAC5C,OAAO,EAAE,OAAO;GACd,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,GAAI,CAAC,CAAC,SAAS;GACvC,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;GAC5B,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;EAC7B,CAAC,CAAC,CAAC,QAAQ,UAAU,QAAQ,MAAM,MAAM,MAAM,QAAQ,MAAM,KAAK,GAAG,EACnE,SAAS,yEACX,CAAC,CAAC,CAAC,SAAS;CACd,CAAC,CAAC,CACD,SAAS;CACZ,YAAY,EACT,OAAO;EACN,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;EACrD,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;EACzD,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;CAC9D,CAAC,CAAC,CACD,SAAS;CACZ,OAAO,EACJ,OAAO,EACN,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,EAC5B,CAAC,CAAC,CACD,SAAS;CACZ,MAAM,EACH,OAAO;EACN,KAAK,EAAE,QAAQ,CAAC,CAAC,SAAS;EAC1B,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EACzC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;EACtC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACtD,CAAC,CAAC,CACD,SAAS;CACZ,QAAQ,EACL,OAAO,EACN,aAAa,EAAE,KAAK;EAAC;EAAO;EAAQ;CAAM,CAAC,CAAC,CAAC,SAAS,EACxD,CAAC,CAAC,CACD,SAAS;CACZ,aAAa,EAAE,QAAQ,CAAC,CAAC,SAAS;AACpC,CAAC;AAID,MAAa,iBAAyB;CACpC,SAAS;CACT,WAAW;CACX,SAAS;EAAC;EAAM;EAAiB;EAAK;CAAU;CAChD,SAAS;EACP,WAAW;GAAC;GAAgB;GAAsB;EAAW;EAC7D,eAAe;EACf,eAAe;EAGf,UAAU;EACV,SAAS;CACX;CACA,YAAY;EAIV,OAAO;GAAC;GAAI;GAAI;GAAK;GAAK;GAAK;GAAM;GAAM;GAAM;EAAK;EACtD,WAAW;GAAC;GAAM;GAAO;GAAQ;EAAO;EACxC,cAAc;GAAC;GAAI;GAAI;GAAI;EAAG;CAChC;CACA,OAAO,EACL,MAAM,uBACR;CACA,MAAM;EACJ,KAAK;EACL,UAAU;EACV,OAAO;EACP,YAAY;CACd;CACA,QAAQ,EACN,aAAa,MACf;CACA,aAAa;AACf;;;;ACtFA,eAAsB,WAAW,KAA8B;CAC7D,MAAM,OAAO,KAAK,KAAK,aAAa,aAAa;CACjD,IAAI;EACF,MAAM,MAAe,KAAK,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC;EAC5D,MAAM,SAAS,aAAa,MAAM,GAAG;EACrC,OAAO,YAAY,gBAAgB,MAAM;CAC3C,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC9D,OAAO;EAET,MAAM;CACR;AACF;AAEA,SAAgB,YAAY,MAAc,SAAyB;CACjE,OAAO;EACL,GAAG;EACH,GAAG;EACH,SAAS;GAAE,GAAG,KAAK;GAAS,GAAG,QAAQ;EAAQ;EAC/C,YAAY;GAAE,GAAG,KAAK;GAAY,GAAG,QAAQ;EAAW;EACxD,OAAO;GAAE,GAAG,KAAK;GAAO,GAAG,QAAQ;EAAM;EACzC,MAAM;GAAE,GAAG,KAAK;GAAM,GAAG,QAAQ;EAAK;EACtC,QAAQ;GAAE,GAAG,KAAK;GAAQ,GAAG,QAAQ;EAAO;CAC9C;AACF;;;;AC5BA,MAAa,cAAc;CACzB,UAAU;CACV,aAAa;CACb,WAAW;CACX,KAAK;CACL,eAAe;AACjB;;;;ACHA,SAAgB,kBACd,OACA,mBAGA,aACM;CACN,MAAM,OAAO,MAAM,QAAQ,KAAK;CAChC,MAAM,UAAU,MAAM,SAAS,QAAQ;CACvC,MAAM,YAAY,MAAM,SAAS,YAAY,CAAC,EAAC,CAAE,KAAK,SAAS,KAAK,KAAK;CACzE,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC,EAAC,CAAE,KAAK,SAAS,KAAK,KAAK;CACnE,MAAM,YAAY,MAAM,SAAS,YAAY,CAAC,EAAC,CAAE,KAAK,SAAS,KAAK,KAAK;CAWzE,MAAM,iBAAiB,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC,CAC9C,KAAK,SAAS,UAAU,cAAc,IAAI,CAAC,CAAC,CAAC,CAC7C,MAAM,SAAS,KAAK,UAAU,kBAAkB;CACnD,MAAM,QAAQ,eAAe;CAC7B,MAAM,WACJ,MAAM,SAAS,UAAU,SACzB,mBACC,YAAY,SAAY,QAAQ,GAAG,MAAM,GAAG;CAE/C,MAAM,UAAU,MAAM,SAAS,aAAa,SAAS,MAAM,QAAQ,SAAS;CAC5E,MAAM,cACJ,YAAY,UAAa,QAAQ,SAAS,IACtC,UAAU,OAAO,IACjB,UAAU,SAAS,MAAM,MAAM,MAAM,MAAM,MAAM,iBAAiB,WAAW,MAAM;CAIzF,MAAM,aAAuB,CAAC;CAC9B,MAAM,gBAAgB,MAAc,SAAS,OAAa;EACxD,IAAI,WAAW,UAAU,eACvB;EAEF,WAAW,KAAK,GAAG,SAAS,UAAU,cAAc,IAAI,CAAC,GAAG;CAC9D;CACA,KAAK,MAAM,QAAQ,UACjB,aAAa,MAAM,YAAY;CAEjC,KAAK,MAAM,QAAQ,UACjB,aAAa,IAAI;CAEnB,KAAK,MAAM,QAAQ,OACjB,aAAa,IAAI;CAGnB,MAAM,OAAa;EACjB;EACA;EACA;EACA,KAAK,OAAO,KAAK;CACnB;CACA,MAAM,UAAU,MAAM,SAAS,aAAa,MAAM;CAClD,IAAI,YAAY,UAAa,cAAc,OAAO,GAChD,KAAK,YAAY;CAEnB,OAAO;AACT;;;;;;;;AASA,MAAM,kBACJ;AAEF,SAAgB,cAAc,MAAuB;CACnD,MAAM,QAAQ,KACX,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,QAAQ,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CACjD,QAAQ,SAAS,KAAK,SAAS,KAAK,CAAC,KAAK,WAAW,GAAG,CAAC;CAC5D,OAAO,MAAM,SAAS,KAAK,MAAM,OAAO,SAAS,gBAAgB,KAAK,IAAI,CAAC;AAC7E;AAEA,SAAgBA,cAAY,OAAuB;CACjD,OAAO,MAAM,eAAe,OAAO;AACrC;AAEA,SAAgB,cACd,OACA,QACA,WACM;CACN,MAAM,YAAYA,cAAY,SAAS;CACvC,MAAM,OACJ,WAAW,UACP,iBAAiB,UAAU,UAC3B,WAAW,cACT,GAAG,UAAU,qBACb,cAAc,UAAU;CAChC,MAAM,UAAU,MAAM,QAAQ,SAAS;CACvC,OAAO;EACL,UAAU,MAAM,QAAQ,KAAK;EAC7B,aAAa,YAAY,UAAa,QAAQ,SAAS,IAAI,UAAU,OAAO,IAAI;EAChF,YAAY,CAAC;EACb,KAAK,OAAO,KAAK;EACjB,eAAe;CACjB;AACF;AAEA,SAAgB,UAAU,OAAoB;CAC5C,MAAM,QAAQ,MAAM,OAAO,MAAM,SAAS,MAAM,QAAQ,KAAK;CAC7D,MAAM,OAAO,MAAM,OAAO,MAAM;CAChC,OAAO;EACL,UAAU;EACV,aAAa,SAAS,UAAa,KAAK,SAAS,IAAI,OAAQ,MAAM,QAAQ,SAAS,SAAS;EAC7F,YAAY,CAAC;EACb,KAAK,OAAO,KAAK;CACnB;AACF;;;;;;;;;AAUA,SAAgB,cAAc,MAAsB;CAClD,MAAM,YAAY,KAAK,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;CAEjD,OADc,sBAAsB,KAAK,SAC9B,CAAC,GAAG,MAAM;AACvB;;;;;;AAOA,MAAM,qBAAqB;;;;;;;;;;;AAc3B,MAAM,QAAQ;AAEd,SAAgB,WAAW,MAAsB;CAC/C,OAAO,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;AAC9D;AAEA,SAAgB,UAAU,MAAsB;CAI9C,MAAM,WAAW,WAAW,IAAI,CAAC,CAC9B,QAAQ,iBAAiB,IAAI,CAAC,CAC9B,QAAQ,iBAAiB,IAAI,CAAC,CAC9B,WAAW,KAAU,GAAG,CAAC,CACzB,WAAW,KAAK,GAAG,CAAC,CACpB,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK;CACR,MAAM,UAAU,SAAS,SAAS,GAAG,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI;CACjE,MAAM,QAAQ,QAAQ,GAAG,CAAC;CAC1B,IAAI,UAAU,QACZ,OAAO;CAET,OAAO,MAAM,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC9C;AAEA,SAAS,OAAO,OAAsB;CACpC,MAAM,MAAM,MAAM,QAAQ,YAAY;CACtC,IAAI,QAAQ,UAAa,IAAI,SAAS,GAGpC,OAAO,MAAM,QAAQ,KAAK,UAAU,OAAO,OAAO,IAAI,WAAW,SAAS;CAE5E,MAAM,MAAM,MAAM,QAAQ,KAAK,SAAS,MAAM,QAAQ,MAAM;CAC5D,IAAI,QAAQ,QACV,OAAO,MAAM,QAAQ,KAAK;CAE5B,OAAO,IAAI,QAAQ,gBAAgB,EAAE;AACvC;;;;AC/LA,SAAgB,cAAc,QAAgB,OAAe,QAA2C;CACtG,IAAI,WAAW,GAAG;EAChB,IAAI,UAAU,GACZ,OAAO;GAAE,QAAQ;GAAG,YAAY;GAAG,YAAY;EAAM;EAEvD,MAAM,WAAW,WAAW,WAAW,QAAQ,IAAI,QAAQ;EAC3D,OAAO;GAAE,QAAQ,WAAW,MAAM;GAAM,YAAY;GAAK,YAAY,CAAC;EAAS;CACjF;CACA,MAAM,MAAM,WAAW,WAAW,SAAS,SAAS,UAAU,QAAQ,UAAU;CAChF,MAAM,SAAS,KAAK,MAAM,MAAM,GAAG;CACnC,OAAO;EAAE;EAAQ,YAAY,KAAK,IAAI,MAAM;EAAG,YAAY,SAAS;CAAE;AACxE;AAEA,SAAgB,aAAa,MAAc,QAA4B,QAA+B;CACpG,IAAI,OAAO,eAAe,GACxB,OAAO;CAET,OAAO,GAAG,OAAO,OAAO,UAAU,EAAE,IAAI,UAAU,MAAM,QAAQ,OAAO,UAAU;AACnF;AAEA,SAAS,UAAU,MAAc,QAA4B,YAA6B;CACxF,IAAI,WAAW,UACb,OAAO,aAAa,UAAU;CAEhC,MAAM,aAAa,KAAK,YAAY;CACpC,IAAI,eAAe,QAAQ,eAAe,OAAO,eAAe,SAAS,eAAe,WACtF,OAAO,aAAa,WAAW;CAEjC,IACE,eAAe,QACf,eAAe,QACf,eAAe,OACf,eAAe,WACf,eAAe,QAEf,OAAO,aAAa,WAAW;CAEjC,OAAO,aAAa,UAAU;AAChC;;;;ACpBA,eAAsB,QACpB,UACA,MACA,MACA,MACqB;CACrB,MAAM,QAAQ,UAAU,IAAI;CAC5B,KAAK,MAAM,YAAY,OAAO;EAG5B,MAAM,WAAW,MAAM,SAAS,YAAY,MAAMC,cAAY,MAAM,MAAM,QAAQ,CAAC;EACnF,IAAI,SAAS,SAAS,KAAK,UACzB,OAAO;GAAE;GAAU;GAAM,OAAO,SAAS;GAAO,WAAW;EAAM;CAErE;CAEA,MAAM,WAAW,KAAK;CACtB,MAAM,YAAY,MAAM,cAAc,UAAU,MAAM,MAAM,MAAM,QAAQ;CAE1E,OAAO;EAAE;EAAU,MAAM;EAAW,QAAO,MADpB,SAAS,YAAY,WAAWA,cAAY,MAAM,MAAM,QAAQ,CAAC,EACrC,CAAC;EAAO,WAAW,cAAc;CAAK;AAC3F;AAEA,SAAS,UAAU,MAA8B;CAC/C,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,OAAO,KAAK,aAAa,QAAQ,KAAK,aAAa,QAAQ,KAAK,MACvE,MAAM,KAAK,IAAI;CAGjB,IADa,MAAM,MAAM,SAAS,OACrB,KAAK,aAChB,MAAM,KAAK,KAAK,WAAW;CAE7B,OAAO;AACT;AAEA,SAASA,cAAY,MAAoB,MAAe,UAAsC;CAC5F,MAAM,OAA2B;EAC/B,YAAY,KAAK;EACjB;EACA,UAAU,KAAK,IAAI;EACnB,YAAY,KAAK;CACnB;CACA,IAAI,KAAK,WAAW,QAClB,KAAK,aAAa,KAAK;CAEzB,IAAI,KAAK,eAAe,QACtB,KAAK,aAAa,KAAK;CAEzB,OAAO;AACT;AAEA,eAAe,cACb,UACA,MACA,MACA,MACA,UACiB;CACjB,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,MAAM,KAAK;CACrE,IAAI,MAAM,WAAW,GACnB,OAAO;CAGT,MAAM,OAAO,OAAO,cAAwC;EAK1D,QAAO,MAJgB,SAAS,YAC9B,WACAA,cAAY,MAAM,MAAM,QAAQ,CAClC,EACe,CAAC,SAAS,KAAK;CAChC;CAEA,KAAK,IAAI,QAAQ,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;EACzD,MAAM,YAAY,GAAG,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GAAG,EAAE;EAErD,IAAI,MAAM,KAAK,SAAS,GACtB,OAAO;CAEX;CAEA,MAAM,QAAQ,MAAM;CACpB,IAAI,UAAU,QACZ,OAAO;CAET,KAAK,IAAI,SAAS,MAAM,QAAQ,UAAU,GAAG,UAAU,GAAG;EACxD,MAAM,YAAY,GAAG,MAAM,MAAM,GAAG,MAAM,EAAE;EAE5C,IAAI,MAAM,KAAK,SAAS,GACtB,OAAO;CAEX;CACA,OAAO;AACT;;;;ACvGA,SAAgB,YAAY,OAAc,OAAsC;CAC9E,MAAM,UAAU,MAAM,OAAO,WAAW,qBAAqB;CAC7D,MAAM,SAAS,MAAM,OAAO,UAAU,qBAAqB;CAC3D,MAAM,QAAQ,MAAM,OAAO,SAAS,qBAAqB;CACzD,IAAI,UAAU,QAAQ;EACpB,MAAM,aAAa,MAAM,UAAU,SAAS,MAAM,OAAO,aAAa,MAAM,OAAO;EACnF,MAAM,aAAa,MAAM,UAAU,SAAS,MAAM,OAAO,aAAa,MAAM,OAAO;EACnF,OAAO;GACL;GACA;GACA,OAAO,MAAM,UAAU,SAAS,QAAQ,qBAAqB;GAC7D;GACA;GACA,MAAM,IAAI,YAAY,YAAY,GAAI;EACxC;CACF;CACA,MAAM,aAAa,MAAM,UAAU,UAAU,MAAM,OAAO,aAAa,MAAM,OAAO;CACpF,MAAM,aAAa,MAAM,UAAU,UAAU,MAAM,OAAO,aAAa,MAAM,OAAO;CACpF,OAAO;EACL;EACA;EACA,OAAO,MAAM,UAAU,UAAU,QAAQ;EACzC;EACA;EACA,MAAM,IAAI,YAAY,YAAY,GAAI;CACxC;AACF;AAEA,SAAS,IAAI,GAAW,GAAW,QAAwB;CACzD,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,MAAM,KAAK,OAAO,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE;CAC5C,OAAO,IAAI,MAAM,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,MAAM;AAC5G;AAEA,SAAS,MAAM,OAAuB;CACpC,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG;AACvD;;;;AC7CA,SAAgB,IACd,MACA,OACA,KACY;CACZ,OAAO;EAAE;EAAM;EAAO,KAAK,OAAO;CAAK;AACzC;AAEA,MAAa,OAAO;;;;;ACLpB,MAAa,eAAe;AAE5B,MAAMC,gBAAc,EAAE,OAAO;CAC3B,UAAU,EAAE,OAAO;CACnB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,QAAQ,EAAE,OAAO;CACjB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;EAAE,MAAM,EAAE,OAAO;EAAG,OAAO,EAAE,OAAO;CAAE,CAAC,CAAC,CAAC;AAC3E,CAAC;AAID,MAAa,WAA+B;CAC1C,IAAI;CACJ,QAAQ,CAAC,SAAS;CAClB,SAAS,CAAC,KAAK,UAAU;CACzB;CACA,MAAM,QAAgB;EAEpB,OAAO,EACL,UAAU;GAAE,UAAU;GAAG,aAAa;GAAI,aAAa;GAAI,MAAM;GAAG,KAAK,EAAE,OAF/D,OAAO,QAAQ,IAAI,OAAO,SAE2C;EAAE,EACrF;CACF;CACA,SAAS,KAAK;EAEZ,OAAO,EAAE,UADKA,cAAY,MAAM,GACT,CAAC,CAAC,SAAS;CACpC;CACA,SAAS,KAAK,MAAM;EAClB,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,IAAI,SAAS,YACX,OAAO;GAAE,QAAQ,MAAM;GAAe,QAAQ,MAAM;GAAe,YAAY;EAAI;EAErF,OAAO;GAAE,QAAQ,MAAM;GAAY,QAAQ,MAAM;GAAY,YAAY;GAAM,YAAY;EAAM;CACnG;CACA,WAAW,OAAc,MAAY,OAAc;EACjD,MAAM,UAAU,CAAC;EACjB,MAAM,QAAQ,KAAK,aAAa,CAAC;EACjC,IAAI,MAAM,WAAW,GACnB,QAAQ,KAAK;GAAE,MAAM;GAAuB,QAAQ;EAA+B,CAAC;EAEtF,OAAO;GACL,OAAO;IACL,UAAU,KAAK,aAAa,KAAK;IACjC,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,QAAQ,MAAM;IACd;GACF;GACA;EACF;CACF;CACA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,WAAW,IAAI,OAAO;EAM5B,MAAM,SAAS;EACf,MAAM,aAAa;EACnB,MAAM,QAAQ,MAAM,MAAM,WAAW,IAAI,IAAI,MAAM,MAAM;EACzD,MAAM,UAAU,KAAK,IACnB,GACA,GAAG,MAAM,MAAM,KAAK,SAAS,KAAK,QAAQ,OAAO,UAAU,QAAQ,MAAM,KAAK,QAAQ,CAAC,CAAC,CAC1F;EACA,MAAM,kBAAkB,UAAU,YAAY,MAAM;EACpD,MAAM,oBAAoB,IAAI,cAAc,OAAgB;EAC5D,MAAM,aAAa,IAAI,OAAO,QAAQ,IAAI,MAAM;EAChD,MAAM,cACJ,IAAI,OAAO,SAAS,IAAI,MAAM,iBAAiB,KAAK,oBAAoB;EAC1E,MAAM,WAAW,KAAK,IACpB,IACA,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,IAAI,cAAc,UAAU,eAAe,eAAe,QAAQ,WAAW,CAAC,CAAC,CAC9G;EAEA,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,SAAS;IACT,KAAK;GACP;aATF;IAWE,oBAAC,OAAD;KACE,OAAO;MACL,YAAY,MAAM;MAClB,YAAY,MAAM;MAClB,UAAU,UAAU,YAAY;MAChC,OAAO,OAAO;KAChB;eAEC,UAAU,QAAQ,MAAM;IACtB;IACL,oBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,eAAe;MACf,UAAU;MACV,gBAAgB;KAClB;eAEF,oBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,eAAe;OACf,iBAAiB,OAAO;OACxB,cAAc,MAAM;OACpB,SAAS;OACT,KAAK;MACP;gBAEC,MAAM,MAAM,KAAK,MAAM,cACtB,oBAAC,OAAD;OAEE,OAAO;QACL,SAAS;QACT,eAAe;QACf,UAAU;OACZ;iBAEC,KAAK,KAAK,OAAO,eAChB,oBAAC,OAAD;QAEE,OAAO;SACL,YAAY,MAAM;SAClB,YAAY,MAAM;SAClB,UAAU;SACV,OAAO,MAAM;SACb,YAAY;SACZ;QACF;kBAEC,MAAM;OACJ,GAXE,GAAG,OAAO,SAAS,EAAE,GAAG,OAAO,UAAU,GAW3C,CACN;MACE,GAtBE,OAAO,SAAS,CAsBlB,CACN;KACE;IACA;IACJ,IAAI,cACH,oBAAC,OAAD;KACE,OAAO;MACL,YAAY,MAAM;MAClB,YAAY;MACZ,UAAU;MACV,OAAO,OAAO;KAChB;eACD;IAEI,KACH;GACD;;CAET;AACF;AAEA,SAAgB,iBAA6B;CAC3C,OAAO,CAAC,CAAC;EAAE,MAAM;EAAK,OAAO;CAAU,CAAC,CAAC;AAC3C;;;;AChLA,MAAM,YAAY;AAElB,eAAsB,cACpB,MACA,MACA,OACqB;CACrB,MAAM,UAAU,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,IAAI;CAC9D,MAAM,gBAAgB,UAAU,SAAS,YAAY;CACrD,IAAI;EACF,MAAM,EAAE,iBAAiB,MAAM,OAAO;EAKtC,QAAO,MAJc,aAAa,SAAS;GACzC,MAAM,QAAQ,IAAI;GAClB,OAAO,UAAU,SAAS,gBAAgB;EAC5C,CAAC,EACY,CAAC,OAAO,KAAK,SAAS;GACjC,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;IAAE,MAAM;IAAK,OAAO;GAAc,CAAC;GAE7C,OAAO,KAAK,KAAK,WAAW;IAC1B,MAAM,MAAM;IACZ,OAAO,MAAM,SAAS;GACxB,EAAE;EACJ,CAAC;CACH,QAAQ;EACN,OAAO,QAAQ,MAAM,IAAI,CAAC,CAAC,KAAK,SAAS,CAAC;GAAE,MAAM,KAAK,WAAW,IAAI,MAAM;GAAM,OAAO;EAAc,CAAC,CAAC;CAC3G;AACF;AAEA,SAAS,QAAQ,MAA6D;CAC5E,MAAM,MAAM,KAAK,YAAY;CAC7B,IAAI,QAAQ,gBAAgB,QAAQ,MAClC,OAAO;CAET,IAAI,QAAQ,OACV,OAAO;CAET,IAAI,QAAQ,OACV,OAAO;CAET,IAAI,QAAQ,QACV,OAAO;CAET,IAAI,QAAQ,UAAU,QAAQ,WAAW,QAAQ,MAC/C,OAAO;CAET,OAAO;AACT;;;;ACxCA,MAAM,YAAY,EAAE,OAAO;CACzB,OAAO,EAAE,OAAO;CAChB,YAAY,EAAE,OAAO;CACrB,WAAW,EAAE,OAAO;CACpB,YAAY,EAAE,OAAO;CACrB,YAAY,EAAE,QAAQ;AACxB,CAAC;AAED,MAAMC,gBAAc,EAAE,OAAO;CAC3B,OAAO,EAAE,OAAO;CAChB,MAAM,EAAE,OAAO;CACf,MAAM,EAAE,MAAM,SAAS;CACvB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,QAAQ,EAAE,OAAO;AACnB,CAAC;AAID,MAAa,QAA4B;CACvC,IAAI;CACJ,QAAQ,CAAC,OAAO;CAChB,SAAS,CAAC,KAAK,UAAU;CACzB;CACA,MAAM,QAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO;EACxC,MAAM,QACJ,EACE,OAAO;GAAE,UAAU;GAAG,aAAa;GAAI,aAAa;GAAI,MAAM;GAAG,KAAK,EAAE,MAAM;EAAE,EAClF;EACF,KAAK,IAAI,QAAQ,GAAG,QAAQ,GAAG,SAAS,GACtC,MAAM,UAAU,OAAO,KAAK,OAAO;GACjC,UAAU;GACV,aAAa;GACb,aAAa;GACb,MAAM;GACN,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,KAAK,EAAE;EACrC;EAEF,OAAO;CACT;CACA,SAAS,KAAK;EACZ,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,OAA+B,EAAE,OAAO,MAAM,MAAM;EAC1D,MAAM,KAAK,SAAS,KAAK,UAAU;GACjC,KAAK,UAAU,OAAO,KAAK,OAAO,IAAI;EACxC,CAAC;EACD,OAAO;CACT;CACA,SAAS,KAAK,MAAM;EAClB,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,IAAI,SAAS,SACX,OAAO;GAAE,QAAQ,MAAM;GAAe,QAAQ,MAAM;GAAe,YAAY;EAAK;EAEtF,OAAO;GAAE,QAAQ,MAAM;GAAe,QAAQ,MAAM;GAAe,YAAY;EAAI;CACrF;CACA,WAAW,OAAc,MAAY,OAAc;EACjD,MAAM,UAAU,CAAC;EACjB,IAAI,MAAM,UAAU,QAClB,QAAQ,KAAK;GAAE,MAAM;GAAS,QAAQ;EAAiB,CAAC;EAE1D,MAAM,OACJ,MAAM,OAAO,QAAQ,KAAK,WAAW;GACnC,MAAM,SAAS,cAAc,OAAO,OAAO,OAAO,OAAO,MAAM,OAAO,OAAO,OAAO,KAAK;GACzF,OAAO;IACL,OAAO,OAAO,MAAM;IACpB,YAAY,GAAG,aAAa,OAAO,OAAO,KAAK,EAAE,GAAG,OAAO,KAAK;IAChE,WAAW,GAAG,aAAa,OAAO,MAAM,KAAK,EAAE,GAAG,OAAO,KAAK;IAC9D,YAAY,aAAa,OAAO,KAAK,OAAO,OAAO,OAAO,OAAO,MAAM;IACvE,YAAY,OAAO;GACrB;EACF,CAAC,KAAK,CAAC;EACT,OAAO;GACL,OAAO;IACL,OAAO,KAAK;IACZ,MAAM,KAAK;IACX;IACA,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,QAAQ,MAAM;GAChB;GACA;EACF;CACF;CACA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,QAAQ,IAAI,OAAO;EACzB,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,SAAS;GACX;aATF;IAWE,oBAAC,OAAD;KACE,OAAO;MACL,YAAY,MAAM;MAClB,YAAY,MAAM;MAClB,UAAU,OAAO,YAAY;MAC7B,OAAO,OAAO;MACd,YAAY;KACd;eAEC,OAAO,QAAQ,MAAM;IACnB;IACL,oBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAU,KAAK;KAAG;eAC7D,MAAM,KAAK,KAAK,KAAK,UAAU;MAC9B,MAAM,SAAS,IAAI,OAAO,UAAU,OAAO,KAAK;MAChD,OACE,qBAAC,OAAD;OAEE,OAAO;QACL,SAAS;QACT,eAAe;QACf,gBAAgB;QAChB,YAAY;QACZ,iBAAiB,OAAO;QACxB,cAAc,MAAM;QACpB,YAAY;QACZ,eAAe;QACf,aAAa;QACb,cAAc;OAChB;iBAbF,CAeE,qBAAC,OAAD;QAAK,OAAO;SAAE,SAAS;SAAQ,eAAe;SAAU,KAAK;QAAE;kBAA/D,CACE,oBAAC,OAAD;SACE,OAAO;UACL,YAAY,MAAM;UAClB,YAAY,MAAM;UAClB,UAAU;UACV,OAAO,OAAO;SAChB;mBAEC,IAAI;QACF,IACL,oBAAC,OAAD;SACE,OAAO;UACL,YAAY,MAAM;UAClB,YAAY,MAAM;UAClB,UAAU;UACV,OAAO,OAAO;SAChB;mBAEC,GAAG,IAAI,WAAW,MAAM,IAAI;QAC1B,EACF;WACL,qBAAC,OAAD;QAAK,OAAO;SAAE,SAAS;SAAQ,eAAe;SAAU,YAAY;SAAY,KAAK;QAAE;kBAAvF,CACE,oBAAC,OAAD;SACE,OAAO;UACL,YAAY,MAAM;UAClB,YAAY,MAAM;UAClB,UAAU,QAAQ,YAAY;UAC9B,OAAO,IAAI,aAAa,OAAO,UAAU,OAAO;SAClD;mBAEC,QAAQ,QAAQ,IAAI;QAClB,IACJ,IAAI,aACH,oBAAC,OAAD;SACE,OAAO;UACL,YAAY,MAAM;UAClB,YAAY,MAAM;UAClB,UAAU;UACV,OAAO,OAAO;SAChB;mBACD;QAEI,KACH,MACD;SACF;SA5DE,IAAI,KA4DN;KAET,CAAC;IACE;IACL,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAO,gBAAgB;MAAiB,YAAY;KAAW;eAA7G,CACE,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBAEC,MAAM;KACJ,IACJ,IAAI,cACH,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBACD;KAEI,KACH,MACD;;GACF;;CAET;AACF;AAEA,SAAS,aAAa,OAAuB;CAC3C,OAAO,OAAO,KAAK;AACrB;;;;ACxNA,MAAMC,gBAAc,EAAE,OAAO;CAC3B,MAAM,EAAE,OAAO;CACf,YAAY,EAAE,OAAO;CACrB,aAAa,EAAE,OAAO;CACtB,UAAU,EAAE,OAAO;CACnB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,QAAQ,EAAE,OAAO;CACjB,UAAU,EAAE,QAAQ;AACtB,CAAC;AAID,MAAa,YAAgC;CAC3C,IAAI;CACJ,QAAQ,CAAC,WAAW;CACpB,SAAS;EAAC;EAAM;EAAK;CAAU;CAC/B;CACA,MAAM,QAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO;EACxC,OAAO;GACL,QAAQ;IAAE,UAAU;IAAG,aAAa;IAAK,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,MAAM;GAAE;GAClF,UAAU;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,MAAM;GAAE;EACrF;CACF;CACA,SAAS,KAAK;EACZ,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,OAAO;GAAE,QAAQ,MAAM;GAAY,UAAU,MAAM;EAAS;CAC9D;CACA,SAAS,KAAK,MAAM;EAClB,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,IAAI,SAAS,UACX,OAAO;GAAE,QAAQ,MAAM;GAAe,QAAQ,MAAM;GAAe,YAAY;EAAE;EAEnF,OAAO;GAAE,QAAQ,MAAM;GAAY,QAAQ,MAAM;GAAY,YAAY;EAAK;CAChF;CACA,WAAW,OAAc,MAAY,OAAc;EACjD,MAAM,UAAU,CAAC;EACjB,MAAM,YAAY,MAAM,WAAW,UAAU;EAC7C,IAAI,cAAc,QAChB,QAAQ,KAAK;GAAE,MAAM;GAAuB,QAAQ;EAAgB,CAAC;EAEvE,MAAM,SAAS,MAAM,WAAW,OAAO;EACvC,MAAM,cACJ,WAAW,cAAc,qBAAqB,WAAW,iBAAiB,iBAAiB;EAC7F,MAAM,WAAW,MAAM,SAAS;EAChC,IAAI,CAAC,UACH,QAAQ,KAAK;GAAE,MAAM;GAAc,QAAQ;EAAc,CAAC;EAE5D,MAAM,WAAW,KAAK,kBAAkB,cAAc,SAAY,KAAK,iBAAiBC,cAAY,SAAS,EAAE,GAAG;EAClH,OAAO;GACL,OAAO;IACL,MAAM,MAAM;IACZ,YAAY,cAAc,SAAY,KAAKA,cAAY,SAAS;IAChE;IACA;IACA,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,QAAQ,MAAM;IACd;GACF;GACA;EACF;CACF;CACA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQD,cAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,SAAS,IAAI,OAAO;EAC1B,MAAM,SAAS,IAAI,OAAO;EAC1B,MAAM,UAAU,IAAI,OAAO,UAAU;EACrC,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,SAAS;GACX;aATF;IAWE,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAO,YAAY;MAAU,KAAK;KAAG;eAAnF,CACG,MAAM,YAAY,IAAI,YAAY,SACjC,oBAAC,OAAD;MAAK,KAAK,IAAI;MAAS,OAAO,UAAU,KAAK;MAAI,QAAQ,UAAU,KAAK;KAAK,KAC3E,QACJ,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBAEC,MAAM;KACJ,EACF;;IACL,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAU,KAAK;KAAG;eAAhE,CACE,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU,QAAQ,YAAY;OAC9B,OAAO,OAAO;OACd,YAAY;MACd;gBAEC,QAAQ,QAAQ,MAAM;KACpB,IACL,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBAEC,MAAM;KACJ,EACF;;IACL,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAO,gBAAgB;MAAiB,YAAY;KAAW;eAA7G,CACE,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU,QAAQ,YAAY;OAC9B,OAAO,OAAO;OACd,YAAY;MACd;gBAEC,QAAQ,QAAQ,MAAM;KACpB,IACJ,IAAI,cACH,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBACD;KAEI,KACH,MACD;;GACF;;CAET;AACF;;;;;;;;;;;ACnJA,SAAgB,UAAU,OAAyB;CACjD,MAAM,WAAW,CAAC,QAAQ;CAC1B,MAAM,UAAgC,CAAC;CAEvC,MAAM,UAAU,MAAM,SAAS,aAAa;CAC5C,IAAI,YAAY,QACd,QAAQ,KAAK;EAAE,MAAM;EAAuB,QAAQ;CAAoC,CAAC;MAEzF,SAAS,KAAK,GAAGE,cAAY,OAAO,EAAE,GAAG,YAAY,IAAI,WAAW,WAAW;CAGjF,MAAM,OAAO,MAAM,SAAS,MAAM;CAClC,IAAI,SAAS,QACX,QAAQ,KAAK;EAAE,MAAM;EAAgB,QAAQ;CAA4B,CAAC;MAE1E,SAAS,KAAK,IAAI;CAGpB,OAAO;EAAE;EAAU;CAAQ;AAC7B;;;;ACzBA,MAAMC,gBAAc,EAAE,OAAO;CAC3B,MAAM,EAAE,OAAO;CACf,SAAS,EAAE,OAAO;CAClB,UAAU,EAAE,OAAO;CACnB,aAAa,EAAE,OAAO;CACtB,KAAK,EAAE,OAAO;CACd,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,QAAQ,EAAE,OAAO;CACjB,SAAS,EAAE,QAAQ;CACnB,UAAU,EAAE,QAAQ;CACpB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;AAC1B,CAAC;AAID,MAAa,cAAkC;CAC7C,IAAI;CACJ,QAAQ,CAAC,SAAS;CAClB,SAAS;EAAC;EAAM;EAAiB;EAAK;CAAU;CAChD;CACA,MAAM,QAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO;EACxC,OAAO;GACL,UAAU;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,MAAM;GAAE;GACnF,aAAa;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,MAAM;GAAE;GACtF,KAAK;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,KAAK,EAAE;GAAE;EACtG;CACF;CACA,SAAS,KAAK;EACZ,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,OAAO;GACL,UAAU,MAAM;GAChB,aAAa,MAAM;GACnB,KAAK,MAAM;EACb;CACF;CACA,SAAS,KAAK,MAAM;EAClB,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,IAAI,SAAS,YACX,OAAO;GAAE,QAAQ,MAAM;GAAe,QAAQ,MAAM;GAAe,YAAY;EAAI;EAErF,OAAO;GAAE,QAAQ,MAAM;GAAY,QAAQ,MAAM;GAAY,YAAY;EAAK;CAChF;CACA,WAAW,OAAc,MAAY,OAAc;EACjD,MAAM,UAAU,CAAC;EACjB,IAAI,MAAM,QAAQ,eAAe,UAAa,MAAM,QAAQ,QAAQ,QAClE,QAAQ,KAAK;GAAE,MAAM;GAAsB,QAAQ;EAAwB,CAAC;EAE9E,MAAM,WAAW,MAAM,SAAS;EAChC,IAAI,CAAC,UACH,QAAQ,KAAK;GAAE,MAAM;GAAc,QAAQ;EAAc,CAAC;EAE5D,MAAM,OAAO,UAAU,KAAK;EAC5B,QAAQ,KAAK,GAAG,KAAK,OAAO;EAC5B,MAAM,UAAU,MAAM,SAAS,QAAQ,SAAS;EAChD,OAAO;GACL,OAAO;IACL,MAAM,MAAM;IACZ;IACA,UAAU,KAAK;IACf,aAAa,KAAK;IAClB,KAAK,KAAK;IACV,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,QAAQ,MAAM;IACd,SAAS,KAAK,IAAI,SAAS;IAC3B,MAAM,KAAK;IACX;GACF;GACA;EACF;CACF;CACA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,WAAW,IAAI,OAAO;EAC5B,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,UAAU,IAAI,OAAO,UAAU;EACrC,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,SAAS;IACT,UAAU;GACZ;aAVF;IAcG,MAAM,YAAY,IAAI,YAAY,SACjC,oBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,UAAU;MACV,OAAO,CAAC,KAAK,MAAM,IAAI,OAAO,SAAS,GAAI;MAC3C,KAAK,KAAK,MAAM,IAAI,OAAO,SAAS,GAAI;MACxC,SAAS;KACX;eAEA,oBAAC,OAAD;MACE,KAAK,IAAI;MACT,OAAO,KAAK,MAAM,IAAI,OAAO,SAAS,GAAI;MAC1C,QAAQ,KAAK,MAAM,IAAI,OAAO,SAAS,GAAI;KAC5C;IACE,KACH;IACJ,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAO,YAAY;MAAU,KAAK;KAAG;eAAnF,CACG,MAAM,YAAY,IAAI,YAAY,SACjC,oBAAC,OAAD;MAAK,KAAK,IAAI;MAAS,OAAO,UAAU,KAAK;MAAI,QAAQ,UAAU,KAAK;KAAK,KAC3E,QACJ,qBAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,eAAe;OAAU,KAAK;MAAE;gBAA/D,CACE,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,MAAM;QAClB,YAAY,MAAM;QAClB,UAAU;QACV,OAAO,OAAO;OAChB;iBAEC,MAAM;MACJ,IACJ,MAAM,QAAQ,SAAS,IACtB,oBAAC,OAAD;OACE,OAAO;QACL,SAAS;QACT,YAAY;QACZ,iBAAiB,OAAO;QACxB,cAAc,MAAM;QACpB,YAAY;QACZ,eAAe;QACf,aAAa;QACb,cAAc;OAChB;iBAEA,oBAAC,OAAD;QACE,OAAO;SACL,YAAY,MAAM;SAClB,YAAY,MAAM;SAClB,UAAU;SACV,OAAO,OAAO;QAChB;kBAEC,IAAI,MAAM;OACR;MACF,KACH,MACD;OACF;;IACL,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAU,KAAK;KAAG;eAAhE,CACE,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU,UAAU,YAAY;OAChC,OAAO,OAAO;OACd,YAAY;MACd;gBAEC,UAAU,QAAQ,MAAM;KACtB,IACL,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU,KAAK,YAAY;OAC3B,OAAO,OAAO;OACd,YAAY;MACd;gBAEC,KAAK,QAAQ,MAAM;KACjB,EACF;;IACL,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAO,gBAAgB;MAAiB,YAAY;KAAW;eAA7G,CACG,MAAM,UACL,oBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,iBAAiB,OAAO;OACxB,cAAc,MAAM;OACpB,YAAY;OACZ,eAAe;OACf,aAAa;OACb,cAAc;MAChB;gBAEA,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,MAAM;QAClB,YAAY,MAAM;QAClB,UAAU,KAAK,YAAY;QAC3B,OAAO,OAAO;OAChB;iBAEC,KAAK,QAAQ,MAAM;MACjB;KACF,KAEL,oBAAC,OAAD,CAAM,IAER,qBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,eAAe;OACf,YAAY;OACZ,KAAK;MACP;gBANF,CAQE,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,MAAM;QAClB,YAAY,MAAM;QAClB,UAAU;QACV,OAAO,OAAO;OAChB;iBAEC,MAAM,KAAK,KAAK,OAAY;MAC1B,IACJ,IAAI,cACH,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,MAAM;QAClB,YAAY,MAAM;QAClB,UAAU;QACV,OAAO,OAAO;OAChB;iBACD;MAEI,KACH,MACD;OACF;;GACF;;CAET;AACF;;;;ACtPA,MAAMC,gBAAc,EAAE,OAAO;CAC3B,MAAM,EAAE,OAAO;CACf,SAAS,EAAE,OAAO;CAClB,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC;CAC9B,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,eAAe,EAAE,OAAO;CACxB,YAAY,EAAE,OAAO;CACrB,QAAQ,EAAE,OAAO;AACnB,CAAC;AAID,MAAa,oBAAwC;CACnD,IAAI;CACJ,QAAQ,CAAC,SAAS;CAClB,SAAS,CAAC,KAAK,UAAU;CACzB;CACA,MAAM,QAAgB;EACpB,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO,WAAW;EACnD,MAAM,QAA8H,CAAC;EACrI,KAAK,IAAI,QAAQ,GAAG,QAAQ,GAAG,SAAS,GACtC,MAAM,aAAa,OAAO,KAAK,OAAO;GACpC,UAAU;GACV,aAAa;GACb,aAAa;GACb,MAAM;GACN,KAAK,EAAE,MAAM;EACf;EAEF,OAAO;CACT;CACA,SAAS,KAAK;EACZ,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,OAA+B,CAAC;EACtC,MAAM,WAAW,SAAS,MAAM,UAAU;GACxC,KAAK,aAAa,OAAO,KAAK,OAAO;EACvC,CAAC;EACD,OAAO;CACT;CACA,SAAS,KAAK;EACZ,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,OAAO;GAAE,QAAQ,MAAM;GAAY,QAAQ,MAAM;GAAY,YAAY;EAAK;CAChF;CACA,WAAW,OAAc,MAAY,OAAc;EACjD,MAAM,UAAU,CAAC;EACjB,IAAI,KAAK,WAAW,WAAW,GAC7B,QAAQ,KAAK;GAAE,MAAM;GAAoB,QAAQ;EAAwB,CAAC;EAE5E,OAAO;GACL,OAAO;IACL,MAAM,MAAM;IACZ,SAAS,MAAM,SAAS,QAAQ,SAAS;IACzC,YAAY,KAAK;IACjB,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,eAAe,MAAM,MAAM,QAAQ;IACnC,YAAY,MAAM,MAAM,KAAK;IAC7B,QAAQ,MAAM;GAChB;GACA;EACF;CACF;CACA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQA,cAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,MAAM,IAAI,OAAO;EACvB,MAAM,QAAQ,MAAM,QAAQ,SAAS,IAAI,kBAAkB,MAAM,YAAY;EAC7E,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,SAAS;IACT,KAAK;GACP;aATF;IAWE,qBAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,eAAe;MAAU,KAAK;KAAE;eAA/D,CACE,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBAEC,MAAM;KACJ,IACL,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY,MAAM;OAClB,UAAU;OACV,OAAO,OAAO;MAChB;gBAEC;KACE,EACF;;IAML,oBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,eAAe;MACf,UAAU;MACV,gBAAgB,MAAM,WAAW,SAAS,IAAI,eAAe;MAC7D,KAAK,MAAM,WAAW,SAAS,IAAI,KAAK;KAC1C;eAEC,MAAM,WAAW,KAAK,MAAM,UAAU;MACrC,MAAM,SAAS,IAAI,OAAO,aAAa,OAAO,KAAK;MACnD,MAAM,WAAW,KAAK,WAAW,WAAW;MAC5C,OACE,qBAAC,OAAD;OAEE,OAAO;QACL,SAAS;QACT,eAAe;QACf,YAAY;QACZ,KAAK;QACL,iBAAiB,OAAO;QACxB,cAAc,MAAM;QACpB,SAAS;OACX;iBAVF,CAYE,oBAAC,OAAD,EACE,OAAO;QACL,OAAO;QACP,QAAQ;QACR,cAAc;QACd,iBAAiB,WAAW,OAAO,SAAS,OAAO;QACnD,WAAW;OACb,EACD,IACD,oBAAC,OAAD;QACE,OAAO;SACL,YAAY,MAAM;SAClB,YAAY,MAAM;SAClB,UAAU,QAAQ,YAAY;SAC9B,OAAO,OAAO;SACd,YAAY;QACd;kBAEC,QAAQ,QAAQ;OACd,EACF;SA/BE,OAAO,KAAK,CA+Bd;KAET,CAAC;IACE;IACJ,IAAI,cACH,oBAAC,OAAD;KACE,OAAO;MACL,YAAY,MAAM;MAClB,YAAY,MAAM;MAClB,UAAU;MACV,OAAO,OAAO;MACd,WAAW;KACb;eACD;IAEI,KACH;GACD;;CAET;AACF;;;;AClLA,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,iBAAiB,EAAE,KAAK,UAAU;AAG/C,MAAa,mBAAmB,EAAE,OAAO;CACvC,QAAQ;CACR,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACrB,WAAW,EAAE,IAAI,SAAS;AAC5B,CAAC;AAGD,SAAgB,WAAgC,aAAgB;CAC9D,OAAO,EAAE,OAAO;EACd,OAAO;EACP,YAAY;CACd,CAAC;AACH;AAOA,MAAM,aAAa,WAAW,EAAE,OAAO,CAAC;AACxC,MAAM,aAAa,WAAW,EAAE,OAAO,CAAC;AACxC,MAAM,iBAAiB,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACrD,MAAM,kBAAkB,WACtB,EAAE,OAAO;CACP,MAAM,EAAE,OAAO;CACf,MAAM,EAAE,OAAO;AACjB,CAAC,CACH;AACA,MAAM,aAAa,WAAW,EAAE,KAAK,CAAC,SAAS,QAAQ,CAAC,CAAC;AAEzD,MAAa,kBAAkB,EAAE,OAAO;CACtC,MAAM,EAAE,KAAK;EAAC;EAAS;EAAU;EAAQ;EAAc;CAAS,CAAC;CACjE,OAAO;CACP,MAAM;CACN,QAAQ,WAAW,SAAS;CAC5B,OAAO,WAAW,SAAS;AAC7B,CAAC;AAGD,MAAa,cAAc,EAAE,OAAO;CAClC,OAAO,EAAE,MAAM,eAAe,CAAC,CAAC,SAAS;CACzC,SAAS,EAAE,OAAO;EAChB,MAAM;EACN,SAAS,WAAW,SAAS;EAC7B,KAAK,WAAW,SAAS;EACzB,MAAM,WAAW,SAAS;EAC1B,YAAY,WAAW,SAAS;EAChC,KAAK,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;EACtC,SAAS,WAAW,SAAS;CAC/B,CAAC;CACD,SAAS,EACN,OAAO;EACN,SAAS;EACT,KAAK;EACL,MAAM,WAAW,EAAE,KAAK;GAAC;GAAS;GAAS;EAAO,CAAC,CAAC,CAAC,CAAC,SAAS;EAC/D,UAAU,WAAW,SAAS;EAC9B,aAAa,WAAW,SAAS;EACjC,iBAAiB,WAAW,SAAS;EACrC,MAAM;EACN,UAAU,EAAE,MAAM,UAAU;EAC5B,OAAO,EAAE,MAAM,UAAU;EACzB,UAAU,EAAE,MAAM,UAAU;EAC5B,aAAa,WAAW,SAAS;EACjC,cAAc,eAAe,SAAS;EACtC,aAAa,gBAAgB,SAAS;CACxC,CAAC,CAAC,CACD,SAAS;CACZ,SAAS,EACN,OAAO;EACN,OAAO,WAAW,SAAS;EAC3B,iBAAiB,WAAW,SAAS;EACrC,kBAAkB,WAAW,SAAS;CACxC,CAAC,CAAC,CACD,SAAS;CACZ,OAAO,EACJ,OAAO;EACN,OAAO;EACP,SAAS,EAAE,MACT,EAAE,OAAO;GACP,OAAO;GACP,QAAQ;GACR,OAAO;GACP,MAAM;GACN,QAAQ;EACV,CAAC,CACH;EACA,MAAM,WAAW,SAAS;CAC5B,CAAC,CAAC,CACD,SAAS;CACZ,WAAW,EACR,OAAO;EACN,QAAQ;EACR,WAAW;CACb,CAAC,CAAC,CACD,SAAS;AACd,CAAC;;;;ACrGD,MAAM,cAAc,EAAE,OAAO;CAC3B,MAAM;CACN,MAAM,EAAE,OAAO;CACf,SAAS,EAAE,OAAO;CAClB,SAAS,EAAE,OAAO;CAClB,MAAM,EAAE,OAAO;CACf,MAAM,EAAE,OAAO;CACf,QAAQ,EAAE,OAAO;AACnB,CAAC;AAED,MAAM,gBAAgB;AACtB,MAAM,WAAW;AACjB,MAAM,mBAAmB;AACzB,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,iBAAiB;AAEvB,SAAS,SAAS,QAAgB;CAChC,MAAM,OAAO,OAAO,SAAS;CAC7B,MAAM,cAAc,OAAO,MAAM;CACjC,OAAO;EACL;EACA;EACA,OAAO,OAAO,QAAQ,IAAI,OAAO;EACjC,YAAY,OAAO,SAAS,IAAI,OAAO,WAAW,cAAc;CAClE;AACF;AAEA,MAAM,YAAY;;;;;;;AAQlB,SAAS,aAAa,MAAc,KAAwC,KAAqB;CAC/F,MAAM,QAAQ,KAAK,MAAM,IAAI;CAC7B,MAAM,UAAU,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,SAAS,KAAK,MAAM,CAAC;CAC/D,MAAM,UAAU,IAAI,SAAS,UAAU;CACvC,MAAM,WAAW,IAAI,UAAU,MAAM,SAAS;CAC9C,OAAO,KAAK,IAAI,oBAAoB,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,IAAI,SAAS,QAAQ,CAAC,CAAC,CAAC;AAC5F;;;;;;AAOA,SAAS,UAAU,MAAoD;CACrE,OACE,KAAK,SAAS,UACb,KAAK,SAAS,aAAa,KAAK,KAAK,WAAW,WAAW;AAEhE;AAEA,MAAa,YAAgC;CAC3C,IAAI;CACJ,QAAQ,CAAC,SAAS;CAClB,SAAS;EAAC;EAAM;EAAiB;EAAK;EAAY;EAAU;EAAY;CAAa;CACrF;CAEA,MAAM,QAAQ;EACZ,MAAM,EAAE,OAAO,aAAa,YAAY,SAAS,SAAS,MAAM;EAChE,OAAO;GACL,MAAM;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,OAAO,QAAQ,IAAI;GAAE;GAC5F,SAAS;IAAE,UAAU;IAAG,aAAa;IAAI,aAAa;IAAI,MAAM;IAAG,KAAK,EAAE,OAAO,IAAI;GAAE;GAKvF,OAAO;IAGL,UAAU,OAAO,IAAI;IACrB,aAAa,OAAO,KAAK;IACzB,aAAa,OAAO,KAAK;IACzB,MAAM;IACN,KAAK;KAAE,OAAO,QAAQ;KAAI,QAAQ;IAAY;GAChD;GACA,MAAM;IACJ,UAAU,KAAK,MAAM,aAAa,EAAE;IACpC,aAAa,OAAO,KAAK;IACzB,aAAa;IACb,MAAM;IACN,KAAK;KAAE,OAAO,QAAQ;KAAI,QAAQ,aAAa;IAAG;GACpD;EACF;CACF;CAEA,SAAS,KAAK;EACZ,MAAM,QAAQ,YAAY,MAAM,GAAG;EACnC,OAAO;GACL,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,OAAO,MAAM,KAAK,MAAM;GACxB,MAAM,MAAM,KAAK,KAAK;EACxB;CACF;CAEA,SAAS,KAAK,MAAM;EAClB,MAAM,QAAQ,YAAY,MAAM,GAAG;EACnC,MAAM,OAAO,SAAS,UAAU,UAAU,MAAM,IAAI;EACpD,OAAO;GACL,QAAQ,OAAO,MAAM,OAAO,SAAS,UAAU,MAAM,UAAU,MAAM;GACrE,QAAQ,SAAS,UAAU,MAAM,SAAS;GAC1C,YAAY,OAAO,OAAO;GAC1B,YAAY,OAAO,QAAQ;EAC7B;CACF;CAEA,WAAW,OAAO,OAAO,OAAO;EAC9B,MAAM,OAAO,MAAM,QAAQ;EAC3B,IAAI,SAAS,QAGX,MAAM,IAAI,cACR,sBACA,wDACA,wFACF;EAEF,OAAO;GACL,OAAO;IACL;IACA,MAAM,MAAM;IACZ,SAAS,MAAM,SAAS,IAAI,SAAS;IACrC,SAAS,MAAM,UAAU,aAAa,MAAM,MAAM,KAAK,SAAS,MAAM,MAAM,QAAQ;IACpF,MAAM,MAAM,MAAM,KAAK;IACvB,MAAM,MAAM,MAAM,KAAK;IACvB,QAAQ,MAAM,MAAM,QAAQ;GAC9B;GACA,SAAS,CAAC;EACZ;CACF;CAEA,OAAO,KAAK,KAAK;EACf,MAAM,QAAQ,YAAY,MAAM,GAAG;EACnC,MAAM,SAAS,YAAY,IAAI,OAAO,IAAI,KAAK;EAC/C,MAAM,EAAE,MAAM,YAAY,UAAU,SAAS,IAAI,MAAM;EACvD,MAAM,YAAY,IAAI,MAAM,UAAU;EACtC,MAAM,WAAW,IAAI,MAAM,UAAU;EACrC,MAAM,OAAO,UAAU,MAAM,IAAI;EACjC,MAAM,aAAa,MAAM,KAAK,SAAS;EACvC,MAAM,QAAQ,IAAI,OAAO;EACzB,MAAM,OAAO,IAAI,OAAO;EACxB,MAAM,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC,CAAC,SAAS;EACtD,MAAM,WAAW,MAAM,QAAQ,MAAM,KAAK,KAAK;EAC/C,MAAM,eAAe,OACjB,aACE,UACA;GAAE,OAAO,QAAQ;GAAc,QAAQ,aAAa;EAAa,GACjE,OAAO,KAAK,EACd,IACC,MAAM,YAAY;EACvB,MAAM,YAAY,OAAO,SAAS,QAAQ,MAAM;EAChD,MAAM,aAAa,QAAQ,aAAa,MAAM,IAAI;EAElD,OACE,qBAAC,OAAD;GACE,OAAO;IACL,SAAS;IACT,eAAe;IACf,OAAO;IACP,QAAQ;IACR,iBAAiB,OAAO;IACxB,OAAO,OAAO;IACd,SAAS,IAAI,OAAO;IACpB,KAAK;IACL,WAAW,YAAY,cAAc,OAAO,YAAY;GAC1D;aAXF;IAaE,qBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,gBAAgB;MAChB,YAAY;MACZ,QAAQ;MACR,YAAY;MACZ,cAAc,WAAW,aAAa,OAAO,UAAU;MACvD,eAAe,WAAW,KAAK;KACjC;eATF,CAWE,qBAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,KAAK;OAAI,YAAY;MAAS;gBAA7D,CACG,IAAI,YAAY,SAAY,oBAAC,OAAD;OAAK,KAAK,IAAI;OAAS,OAAO;OAAI,QAAQ;MAAK,KAAI,QAChF,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,WAAW,MAAM,OAAO,MAAM;QAC1C,YAAY;QACZ,UAAU,IAAI,OAAO,MAAM,YAAY;QACvC,OAAO,OAAO;OAChB;iBAEC,IAAI,OAAO,MAAM,QAAQ,MAAM;MAC7B,EACF;SACL,oBAAC,OAAD;MACE,OAAO;OACL,YAAY,MAAM;OAClB,YAAY;OACZ,UAAU,IAAI,OAAO,SAAS,YAAY;OAC1C,OAAO,OAAO;MAChB;gBAEC,IAAI,OAAO,SAAS,QAAQ,MAAM;KAChC,EACF;;IAOL,qBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,eAAe;MACf,UAAU;MACV,gBAAgB;MAChB,KAAK;MACL,WAAW;KACb;eARF,CAUA,oBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,YAAY;OACZ,YAAY;OACZ,aAAa,YAAY,KAAK;OAC9B,YAAY,YAAY,aAAa,OAAO,YAAY;MAC1D;gBAEA,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,MAAM;QAClB,YAAY,MAAM;QAClB,UAAU,OAAO,YAAY;QAC7B,YAAY;QACZ,UAAU,SAAS,YAAY,KAAK;OACtC;iBAEC,OAAO,QAAQ,MAAM,KAAK,MAAM;MAC9B;KACF,IAEJ,aACC,oBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,eAAe,OAAO,WAAW;OACjC,KAAK;OACL,QAAQ;MACV;gBAEC,CAAC,UAAU,OAAO,CAAC,CAAC,KAAK,UACxB,qBAAC,OAAD;OAEE,OAAO;QACL,SAAS;QACT,eAAe;QACf,KAAK;QACL,OAAO;QACP,QAAQ;OACV;iBARF,CAUE,oBAAC,OAAD;QAAK,OAAO;SAAE,YAAY,MAAM;SAAM,UAAU;SAAI,OAAO,OAAO;QAAM;kBACrE,UAAU,WAAW,WAAW;OAC9B,IACL,oBAAC,OAAD;QACE,KAAK,SAAS;QACd,OAAO;QACP,QAAQ,aAAa;QACrB,OAAO,EAAE,WAAW,UAAU;OAC/B,EACE;SAlBE,KAkBF,CACN;KACE,KACH,UACF,oBAAC,OAAD;MACE,OAAO;OACL,SAAS;OACT,eAAe;OAGf,gBAAgB;OAChB,WAAW;OACX,SAAS,YAAY,OAAO,WAAW;OACvC,iBAAiB,YAAY,OAAO,OAAO,OAAO;OAClD,cAAc,WAAW,IAAI,IAAI,MAAM;OACvC,YAAY,WAAW,aAAa,OAAO,YAAY;MACzD;gBAEA,oBAAC,OAAD;OACE,OAAO;QACL,YAAY,OAAO,MAAM,OAAO,MAAM;QACtC,YAAY;QACZ,UAAU;QACV,YAAY,OAAO,mBAAmB;QACtC,YAAY,OAAO,QAAQ;QAC3B,OAAO,OAAO;OAChB;iBAEC;MACE;KACF,KACH,MACC;;IAEL,qBAAC,OAAD;KACE,OAAO;MACL,SAAS;MACT,gBAAgB;MAChB,YAAY;MACZ,YAAY,MAAM;MAClB,YAAY;MACZ,UAAU;MACV,OAAO,OAAO;KAChB;eATF,CAWE,oBAAC,OAAD;MAAK,OAAO,EAAE,YAAY,MAAM,KAAK;gBAClC,aAAa,yBAAyB;KACpC,IACJ,IAAI,cACH,oBAAC,OAAD;MAAK,OAAO,EAAE,YAAY,MAAM,KAAK;gBAAG;KAA2B,KACjE,MACD;;GACF;;CAET;AACF;;;;AC3UA,MAAM,YAAY;CAAC;CAAa;CAAmB;CAAU;CAAW;CAAO;AAAS;AAExF,SAAgB,YAAY,IAAgC;CAC1D,MAAM,QAAQ,UAAU,MAAM,aAAa,SAAS,OAAO,EAAE;CAC7D,IAAI,UAAU,QACZ,MAAM,IAAI,cACR,oBACA,qBAAqB,GAAG,KACxB,eAAe,UAAU,KAAK,aAAa,SAAS,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,EACrE;CAEF,OAAO;AACT;;;;;;;;ACHA,eAAe,UAAU,OAAoC;CAC3D,MAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,WAAW,KAAK,KAAK,CAAC;CAC3E,OAAO,MAAM,KAAK,IAAI,WAAW,MAAM,CAAC,CAAC,CACtC,KAAK,UAAU,MAAM,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CACnD,KAAK,EAAE;AACZ;AA8CA,eAAsB,SAAS,OAA+C;CAC5E,MAAM,cAAc,eAAe,MAAM,OAAO,MAAM,MAAM;CAC5D,MAAM,YAAY,MAAM,OAAO,WAAW;EAAC;EAAM;EAAiB;EAAK;CAAU;CACjF,MAAM,cAA2B,MAAM,OAAO,QAAQ,eAAe;CACrE,MAAM,cAAc,MAAM,OAAO,gBAAgB;CACjD,MAAM,QAAyB,CAAC;CAChC,MAAM,WAAyB,CAAC;CAChC,MAAM,UAAyD,CAAC;CAChE,MAAM,kCAAkB,IAAI,IAAY;CACxC,MAAM,kBAAkB,MAAM,OAAO,WAAW;CAEhD,KAAK,MAAM,cAAc,aAAa;EACpC,MAAM,WAAW,YAAY,UAAU;EACvC,IAAI,CAAC,SAAS,OAAO,SAAS,MAAM,MAAM,IAAI,GAC5C;EAEF,KAAK,MAAM,YAAY,WAAW;GAChC,IAAI,CAAC,SAAS,QAAQ,SAAS,QAAQ,GACrC;GAEF,MAAM,SAAS,QAAQ;GACvB,KAAK,MAAM,SAAS,MAAM,QAAQ;IAGhC,MAAM,OAAO,MAAM,gBAAgB,SAAS,IAAI,MAAM,MAAM,MAAM,OAAO,KAAK;IAC9E,MAAM,QAAQ,SAAS,WAAW,MAAM,OAAO,MAAM,MAAM,KAAK;IAChE,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,KAAK;IACpD,IAAI,CAAC,gBAAgB,IAAI,SAAS,EAAE,GAAG;KACrC,gBAAgB,IAAI,SAAS,EAAE;KAC/B,KAAK,MAAM,QAAQ,MAAM,SACvB,QAAQ,KAAK;MAAE,UAAU,SAAS;MAAI,MAAM,KAAK;MAAM,QAAQ,KAAK;KAAO,CAAC;IAEhF;IAEA,MAAM,EAAE,QAAQ,cAAc,MAAM,SAAS,MAAM,UAAU,UAAU,OAAO,MAAM;IACpF,KAAK,MAAM,QAAQ,WACjB,SAAS,KAAK;KACZ,MAAM;KACN,UAAU,SAAS;KACnB,QAAQ;KACR;KACA,QAAQ;IACV,CAAC;IAEH,MAAM,OAAO,aAAa,MAAM,OAAO,KAAK;IAC5C,MAAM,MAAqB;KACzB;KACA;KACA,OAAO,MAAM;KACb;KACA;IACF;IACA,IAAI,SAAS,QACX,IAAI,UAAU;IAEhB,MAAM,MAAM,SAAS,OAAO,OAAO,GAAG;IAEtC,MAAM,OAAO,MAAM,MAAM,SAAS,QAAQ,GAAG;IAC7C,MAAM,aAA4B;KAChC,OAAO,OAAO;KACd,QAAQ,OAAO;KACf,QAAQ;IACV;IACA,IAAI,SAAS,QACX,WAAW,SAAS,CAAC;KAAE,KAAK;KAAiB,MAAM;IAAK,CAAC;IAE3D,IAAI,MAAM,WAAW,QACnB,WAAW,SAAS,CAAC,GAAI,WAAW,UAAU,CAAC,GAAI,GAAG,MAAM,MAAM;IAGpE,MAAM,QAAQ,MAAM,MAAM,SAAS,OAAO,MAAM,UAAU;IAC1D,MAAM,WAAW,WAAW,SAAS,IAAI,UAAU,OAAO,iBAAiB,WAAW;IAEtF,MAAM,SAAS,MAAM,UAAU,KAAK;IACpC,MAAM,KAAK;KACT;KACA,UAAU,SAAS;KACnB,QAAQ;KACR;KACA,OAAO,OAAO;KACd,QAAQ,OAAO;KACf;KACA;IACF,CAAC;GACH;EACF;CACF;CAEA,OAAO;EACL;EACA;EACA;EACA,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,UAAU,MAAM;EAChB,aAAa,MAAM;EACnB,UAAU,kBAAkB,MAAM,KAAK;CACzC;AACF;AAEA,SAAS,eAAe,OAAsB,QAA0B;CACtE,IAAI,MAAM,SAAS,aACjB,OAAO,CAAC,WAAW;CAErB,IAAI,MAAM,SAAS,SACjB,OAAO,CAAC,OAAO;CAEjB,OAAO,OAAO,SAAS,aAAa;EAAC;EAAgB;EAAsB;CAAW;AACxF;AAEA,SAAS,kBAAkB,OAA0E;CACnG,MAAM,MAAkE,CAAC;CACzE,IAAI,MAAM,UAAU,QAClB,OAAO;CAET,MAAM,MAAM,QAAQ,SAAS,QAAQ,UAAU;EAC7C,MAAM,SAAS,cAAc,OAAO,OAAO,OAAO,OAAO,MAAM,OAAO,OAAO,OAAO,KAAK;EACzF,MAAM,SAAS,iBAAiB,OAAO,KAAK,EAAE;EAC9C,IAAI,GAAG,OAAO,aAAa;GACzB,OAAO,OAAO;GACd,cAAc;IAAC,GAAG,OAAO;IAAU,GAAG,OAAO;IAAS,GAAG,OAAO;GAAQ;EAC1E;CACF,CAAC;CACD,OAAO;AACT;AAEA,eAAe,SACb,UACA,UACA,OACA,QACsE;CACtE,MAAM,QAAQ,SAAS,MAAM,MAAM;CACnC,MAAM,QAAQ,SAAS,SAAS,KAAK;CACrC,MAAM,SAAqC,CAAC;CAC5C,MAAM,YAAsB,CAAC;CAC7B,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,KAAK,GAAG;EAChD,MAAM,OAAO,MAAM;EACnB,IAAI,SAAS,QACX;EAEF,MAAM,OAAO,SAAS,SAAS,OAAO,IAAI;EAC1C,MAAM,UAAiG;GACrG,QAAQ,KAAK;GACb,YAAY,KAAK;GACjB,QAAQ,KAAK;EACf;EACA,IAAI,KAAK,eAAe,QACtB,QAAQ,aAAa,KAAK;EAG5B,MAAM,SAAS,MAAM,QAAQ,UAAU,MAAM,MAAM,OAAO;EAC1D,OAAO,QAAQ;EACf,IAAI,OAAO,WACT,UAAU,KAAK,IAAI;CAEvB;CACA,OAAO;EAAE;EAAQ;CAAU;AAC7B;AAEA,SAAS,WACP,UACA,QACA,OACA,WACA,aACQ;CAER,OAAO,GAAG,SAAS,GAAG,SADJ,YAAY,KAAK,IAAI,QACE,GAAG;AAC9C;AAEA,SAAS,aACP,OACA,OACwB;CACxB,IAAI,UAAU,QACZ;CAEF,IAAI,UAAU,QACZ,OAAO,MAAM,QAAQ,MAAM;CAE7B,OAAO,MAAM,SAAS,MAAM;AAC9B;AAEA,eAAe,gBACb,YACA,MACA,OACA,OACe;CACf,IAAI,eAAe,aACjB,OAAO;CAET,MAAM,UAAU,MAAM,SAAS,aAAa;CAC5C,IAAI,YAAY,QACd,OAAO;EAAE,GAAG;EAAM,WAAW,eAAe;CAAE;CAEhD,OAAO;EAAE,GAAG;EAAM,WAAW,MAAM,cAAc,QAAQ,MAAM,QAAQ,MAAM,KAAK;CAAE;AACtF;;;;ACzQA,SAAgB,KACd,OACA,YACS;CACT,MAAM,YAAY,WAAW,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACjE,OAAO;EACL;EACA,YAAY;GACV,QAAQ,WAAW;GACnB,KAAK,WAAW;GAChB;EACF;CACF;AACF;;;;ACVA,SAAgB,WAAW,OAA8B;CACvD,MAAM,UAA0B,CAAC;CACjC,MAAM,UAA0B,CAAC;CACjC,MAAM,UAA0B,CAAC;CACjC,MAAM,YAA8B,CAAC;CACrC,IAAI;CAEJ,KAAK,MAAM,QAAQ,OAAO;EACxB,WAAW,SAAS,KAAK,OAAO;EAChC,aAAa,SAAS,KAAK,OAAO;EAClC,WAAW,SAAS,KAAK,OAAO;EAChC,WAAW,WAAW,KAAK,SAAS;EACpC,IAAI,KAAK,UAAU,QACjB,QAAQ,KAAK;CAEjB;CAEA,IAAI,QAAQ,SAAS,QACnB,MAAM,IAAI,cACR,sBACA,yCACA,0DACF;CAGF,MAAM,QAAe,EACnB,SAAS,EACP,MAAM,QAAQ,KAChB,EACF;CACA,IAAI,QAAQ,YAAY,QACtB,MAAM,QAAQ,UAAU,QAAQ;CAElC,IAAI,QAAQ,QAAQ,QAClB,MAAM,QAAQ,MAAM,QAAQ;CAE9B,IAAI,QAAQ,SAAS,QACnB,MAAM,QAAQ,OAAO,QAAQ;CAE/B,IAAI,QAAQ,eAAe,QACzB,MAAM,QAAQ,aAAa,QAAQ;CAErC,IAAI,QAAQ,QAAQ,QAClB,MAAM,QAAQ,MAAM,QAAQ;CAE9B,IAAI,QAAQ,YAAY,QACtB,MAAM,QAAQ,UAAU,QAAQ;CAOlC,IAAI,kBAAkB,OAAO,GAAG;EAC9B,MAAM,UAAU;GACd,SAAS,QAAQ;GACjB,KAAK,QAAQ;GACb,MAAM,QAAQ;GACd,UAAU,QAAQ,YAAY,CAAC;GAC/B,OAAO,QAAQ,SAAS,CAAC;GACzB,UAAU,QAAQ,YAAY,CAAC;EACjC;EACA,IAAI,QAAQ,SAAS,QACnB,MAAM,QAAQ,OAAO,QAAQ;EAE/B,IAAI,QAAQ,aAAa,QACvB,MAAM,QAAQ,WAAW,QAAQ;EAEnC,IAAI,QAAQ,gBAAgB,QAC1B,MAAM,QAAQ,cAAc,QAAQ;EAEtC,IAAI,QAAQ,oBAAoB,QAC9B,MAAM,QAAQ,kBAAkB,QAAQ;EAE1C,IAAI,QAAQ,gBAAgB,QAC1B,MAAM,QAAQ,cAAc,QAAQ;EAEtC,IAAI,QAAQ,iBAAiB,QAC3B,MAAM,QAAQ,eAAe,QAAQ;EAEvC,IAAI,QAAQ,gBAAgB,QAC1B,MAAM,QAAQ,cAAc,QAAQ;CAExC;CAEA,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,GAChC,MAAM,UAAU;CAElB,IAAI,UAAU,QACZ,MAAM,QAAQ;CAEhB,IAAI,UAAU,WAAW,UAAa,UAAU,cAAc,QAC5D,MAAM,YAAY;EAAE,QAAQ,UAAU;EAAQ,WAAW,UAAU;CAAU;CAE/E,OAAO;AACT;AAEA,SAAS,aAAa,QAAwB,SAA2C;CACvF,IAAI,YAAY,QACd;CAEF,WAAW,QAAQ,SAAS;EAAC;EAAY;EAAS;CAAU,CAAC;CAC7D,YAAY,QAAQ,SAAS,UAAU;CACvC,YAAY,QAAQ,SAAS,OAAO;CACpC,YAAY,QAAQ,SAAS,UAAU;AACzC;AAEA,SAAS,YACP,QACA,SACA,KACM;CACN,MAAM,OAAO,QAAQ;CACrB,IAAI,SAAS,QACX,OAAO,OAAO;AAElB;AAEA,SAAS,WAA6B,QAAW,SAAwB,OAAoB,CAAC,GAAS;CACrG,IAAI,YAAY,QACd;CAEF,MAAM,UAAU,IAAI,IAAI,IAAI;CAC5B,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GAAkB;EACrD,IAAI,QAAQ,IAAI,GAAG,GACjB;EAEF,MAAM,QAAQ,QAAQ;EACtB,IAAI,UAAU,UAAa,OAAO,SAAS,QACzC,OAAO,OAAO;CAElB;AACF;AAEA,SAAS,kBACP,SAE2D;CAC3D,OAAO,QAAQ,YAAY,UAAa,QAAQ,QAAQ,UAAa,QAAQ,SAAS;AACxF;;;;ACxIA,MAAM,eAAe,EAAE,OAAO;CAC5B,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACvB,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO;CAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO;CACzB,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,kBAAkB,EAAE,OAAO;CAC/B,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACvB,SAAS,EAAE,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;CAC3C,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;AAC5B,CAAC;AAED,eAAsB,iBAAiB,KAAa,WAAW,wBAA+C;CAC5G,MAAM,WAAW,WAAW,QAAQ,IAAI,WAAW,KAAK,KAAK,QAAQ;CACrE,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,UAAU,MAAM;CACvC,SAAS,OAAO;EACd,MAAM,IAAI,cACR,sBACA,6BAA6B,SAAS,IACtC,qGACA,EAAE,OAAO,MAAM,CACjB;CACF;CACA,IAAI;CACJ,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,SAAS,OAAO;EACd,MAAM,IAAI,cACR,sBACA,qCAAqC,SAAS,IAC9C,oCACA,EAAE,OAAO,MAAM,CACjB;CACF;CACA,MAAM,SAAS,gBAAgB,UAAU,IAAI;CAC7C,IAAI,CAAC,OAAO,SACV,MAAM,IAAI,cACR,uBACA,8CAA8C,SAAS,IACvD,wGACF;CAEF,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,MAAM;CACZ,MAAM,QAAqC;EACzC,OAAO,KAAK,OAAO,KAAK,OAAO;GAAE,QAAQ;GAAc,KAAK,GAAG,IAAI;GAAS;EAAU,CAAC;EACvF,SAAS,OAAO,KAAK,QAAQ,KAAK,QAAQ,WAAW;GACnD,OAAO,KAAK,OAAO,OAAO;IAAE,QAAQ;IAAc,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,EAAE;IAAU;GAAU,CAAC;GAC5G,QAAQ,KAAK,OAAO,QAAQ;IAAE,QAAQ;IAAc,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,EAAE;IAAW;GAAU,CAAC;GAC/G,OAAO,KAAK,OAAO,OAAO;IAAE,QAAQ;IAAc,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,EAAE;IAAU;GAAU,CAAC;GAC5G,MAAM,KAAK,OAAO,MAAM;IAAE,QAAQ;IAAc,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,EAAE;IAAS;GAAU,CAAC;GACzG,QAAQ,KAAK,OAAO,QAAQ;IAAE,QAAQ;IAAc,KAAK,GAAG,IAAI,WAAW,OAAO,KAAK,EAAE;IAAW;GAAU,CAAC;EACjH,EAAE;CACJ;CACA,IAAI,OAAO,KAAK,SAAS,QACvB,MAAM,OAAO,KAAK,OAAO,KAAK,MAAM;EAAE,QAAQ;EAAc,KAAK,GAAG,IAAI;EAAQ;CAAU,CAAC;CAE7F,OAAO,EAAE,MAAM;AACjB;;;;AChEA,eAAsB,cAAc,KAAoC;CACtE,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,SAAS,KAAK,KAAK,WAAW,GAAG,MAAM;CAC1D,QAAQ;EACN,OAAO,CAAC;CACV;CACA,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,MAAoB,CAAC;CAC3B,MAAM,KAAK,UAAU,QAAQ;CAC7B,MAAM,UAAU,eAAe,QAAQ;CACvC,MAAM,UAAU,sBAAsB,QAAQ;CAE9C,MAAM,UAA0B,CAAC;CACjC,IAAI,OAAO,QACT,QAAQ,OAAO,KAAK,IAAI;EAAE,QAAQ;EAAU,KAAK;EAAgB;CAAU,CAAC;CAE9E,IAAI,YAAY,QACd,QAAQ,UAAU,KAAK,WAAW,OAAO,GAAG;EAC1C,QAAQ;EACR,KAAK;EACL;CACF,CAAC;CAEH,IAAI,QAAQ,SAAS,UAAa,QAAQ,YAAY,QACpD,IAAI,UAAU;CAEhB,IAAI,YAAY,QACd,IAAI,UAAU,EACZ,aAAa,KAAK,SAAS;EACzB,QAAQ;EACR,KAAK;EACL;CACF,CAAC,EACH;CAEF,OAAO;AACT;AAEA,eAAsB,yBACpB,KACA,MACuB;CACvB,MAAM,SAAS,iBAAiB,IAAI;CACpC,IAAI,WAAW,QACb,OAAO,CAAC;CAEV,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,SAAS,KAAK,KAAK,OAAO,IAAI,GAAG,MAAM;CAC1D,QAAQ;EACN,OAAO,CAAC;CACV;CAEA,MAAM,QADQ,SAAS,MAAM,OACX,CAAC,CAAC,MAAM,OAAO,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC,KAAK,IAAI;CACjE,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,OAAO,EACL,SAAS,EACP,aAAa,KACX;EAAE,MAAM;EAAO,MAAM,aAAa,OAAO,IAAI;CAAE,GAC/C;EAAE,QAAQ;EAAe,KAAK;EAAM;CAAU,CAChD,EACF,EACF;AACF;;;;;;;;;AAUA,SAAS,cAAc,UAA0B;CAC/C,OAAO,SACJ,QAAQ,mBAAmB,EAAE,CAAC,CAC9B,QAAQ,mBAAmB,EAAE,CAAC,CAC9B,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAgB,UAAU,UAAsC;CAE9D,MAAM,UADQ,cAAc,KAAK,cAAc,QAAQ,CACnC,CAAC,GAAG;CACxB,IAAI,YAAY,QACd;CAEF,OAAO,QAAQ,QAAQ,0BAA0B,IAAI,CAAC,CAAC,KAAK;AAC9D;AAEA,SAAgB,eAAe,UAAsC;CACnE,MAAM,QAAQ,cAAc,QAAQ;CACpC,MAAM,KAAK,YAAY,KAAK,KAAK;CACjC,MAAM,QAAQ,OAAO,OAAO,KAAK,GAAG,SAAS,KAAK,GAAG,EAAE,CAAC;CACxD,KAAK,MAAM,SAAS,MAAM,MAAM,KAAK,CAAC,CAAC,MAAM,SAAS,GAAG;EACvD,MAAM,UAAU,YAAY,KAAK,CAAC,CAAC,KAAK;EACxC,IAAI,QAAQ,UAAU,MAAM,CAAC,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,WAAW,KAAK,GAC/E,OAAO;CAEX;AAEF;AAEA,SAAgB,sBAAsB,UAA8D;CAClG,MAAM,QAAQ,qCAAqC,KAAK,QAAQ;CAChE,IAAI,UAAU,QAAQ,MAAM,OAAO,UAAa,MAAM,OAAO,QAC3D;CAEF,OAAO;EAAE,MAAM,MAAM;EAAI,MAAM,MAAM,EAAE,CAAC,QAAQ,OAAO,EAAE;CAAE;AAC7D;AAEA,SAAS,iBAAiB,MAAwE;CAChG,MAAM,QAAQ,iDAAiD,KAAK,IAAI;CACxE,IAAI,UAAU,QAAQ,MAAM,WAAW,QACrC;CAEF,MAAM,OAAO,MAAM,OAAO;CAC1B,MAAM,QAAQ,OAAO,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE;CAC3D,MAAM,MAAM,OAAO,SAAS,MAAM,OAAO,OAAO,MAAM,OAAO,SAAS,KAAK,EAAE;CAC7E,IAAI,SAAS,UAAa,QAAQ,KAAK,MAAM,OAC3C;CAEF,OAAO;EAAE;EAAM;EAAO;CAAI;AAC5B;AAEA,SAAS,aAAa,MAAsB;CAC1C,MAAM,MAAM,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,EAAE;CACzC,IAAI,QAAQ,MACV,OAAO;CAET,IAAI,QAAQ,OACV,OAAO;CAET,IAAI,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,OAC3C,OAAO;CAET,IAAI,QAAQ,OACV,OAAO;CAET,OAAO,IAAI,SAAS,IAAI,MAAM;AAChC;AAEA,SAAS,YAAY,MAAsB;CACzC,OAAO,KACJ,QAAQ,oCAAoC,EAAE,CAAC,CAC/C,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,gBAAgB,EAAE,CAAC,CAC3B,QAAQ,YAAY,EAAE,CAAC,CACvB,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK;AACV;;;;;ACtJA,MAAM,kBAAkB;AAExB,SAAgB,iBAAiB,MAAsB;CACrD,OACE,KACG,QAAQ,eAAe,EAAE,CAAC,CAE1B,QAAQ,kCAAkC,EAAE,CAAC,CAC7C,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,aAAa,EAAE,CAAC,CACxB,QAAQ,qBAAqB,EAAE,CAAC,CAChC,QAAQ,WAAW,EAAE,CAAC,CAEtB,QAAQ,4CAA4C,EAAE,CAAC,CACvD,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,gBAAgB,EAAE,CAAC,CAC3B,QAAQ,qBAAqB,EAAE,CAAC,CAChC,QAAQ,YAAY,EAAE,CAAC,CACvB,QAAQ,yBAAyB,EAAE,CAAC,CAEpC,WAAW,yBAAyB,EAAE,CAAC,CACvC,WAAW,0BAA0B,IAAI,CAAC,CAC1C,WAAW,YAAY,EAAE,CAAC,CAC1B,WAAW,iBAAiB,IAAI,CAAC,CACjC,WAAW,SAAS,EAAE,CAAC,CACvB,QAAQ,eAAe,EAAE,CAAC,CAE1B,QAAQ,eAAe,EAAE,CAAC,CAC1B,QAAQ,gBAAgB,IAAI,CAAC,CAC7B,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK,CAAC,CACN,QAAQ,cAAc,EAAE,CAAC,CACzB,QAAQ,OAAO,EAAE;AAExB;;;;AChCA,eAAsB,iBACpB,KACA,SACA,gBAAgB,gBACO;CACvB,IAAI,YAAY,QACd,OAAO,CAAC;CAEV,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,SAAS,KAAK,KAAK,aAAa,GAAG,MAAM;CAC5D,QAAQ;EACN,OAAO,CAAC;CACV;CACA,MAAM,UAAU,mBAAmB,UAAU,OAAO;CACpD,IAAI,YAAY,QACd,OAAO,CAAC;CAEV,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,WAA2B,CAAC;CAClC,MAAM,QAAwB,CAAC;CAC/B,MAAM,WAA2B,CAAC;CAElC,KAAK,MAAM,SAAS,YAAY,QAAQ,IAAI,GAAG;EAC7C,MAAM,SAAS,iBAAiB,MAAM,OAAO;EAC7C,IAAI,WAAW,QACb;EAEF,KAAK,MAAM,QAAQ,MAAM,OAAO;GAC9B,MAAM,UAAU,mBAAmB,IAAI;GACvC,IAAI,QAAQ,WAAW,GACrB;GAEF,MAAM,QAAQ,KAAK,SAAS;IAC1B,QAAQ;IACR,KAAK,GAAG,cAAc,GAAG,QAAQ,QAAQ,GAAG,MAAM,QAAQ,IAAI;IAC9D;GACF,CAAC;GACD,IAAI,WAAW,YACb,SAAS,KAAK,KAAK;QACd,IAAI,WAAW,SACpB,MAAM,KAAK,KAAK;QAEhB,SAAS,KAAK,KAAK;EAEvB;CACF;CAEA,MAAM,MAAoB,EACxB,SAAS;EACP,SAAS,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG;GACvC,QAAQ;GACR,KAAK,GAAG,cAAc,GAAG,QAAQ;GACjC;EACF,CAAC;EACD,KAAK,KAAK,QAAQ,WAAW,GAAG,IAAI,UAAU,IAAI,WAAW;GAC3D,QAAQ;GACR,KAAK,GAAG,cAAc,GAAG,QAAQ;GACjC;EACF,CAAC;EACD;EACA;EACA;CACF,EACF;CAKA,KAAK,MAAM,QAAQ,CAAC,YAAY,aAAa,GAAY;EAEvD,MAAM,OADS,IAAI,OAAO,wBAAwB,KAAK,qBAAqB,CAAC,CAAC,KAAK,QAAQ,IACzE,CAAC,GAAG,EAAE,EAAE,KAAK;EAC/B,IAAI,SAAS,UAAa,KAAK,SAAS,GACtC,IAAI,UAAU;GACZ,GAAG,IAAI;IACN,OAAO,KAAK,MAAM;IACjB,QAAQ;IACR,KAAK,GAAG,cAAc,GAAG,QAAQ,QAAQ,YAAY,KAAK;IAC1D;GACF,CAAC;EACH;CAEJ;CAKA,MAAM,UAAU,sBAAsB,QAAQ,IAAI;CAClD,IAAI,YAAY,QACd,IAAI,UAAU;EACZ,GAAG,IAAI;EACP,aAAa,KAAK,SAAS;GACzB,QAAQ;GACR,KAAK,GAAG,cAAc,GAAG,QAAQ,QAAQ;GACzC;EACF,CAAC;CACH;CAEF,IAAI,QAAQ,SAAS,QACnB,IAAI,UAAU;EACZ,GAAG,IAAI;EACP,MAAM,KAAK,QAAQ,MAAM;GACvB,QAAQ;GACR,KAAK,GAAG,cAAc,GAAG,QAAQ;GACjC;EACF,CAAC;CACH;CAEF,OAAO;AACT;AAEA,SAAgB,mBACd,UACA,SAC8D;CAC9D,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE;CAEvC,MAAM,UAAU,CAAC,GAAG,SAAS,SAAS,eAAS,CAAC;CAChD,KAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;EACtD,MAAM,QAAQ,QAAQ;EACtB,IAAI,UAAU,QACZ;EAEF,MAAM,UAAU,MAAM;EACtB,IAAI,YAAY,UAAa,CAAC,uBAAuB,SAAS,MAAM,GAClE;EAEF,MAAM,SAAS,MAAM,SAAS,KAAK,MAAM,EAAE,CAAC;EAE5C,MAAM,MADO,QAAQ,QAAQ,EACb,EAAE,SAAS,SAAS;EACpC,MAAM,OAAO,YAAY,OAAO;EAChC,MAAM,OAAO,SAAS,MAAM,OAAO,GAAG;EACtC,IAAI,SAAS,QACX,OAAO;GAAE;GAAS;EAAK;EAEzB,OAAO;GAAE;GAAS;GAAM;EAAK;CAC/B;AAEF;AAEA,SAAgB,mBAAmB,MAAsB;CACvD,OAAO,iBAAiB,IAAI;AAC9B;AAEA,SAAS,uBAAuB,SAAiB,SAA0B;CACzE,MAAM,YAAY,QAAQ,QAAQ,UAAU,GAAG;CAC/C,OAAO,IAAI,OAAO,cAAc,aAAa,OAAO,EAAE,UAAU,CAAC,CAAC,KAAK,SAAS;AAClF;AAEA,SAAS,YAAY,SAAqC;CAExD,OADc,sBAAsB,KAAK,OAC9B,CAAC,GAAG;AACjB;AAEA,SAAS,YAAY,MAA2D;CAC9E,MAAM,SAAsD,CAAC;CAE7D,MAAM,UAAU,CAAC,GAAG,KAAK,SAAS,gBAAS,CAAC;CAC5C,IAAI,QAAQ,WAAW,GACrB,OAAO,CAAC;EAAE,SAAS;EAAS,OAAO,UAAU,IAAI;CAAE,CAAC;CAEtD,KAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS,GAAG;EACtD,MAAM,QAAQ,QAAQ;EACtB,IAAI,UAAU,QACZ;EAEF,MAAM,UAAU,MAAM;EACtB,IAAI,YAAY,QACd;EAEF,MAAM,SAAS,MAAM,SAAS,KAAK,MAAM,EAAE,CAAC;EAE5C,MAAM,MADO,QAAQ,QAAQ,EACb,EAAE,SAAS,KAAK;EAChC,OAAO,KAAK;GAAE;GAAS,OAAO,UAAU,KAAK,MAAM,OAAO,GAAG,CAAC;EAAE,CAAC;CACnE;CACA,OAAO;AACT;AAEA,SAAS,UAAU,OAAyB;CAC1C,MAAM,QAAkB,CAAC;CACzB,IAAI;CACJ,KAAK,MAAM,OAAO,MAAM,MAAM,IAAI,GAAG;EACnC,MAAM,UAAU,IAAI,KAAK;EAKzB,IAAI,CADa,OAAO,KAAK,GACjB,MAAM,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,IAAI,IAAI;GACvE,IAAI,YAAY,QACd,MAAM,KAAK,OAAO;GAEpB,UAAU;GACV;EACF;EACA,IAAI,YAAY,UAAa,QAAQ,SAAS,KAAK,CAAC,QAAQ,WAAW,GAAG,GACxE,UAAU,GAAG,QAAQ,GAAG;CAE5B;CACA,IAAI,YAAY,QACd,MAAM,KAAK,OAAO;CAEpB,OAAO;AACT;AAEA,SAAS,iBAAiB,SAAgE;CACxF,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC,YAAY;CACvC,IACE,QAAQ,WACR,QAAQ,aACR,QAAQ,mBACR,QAAQ,YAER,OAAO;CAET,IAAI,QAAQ,WAAW,QAAQ,mBAAmB,QAAQ,cAAc,QAAQ,SAC9E,OAAO;CAET,IACE,QAAQ,aACR,QAAQ,mBACR,QAAQ,cACR,QAAQ,oBAER,OAAO;AAGX;AAEA,SAAS,aAAa,OAAuB;CAC3C,OAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;;ACvOA,MAAMC,kBAAgB,UAAU,QAAQ;AAExC,eAAsB,WACpB,KACA,OACuB;CAEvB,IAAI,MADiB,IAAI,KAAK,CAAC,aAAa,uBAAuB,CAAC,MACrD,QACb,OAAO,CAAC;CAEV,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,MAAM,MAAM,OAAQ,MAAM,cAAc,GAAG;CACjD,IAAI,QAAQ,QACV,OAAO,CAAC;CAGV,IAAI,MADiB,IAAI,KAAK;EAAC;EAAa;EAAY,GAAG,IAAI;CAAU,CAAC,MAC3D,QACb,OAAO,CAAC;CAEV,MAAM,UAAU,eAAe,GAAG;CAClC,MAAM,OAAO,MAAM,SAAS,KAAK,CAAC,OAAO,mBAAmB,CAAC;CAC7D,MAAM,WAAW,KAAK,QAAQ,GAAG;CACjC,MAAM,cACJ,MAAM,gBAAgB,YAAY,IAAI,KAAK,WAAW,KAAK,KAAK,MAAM,cAAc,cAAc,GAAG;CACvG,MAAM,QAAQ,gBAAgB,SAAY,MAAM,GAAG,YAAY,IAAI;CAEnE,MAAM,WAAW,MADC,IAAI,KAAK;EAAC;EAAO;EAAO;CAAuC,CAAC,KAC1D,GAAE,CAAE,MAAM,IAAI,CAAC,CAAC,QAAQ,SAAS,KAAK,SAAS,CAAC;CACxE,MAAM,WAA2B,CAAC;CAClC,MAAM,QAAwB,CAAC;CAC/B,MAAM,WAA2B,CAAC;CAClC,MAAM,+BAAe,IAAI,IAAoB;CAE7C,KAAK,MAAM,QAAQ,SAAS;EAC1B,MAAM,CAAC,SAAS,QAAQ,OAAO,QAAQ,KAAK,MAAM,GAAI;EACtD,IAAI,YAAY,UAAa,SAAS,QACpC;EAEF,MAAM,SAAS,kBAAkB,OAAO;EACxC,MAAM,UAAU,OAAO;EACvB,MAAM,MAAM,WAAW,MAAM,GAAG;EAChC,MAAM,OAAO,KAAK,SAAS;GAAE,QAAQ;GAAO;GAAK;EAAU,CAAC;EAC5D,IAAI,OAAO,UACT,SAAS,KAAK,IAAI;OACb,IAAI,OAAO,SAAS,QACzB,SAAS,KAAK,IAAI;OACb,IAAI,OAAO,SAAS,SAAS,OAAO,SAAS,QAClD,MAAM,KAAK,IAAI;EAEjB,IAAI,UAAU,UAAa,WAAW,UAAa,CAAC,MAAM,QAAQ,KAAK,GACrE,aAAa,IAAI,OAAO,MAAM;CAElC;CAGA,MAAM,QAAQ,MADS,IAAI,KAAK;EAAC;EAAO;EAAM;EAAgB;CAAG,CAAC,KACxC,UAAS,CAAE,MAAM,GAAG,EAAE;CAChD,MAAM,QAAQ,CAAC,GAAG,aAAa,OAAO,CAAC;CAEvC,MAAM,UAAgD;EACpD,SAAS,KAAK,SAAS;GAAE,QAAQ;GAAO,KAAK,WAAW;GAAO;EAAU,CAAC;EAC1E,KAAK,KAAK,KAAK;GAAE,QAAQ;GAAO,KAAK,WAAW;GAAO;EAAU,CAAC;EAClE,MAAM,KAAK,MAAM;GAAE,QAAQ;GAAO,KAAK,2BAA2B;GAAO;EAAU,CAAC;EACpF;EACA;EACA;EACA,aAAa,KAAK,QAAQ,QAAQ;GAChC,QAAQ;GACR,KAAK,wBAAwB;GAC7B;EACF,CAAC;CACH;CACA,IAAI,gBAAgB,QAAW;EAC7B,QAAQ,kBAAkB,KAAK,eAAe,WAAW,GAAG;GAC1D,QAAQ;GACR,KAAK,WAAW;GAChB;EACF,CAAC;EACD,MAAM,OAAO,YAAY,eAAe,WAAW,GAAG,eAAe,GAAG,CAAC;EACzE,IAAI,SAAS,QACX,QAAQ,OAAO,KAAK,MAAM;GACxB,QAAQ;GACR,KAAK,UAAU,YAAY,IAAI;GAC/B;EACF,CAAC;CAEL;CACA,IAAI,MAAM,SAAS,GACjB,QAAQ,eAAe,KAAK,OAAO;EACjC,QAAQ;EACR,KAAK,WAAW,MAAM;EACtB;CACF,CAAC;CAEH,OAAO,EAAE,QAAQ;AACnB;AAEA,SAAgB,kBAAkB,SAIhC;CACA,MAAM,QAAQ,+DAA+D,KAAK,OAAO;CACzF,IAAI,UAAU,QAAQ,MAAM,WAAW,QACrC,OAAO;EAAE,MAAM;EAAW,SAAS,eAAe,OAAO;EAAG,UAAU;CAAM;CAE9E,MAAM,OAAO,MAAM,OAAO;CAC1B,MAAM,OAAO,MAAM,OAAO,QAAQ;CAClC,MAAM,WAAW,MAAM,OAAO,SAAS,OAAO,mBAAmB,KAAK,OAAO;CAC7E,OAAO;EAAE;EAAM,SAAS,eAAe,IAAI;EAAG;CAAS;AACzD;AAEA,SAAgB,eAAe,KAAqB;CAClD,MAAM,KAAK,IAAI,YAAY,GAAG;CAC9B,IAAI,MAAM,KAAK,KAAK,IAAI,SAAS,GAC/B,OAAO,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE;CAE3C,OAAO,IAAI,QAAQ,MAAM,EAAE;AAC7B;AAEA,eAAsB,cAAc,KAA0C;CAC5E,OAAO,IAAI,KAAK;EAAC;EAAY;EAAU;CAAY,CAAC;AACtD;AAEA,eAAe,IAAI,KAAa,MAA6C;CAC3E,IAAI;EACF,MAAM,EAAE,WAAW,MAAMA,gBAAc,OAAO,MAAM,EAAE,IAAI,CAAC;EAC3D,MAAM,UAAU,OAAO,KAAK;EAC5B,OAAO,QAAQ,WAAW,IAAI,SAAY;CAC5C,QAAQ;EACN;CACF;AACF;AAEA,eAAe,SAAS,KAAa,MAAmC;CACtE,MAAM,MAAM,MAAM,IAAI,KAAK,IAAI;CAC/B,OAAO,QAAQ,SAAY,CAAC,IAAI,IAAI,MAAM,IAAI,CAAC,CAAC,QAAQ,SAAS,KAAK,SAAS,CAAC;AAClF;AAEA,SAAS,MAAM,QAAgB,OAAwB;CACrD,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,YAAY;CAClD,OACE,OAAO,SAAS,OAAO,KACvB,SAAS,SAAS,YAAY,KAC9B,SAAS,SAAS,UAAU,KAC5B,SAAS,SAAS,gBAAgB;AAEtC;AAEA,SAAS,eAAe,MAAsB;CAC5C,MAAM,UAAU,mBAAmB,IAAI;CACvC,MAAM,QAAQ,QAAQ,GAAG,CAAC;CAC1B,IAAI,UAAU,QACZ,OAAO;CAET,OAAO,MAAM,YAAY,IAAI,QAAQ,MAAM,CAAC;AAC9C;;;;;;;;AASA,eAAsB,iBAAiB,KAAoC;CACzE,MAAM,SAAS,MAAM,IAAI,KAAK;EAAC;EAAU;EAAW;CAAQ,CAAC;CAC7D,IAAI,WAAW,QACb,OAAO,CAAC;CAEV,MAAM,OAAO,WAAW,OAAO,KAAK,CAAC;CACrC,IAAI,SAAS,QACX,OAAO,CAAC;CAGV,MAAM,aAAa;EAAE,QAAQ;EAAgB,KAAK;EAA6B,4BAD7D,IAAI,KAAK,EAAC,CAAC,YAC0D;CAAE;CACzF,OAAO,EACL,SAAS;EACP,MAAM,KAAK,MAAM,UAAU;EAC3B,KAAK,KAAK,sBAAsB,QAAQ,UAAU;CACpD,EACF;AACF;AAEA,SAAS,WAAW,KAAiC;CACnD,MAAM,UAAU,IAAI,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,UAAU,EAAE;CAC9D,OAAO,iCAAiC,KAAK,OAAO,CAAC,GAAG;AAC1D;;;;;;;;AASA,SAAgB,YACd,UACA,SACyC;CACzC,MAAM,SAAS,YAAY,QAAQ;CACnC,MAAM,QAAQ,YAAY,OAAO;CACjC,IAAI,WAAW,UAAa,UAAU,QACpC;CAEF,IAAI,MAAM,OAAO,OAAO,IACtB,OAAO;CAET,IAAI,MAAM,OAAO,OAAO,IACtB,OAAO;CAET,OAAO,MAAM,OAAO,OAAO,KAAK,SAAY;AAC9C;AAEA,SAAS,YAAY,OAAqD;CACxE,MAAM,QAAQ,uBAAuB,KAAK,MAAM,QAAQ,MAAM,EAAE,CAAC;CACjE,IAAI,UAAU,MACZ;CAEF,OAAO;EAAC,OAAO,MAAM,EAAE;EAAG,OAAO,MAAM,EAAE;EAAG,OAAO,MAAM,EAAE;CAAC;AAC9D;;;;ACrNA,MAAM,cAAc;AACpB,MAAMC,aAAW;AAEjB,MAAM,aAAa,EAAE,OAAO;CAC1B,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CAC/C,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC5C,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACzC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;AAC5E,CAAC;AAED,MAAM,gBAAgB,EAAE,OAAO,EAC7B,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,EACvC,CAAC;AAED,MAAM,qBAAqB,EAAE,MAAM,EAAE,QAAQ,CAAC;AAe9C,eAAsB,cAAc,SAAsD;CACxF,MAAM,OAAO,UAAU,QAAQ,IAAI;CACnC,IAAI,SAAS,QACX,OAAO,CAAC;CAEV,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,QAAQ,QAAQ,yBAAS,IAAI,IAA8B;CACjE,MAAM,eAAe,MAAM,UACzB,GAAGA,WAAS,SAAS,KAAK,MAAM,GAAG,KAAK,QACxC,QAAQ,OACR,WACA,KACF;CACA,IAAI,iBAAiB,QACnB,OAAO,CAAC;CAEV,MAAM,OAAO,WAAW,MAAM,aAAa,IAAI;CAC/C,MAAM,MAAoB;EACxB,SAAS,EACP,OAAO,KAAK,KAAK,kBAAkB;GACjC,QAAQ;GACR,KAAK,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;GAC3C;EACF,CAAC,EACH;EACA,SAAS,CAAC;CACZ;CACA,IAAI,KAAK,gBAAgB,UAAa,KAAK,gBAAgB,QAAQ,KAAK,YAAY,SAAS,GAC3F,IAAI,UAAU;EACZ,GAAG,IAAI;EACP,SAAS,KAAK,WAAW,KAAK,WAAW,GAAG;GAC1C,QAAQ;GACR,KAAK,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;GAC3C;EACF,CAAC;CACH;CAEF,IAAI,KAAK,aAAa,UAAa,KAAK,aAAa,QAAQ,KAAK,SAAS,SAAS,GAClF,IAAI,UAAU;EACZ,GAAG,IAAI;EACP,KAAK,KAAK,KAAK,UAAU;GACvB,QAAQ;GACR,KAAK,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;GAC3C;EACF,CAAC;CACH;CAEF,MAAM,UAAU,KAAK,SAAS;CAC9B,IAAI,YAAY,UAAa,YAAY,QAAQ,YAAY,eAC3D,IAAI,UAAU;EACZ,GAAG,IAAI;EACP,SAAS,KAAK,SAAS;GACrB,QAAQ;GACR,KAAK,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;GAC3C;EACF,CAAC;CACH;CAGF,IAAI,QAAQ,QAAQ,QAAW;EAC7B,MAAM,kBAAkB,MAAM,UAC5B,GAAGA,WAAS,SAAS,KAAK,MAAM,GAAG,KAAK,KAAK,iBAAiB,mBAAmB,QAAQ,GAAG,KAC5F,QAAQ,OACR,WACA,OACA,EAAE,YAAY,KAAK,CACrB;EACA,IAAI,oBAAoB,QAAW;GAEjC,MAAM,WAAW,wBADD,cAAc,MAAM,gBAAgB,IACL,CAAC,CAAC,QAAQ,IAAI,QAAQ,KAAK,SAAS;GACnF,IAAI,SAAS,SAAS,GACpB,IAAI,UAAU,EAAE,SAAS;EAE7B;CACF;CAEA,MAAM,eAAe,MAAM,UACzB,GAAGA,WAAS,SAAS,KAAK,MAAM,GAAG,KAAK,KAAK,qCAC7C,QAAQ,OACR,WACA,OACA,EAAE,YAAY,KAAK,CACrB;CACA,IAAI,iBAAiB,QAAW;EAC9B,mBAAmB,MAAM,aAAa,IAAI;EAC1C,MAAM,SAAS,MAAM,QAAQ,aAAa,IAAI,IAAI,aAAa,KAAK,SAAS;EAC7E,MAAM,WAAW,iBAAiB,aAAa,IAAI;EACnD,IAAI,UAAU;GACZ,GAAG,IAAI;GACP,kBAAkB,KAAK,YAAY,QAAQ;IACzC,QAAQ;IACR,KAAK,cAAc,KAAK,MAAM,GAAG,KAAK,KAAK;IAC3C;GACF,CAAC;EACH;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,UAAU,OAA4D;CACpF,MAAM,UAAU,MAAM,KAAK,CAAC,CAAC,QAAQ,UAAU,EAAE;CACjD,MAAM,QAAQ,sEAAsE,KAAK,OAAO;CAChG,IAAI,UAAU,QAAQ,MAAM,OAAO,UAAa,MAAM,OAAO,QAC3D;CAEF,OAAO;EAAE,OAAO,MAAM;EAAI,MAAM,MAAM;CAAG;AAC3C;AAEA,SAAS,wBAAwB,MAAc,KAAa,WAAmC;CAK7F,OAJc,KACX,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,QAAQ,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CACrD,QAAQ,SAAS,KAAK,SAAS,KAAK,CAAC,KAAK,WAAW,GAAG,CAChD,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,SAC5B,KAAK,KAAK,QAAQ,OAAO,EAAE,GAAG;EAC5B,QAAQ;EACR,KAAK,gCAAgC,IAAI;EACzC;CACF,CAAC,CACH;AACF;AAEA,eAAe,UACb,KACA,OACA,WACA,OACA,OAAiC,CAAC,GACK;CACvC,MAAM,SAAS,MAAM,IAAI,GAAG;CAC5B,IAAI,WAAW,QACb,OAAO;CAET,MAAM,UAAkC;EACtC,QAAQ;EACR,wBAAwB;EACxB,cAAc;CAChB;CACA,IAAI,UAAU,UAAa,MAAM,SAAS,GACxC,QAAQ,gBAAgB,UAAU;CAEpC,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,UAAU,KAAK,EAAE,QAAQ,CAAC;CAC7C,SAAS,OAAO;EACd,MAAM,IAAI,cACR,kBACA,mCACA,qHACA,EAAE,OAAO,MAAM,CACjB;CACF;CACA,IAAI,SAAS,WAAW,OAAO,KAAK,eAAe,MACjD;CAEF,IAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KACjD,MAAM,IAAI,cACR,qBACA,mCACA,qEACF;CAEF,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,cACR,eACA,4BAA4B,OAAO,SAAS,MAAM,EAAE,OAAO,IAAI,IAC/D,6DACF;CAGF,MAAM,QAA0B;EAAE,YADN,SAAS,KAAK;EACF,MAAM,SAAS,QAAQ,IAAI,MAAM;CAAE;CAC3E,MAAM,IAAI,KAAK,KAAK;CACpB,OAAO;AACT;AAEA,SAAS,iBAAiB,MAAyC;CACjE,IAAI,SAAS,MACX;CAEF,MAAM,QAAQ,gCAAgC,KAAK,IAAI;CACvD,IAAI,UAAU,QAAQ,MAAM,OAAO,QACjC;CAEF,OAAO,OAAO,SAAS,MAAM,IAAI,EAAE;AACrC;;;;AC1NA,MAAM,WAAW;AACjB,MAAM,gBAAgB;AAEtB,MAAM,cAAc,EAAE,OAAO;CAC3B,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY;CACxC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS;CACzB,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;AAC/B,CAAC;AAQD,eAAsB,WAAW,SAAmD;CAClF,MAAM,OAAO,QAAQ,WAAW,KAAK;CACrC,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;CAEV,MAAM,MAAM,GAAG,SAAS,GAAG,mBAAmB,IAAI;CAClD,MAAM,QAAQ,QAAQ,yBAAS,IAAI,IAAqB;CAExD,MAAM,OADS,MAAM,IAAI,GACP,KAAM,MAAM,OAAO,KAAK,QAAQ,aAAa,OAAO,KAAK;CAC3E,IAAI,SAAS,QACX,OAAO,CAAC;CAEV,MAAM,QAAQ,YAAY,MAAM,IAAI;CACpC,OAAO,EACL,SAAS,EACP,iBAAiB,KAAK,MAAM,WAAW;EACrC,QAAQ;EACR,KAAK,kCAAkC,KAAK;EAC5C,4BAAW,IAAI,KAAK,EAAC,CAAC,YAAY;CACpC,CAAC,EACH,EACF;AACF;AAEA,eAAe,OACb,KACA,WACA,OAC8B;CAC9B,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,UAAU,KAAK,EAAE,SAAS;GAAE,QAAQ;GAAoB,cAAc;EAAW,EAAE,CAAC;CACvG,SAAS,OAAO;EACd,MAAM,IAAI,cACR,eACA,0CACA,8FACA,EAAE,OAAO,MAAM,CACjB;CACF;CACA,IAAI,SAAS,WAAW,KACtB;CAEF,IAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KACjD,MAAM,IAAI,cACR,kBACA,0CACA,yFACF;CAEF,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,cACR,YACA,mCAAmC,OAAO,SAAS,MAAM,EAAE,OAAO,IAAI,IACtE,+DACF;CAEF,MAAM,OAAgB,MAAM,SAAS,KAAK;CAC1C,MAAM,IAAI,KAAK,IAAI;CACnB,OAAO;AACT;;;;;;;;;;;AAYA,eAAsB,iBACpB,MACA,YAA0B,OACI;CAC9B,MAAM,UAAU,KAAK,KAAK;CAC1B,IAAI,QAAQ,WAAW,GACrB,OAAO;CAET,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,UAAU,GAAG,cAAc,GAAG,mBAAmB,OAAO,KAAK;GAC5E,QAAQ;GACR,SAAS,EAAE,QAAQ,mBAAmB;EACxC,CAAC;CACH,QAAQ;EACN;CACF;CACA,IAAI,SAAS,WAAW,KACtB,OAAO;CAET,OAAO,SAAS,KAAK,OAAO;AAC9B;;;;AC/GA,MAAM,YAAY,EAAE,OAAO;CACzB,SAAS,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC9B,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;CAC1B,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;CACtE,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;AACvF,CAAC;AAED,eAAsB,mBACpB,KACA,cAAc,gBACS;CACvB,MAAM,OAAO,KAAK,KAAK,WAAW;CAClC,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,MAAM,MAAM;CACnC,QAAQ;EACN,OAAO,CAAC;CACV;CACA,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,GAAG;CACzB,QAAQ;EACN,OAAO,CAAC;CACV;CACA,MAAM,MAAM,UAAU,UAAU,MAAM;CACtC,IAAI,CAAC,IAAI,SACP,OAAO,CAAC;CAEV,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CAIzC,MAAM,UAAU,IAAI,KAAK,YAAY,OAAO,SAAY,IAAI,KAAK;CACjE,MAAM,UAA0B,EAC9B,MAAM,KAAKC,aAAW,WAAW,iBAAiB,GAAG,CAAC,GAAG;EACvD,QAAQ;EACR,KAAK,YAAY,SAAY,GAAG,YAAY,mBAAmB,GAAG,YAAY;EAC9E;CACF,CAAC,EACH;CACA,IAAI,IAAI,KAAK,gBAAgB,UAAa,IAAI,KAAK,YAAY,SAAS,GACtE,QAAQ,UAAU,KAAK,WAAW,IAAI,KAAK,WAAW,GAAG;EACvD,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC;CAEH,MAAM,MAAM,IAAI,KAAK,YAAYC,gBAAc,IAAI,KAAK,UAAU;CAClE,IAAI,QAAQ,QACV,QAAQ,MAAM,KAAK,KAAK;EACtB,QAAQ;EACR,KAAK,IAAI,KAAK,aAAa,SAAY,GAAG,YAAY,aAAa,GAAG,YAAY;EAClF;CACF,CAAC;CAEH,MAAM,OAAO,SAAS,IAAI,KAAK,UAAU;CACzC,IAAI,SAAS,QACX,QAAQ,OAAO,KAAK,MAAM;EACxB,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC;CAIH,IAAI,IAAI,KAAK,SAAS,UAAa,IAAI,KAAK,YAAY,MACtD,QAAQ,aAAa,KAAK,IAAI,KAAK,MAAM;EACvC,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC;CAIH,IAAI,IAAI,KAAK,QAAQ,UAAa,IAAI,KAAK,YAAY,MACrD,QAAQ,MAAM,KAAK,MAAM;EACvB,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC;CAEH,IAAI,IAAI,KAAK,YAAY,QACvB,QAAQ,UAAU,KAAK,IAAI,KAAK,SAAS;EACvC,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC;CAGH,MAAM,MAAoB,EAAE,QAAQ;CACpC,IAAI,IAAI,KAAK,YAAY,QACvB,IAAI,UAAU,EACZ,SAAS,KAAK,IAAI,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG;EAChD,QAAQ;EACR,KAAK,GAAG,YAAY;EACpB;CACF,CAAC,EACH;CAEF,OAAO;AACT;AAEA,SAASD,aAAW,MAAsB;CACxC,MAAM,QAAQ,KAAK,MAAM,GAAG;CAC5B,OAAO,MAAM,MAAM,SAAS,MAAM;AACpC;AAEA,SAAS,iBAAiB,KAAqB;CAC7C,MAAM,QAAQ,IAAI,MAAM,OAAO,CAAC,CAAC,QAAQ,SAAS,KAAK,SAAS,CAAC;CACjE,OAAO,MAAM,MAAM,SAAS,MAAM;AACpC;AAEA,SAASC,gBAAc,YAAyE;CAC9F,IAAI,OAAO,eAAe,UACxB,OAAOC,kBAAgB,UAAU;CAEnC,IAAI,YAAY,QAAQ,QACtB,OAAOA,kBAAgB,WAAW,GAAG;AAGzC;AAEA,SAAS,SAAS,YAAyE;CACzF,MAAM,MAAMD,gBAAc,UAAU;CACpC,IAAI,QAAQ,QACV;CAGF,OADc,iCAAiC,KAAK,IAAI,QAAQ,UAAU,EAAE,CACjE,CAAC,GAAG;AACjB;AAMA,MAAM,YAAY;AAElB,SAASC,kBAAgB,KAAqB;CAC5C,MAAM,YAAY,UAAU,KAAK,GAAG;CACpC,IAAI,YAAY,OAAO,QACrB,OAAO,sBAAsB,UAAU,EAAE,CAAC,QAAQ,UAAU,EAAE;CAEhE,MAAM,MAAM,qBAAqB,KAAK,GAAG;CACzC,IAAI,QAAQ,QAAQ,IAAI,OAAO,UAAa,IAAI,OAAO,QACrD,OAAO,WAAW,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,QAAQ,UAAU,EAAE;CAEzD,OAAO,IAAI,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,UAAU,EAAE;AACvD;;;;AC/HA,eAAsB,aAAa,SAAyC;CAC1E,MAAM,MAAM,MAAM,mBAAmB,QAAQ,KAAK,QAAQ,eAAe,cAAc;CACvF,MAAM,MAAM,QAAQ,MAAM,SAAS,YAAY,QAAQ,MAAM,MAAM;CACnE,MAAM,cAAc,QAAQ,MAAM,SAAS,YAAY,QAAQ,MAAM,cAAc;CACnF,MAAM,WAAmD,CAAC;CAC1D,IAAI,QAAQ,QACV,SAAS,MAAM;CAEjB,IAAI,gBAAgB,QAClB,SAAS,cAAc;CAEzB,MAAM,MAAM,MAAM,WAAW,QAAQ,KAAK,QAAQ;CAClD,MAAM,UACJ,IAAI,SAAS,SAAS,SACtB,IAAI,SAAS,SAAS,UACrB,QAAQ,SAAY,SAAY,eAAe,GAAG;CACrD,MAAM,SAAS,MAAM,iBAAiB,QAAQ,GAAG;CACjD,MAAM,YAAY,MAAM,qBACtB,QAAQ,KACR,SACA,QAAQ,iBAAiB,gBACzB,QAAQ,WACV;CACA,MAAM,SAAS,MAAM,cAAc,QAAQ,GAAG;CAC9C,MAAM,UACJ,QAAQ,YAAY,UAAa,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,SAAS,IAClF,MAAM,yBAAyB,QAAQ,KAAK,QAAQ,OAAO,IAC3D,CAAC;CAKP,MAAM,eACJ,IAAI,SAAS,eAAe,SAGxB,MAAM,2BACJ,QAAQ,KACR,QAAQ,gBAAgB,OACpB,CAAC,IACD,EAAE,QAAQ,OAAO,SAAS,iBAAiB,MAAM,QAAQ,aAAa,KAAK,EAAE,CACnF,IACA,CAAC;CAKP,MAAM,YAA0B,CAAC;CACjC,KAAK,MAAM,QAAQ,CAAC,YAAY,aAAa,GAAY;EACvD,MAAM,OAAO,QAAQ,KAAK,EAAE,KAAK;EACjC,IAAI,SAAS,UAAa,KAAK,SAAS,GACtC,UAAU,UAAU;GAClB,GAAG,UAAU;IACZ,OAAO,KAAK,MAAM;IACjB,QAAQ;IACR,KAAK,KAAK,KAAK,cAAc;IAC7B,4BAAW,IAAI,KAAK,EAAC,CAAC,YAAY;GACpC,CAAC;EACH;CAEJ;CAaA,MAAM,QAAwB;EAAC;EAAW;EAAK;EAAc;EAAQ;EAAK;EAAS;EAAW;CAAM;CAEpG,IAAI,QAAQ,MAAM,SAAS,SACzB,MAAM,KAAK,MAAM,iBAAiB,QAAQ,KAAK,QAAQ,aAAa,sBAAsB,CAAC;CAG7F,IAAI,QAAQ,gBAAgB,MAAM;EAChC,MAAM,OAAO,IAAI,SAAS,MAAM,SAAS,iBAAiB,KAAK,MAAM;EACrE,IAAI,SAAS,QAAW;GACtB,MAAM,aAAkD,EAAE,KAAK;GAC/D,MAAM,YAAY,IAAI,SAAS,KAAK,SAAS;GAC7C,IAAI,cAAc,QAChB,WAAW,MAAM;GAEnB,IAAI,QAAQ,gBAAgB,QAC1B,WAAW,QAAQ,QAAQ;GAE7B,IAAI,QAAQ,cAAc,QACxB,WAAW,YAAY,QAAQ;GAEjC,MAAM,SAAS,MAAM,cAAc,UAAU;GAC7C,MAAM,wBAAsC,CAAC;GAC7C,IAAI,OAAO,YAAY,QACrB,sBAAsB,UAAU,OAAO;GAEzC,IAAI,OAAO,YAAY,QACrB,sBAAsB,UAAU,OAAO;GAEzC,MAAM,KAAK,qBAAqB;GAChC,MAAM,gBAAgB,WAAW,KAAK;GACtC,IACE,QAAQ,MAAM,SAAS,cACtB,cAAc,SAAS,SAAS,UAAU,OAAO,KAClD,OAAO,SAAS,aAAa,UAC7B,OAAO,QAAQ,SAAS,SAAS,GAEjC,MAAM,KAAK,EAAE,SAAS,EAAE,UAAU,OAAO,QAAQ,SAAS,EAAE,CAAC;EAEjE;EACA,MAAM,aAAa,IAAI,SAAS,YAAY;EAC5C,IAAI,eAAe,QAAW;GAC5B,MAAM,UAA4C,EAAE,WAAW;GAC/D,IAAI,QAAQ,cAAc,QACxB,QAAQ,YAAY,QAAQ;GAE9B,MAAM,KAAK,MAAM,WAAW,OAAO,CAAC;EACtC;CACF;CAEA,MAAM,QAAQ,WAAW,KAAK;CAC9B,IAAI,QAAQ,MAAM,SAAS,aAAa,MAAM,YAAY,QACxD,MAAM,IAAI,cACR,yBACA,oCACA,kFACF;CAEF,OAAO;AACT;AAEA,eAAe,qBACb,KACA,SACA,eACA,aACuB;CACvB,MAAM,QAAQ,CAAC,aAAa;CAC5B,IAAI,gBAAgB,QAAW;EAC7B,MAAM,UAAU,KAAK,QAAQ,WAAW,GAAG,cAAc;EACzD,IAAI,CAAC,MAAM,SAAS,OAAO,GACzB,MAAM,KAAK,OAAO;CAEtB;CAEA,MAAM,SAAQ,MADU,QAAQ,IAAI,MAAM,KAAK,SAAS,iBAAiB,KAAK,SAAS,IAAI,CAAC,CAAC,EACtE,CAAC,MAAM,UAAU,kBAAkB,KAAK,CAAC;CAChE,IAAI,UAAU,QACZ,OAAO;CAMT,MAAM,aAAa,MAAM,oBAAoB,GAAG;CAIhD,QAAO,MAHqB,QAAQ,IAClC,WAAW,KAAK,cAAc,iBAAiB,KAAK,SAAS,SAAS,CAAC,CACzE,EACoB,CAAC,MAAM,UAAU,kBAAkB,KAAK,CAAC,KAAK,CAAC;AACrE;;;;;;;;AASA,eAAe,2BACb,KACA,UAAuE,CAAC,GACjD;CACvB,MAAM,QAAQ,MAAM,mBAAmB,GAAG;CAE1C,MAAM,SAAQ,MADU,QAAQ,IAAI,MAAM,KAAK,SAAS,mBAAmB,KAAK,IAAI,CAAC,CAAC,EAC/D,CACpB,KAAK,OAAO,WAAW;EACtB,MAAM,MAAM,SAAS,YAAY;EACjC,KAAK,MAAM,SAAS;EACpB,MAAM,MAAM,UAAU;CACxB,EAAE,CAAC,CACF,QACE,UACC,MAAM,SAAS,MACnB;CACF,MAAM,OAAO,MAAM,WAAW,IAAI,MAAM,KAAK;CAC7C,IAAI,SAAS,QACX,OAAO,CAAC;CAEV,IAAI,QAAQ,WAAW,UAAc,MAAM,QAAQ,OAAO,KAAK,IAAI,MAAO,OAGxE,OAAO,CAAC;CAEV,MAAM,UAA0B,EAC9B,YAAY,KAAK,KAAK,MAAM;EAC1B,QAAQ;EACR,KAAK,GAAG,KAAK,KAAK;EAClB,4BAAW,IAAI,KAAK,EAAC,CAAC,YAAY;CACpC,CAAC,EACH;CACA,IAAI,KAAK,QAAQ,QACf,QAAQ,MAAM,KAAK;CAErB,OAAO,EAAE,QAAQ;AACnB;AAEA,eAAe,mBAAmB,KAAgC;CAChE,QAAQ,MAAM,oBAAoB,GAAG,EAAC,CAAE,KAAK,SAC3C,KAAK,QAAQ,kBAAkB,cAAc,CAC/C;AACF;AAEA,eAAe,oBAAoB,KAAgC;CAejE,QAAO,MAbgB,QAAQ,IAC7B,CAFa,YAAY,MAErB,CAAC,CAAC,IAAI,OAAO,SAAS;EACxB,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,QAAQ,KAAK,KAAK,IAAI,GAAG,EAAE,eAAe,KAAK,CAAC;EAClE,QAAQ;GACN,OAAO,CAAC;EACV;EACA,OAAO,QACJ,QAAQ,UAAU,MAAM,YAAY,CAAC,CAAC,CACtC,KAAK,UAAU,KAAK,MAAM,MAAM,MAAM,cAAc,CAAC;CAC1D,CAAC,CACH,EACe,CAAC,KAAK,CAAC,CAAC,SAAS;AAClC;AAEA,SAAS,kBAAkB,OAA8B;CACvD,MAAM,UAAU,MAAM;CACtB,IAAI,YAAY,QACd,OAAO;CAET,QACG,QAAQ,UAAU,UAAU,KAAK,MACjC,QAAQ,OAAO,UAAU,KAAK,MAC9B,QAAQ,UAAU,UAAU,KAAK;AAEtC;AAEA,SAAS,iBAAiB,KAAmB,QAA0C;CACrF,OAAO,IAAI,SAAS,MAAM,SAAS,IAAI,SAAS,KAAK,SAAS,OAAO,SAAS,KAAK;AACrF;;;;AClQA,MAAa,oBAAoB;;AAGjC,MAAa,WAAW;;AAGxB,eAAsB,uBAAuB,MAA4C;CACvF,MAAM,WAAW,IAAI,SAAS;CAC9B,MAAM,SAAS,aAAa;EAC1B,MAAM;EACN,MAAM;EACN,SAAS;CACX,CAAC;CACD,OAAO,IAAI,eAAe,QAAQ;AACpC;AAeA,SAAgB,WAAW,MAA6B;CACtD,MAAM,qBAAK,IAAI,IAAY;CAC3B,MAAM,QAAQ,YAAiC;EAC7C,KAAK,MAAM,OAAO,QAAQ,MACxB,GAAG,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;EAE1B,KAAK,MAAM,SAAS,QAAQ,UAC1B,KAAK,KAAK;CAEd;CACA,KAAK,IAAI;CACT,OAAO,GAAG;AACZ;AAEA,SAAgB,eAA2B;CACzC,OAAO,UAAU;EACf,OAAO;GACL,OAAO;GACP,QAAQ;GACR,SAAS;GACT,eAAe;GACf,gBAAgB;GAChB,SAAS;GACT,iBAAiB;EACnB;EACA,UAAU,CACRC,KAAS,YAAY;GACnB,YAAY;GACZ,UAAU;GACV,YAAY;GACZ,OAAO;EACT,CAAC,GACDA,KAAS,4CAA4C;GACnD,YAAY;GACZ,UAAU;GACV,YAAY;GACZ,OAAO;EACT,CAAC,CACH;CACF,CAAC;AACH;AAEA,IAAM,iBAAN,MAAgD;CACjB;CAA7B,YAAY,AAAiB,UAAoB;EAApB;CAAqB;CAElD,MAAM,QAAQ,SAAuC;EACnD,MAAM,SAAS,MAAMC,QAAc,mBAAmB,OAAO,CAAC;EAC9D,OAAO,KAAK,OAAO,MAAM,OAAO,GAAG;CACrC;CAEA,MAAM,OAAO,MAAkB,MAA0C;EACvE,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,SAA8D,EAClE,KAAK,KAAK,OAAO,OAAO,IAC1B;EACA,IAAI,KAAK,WAAW,QAClB,OAAO,SAAS,KAAK;EAEvB,MAAM,SAAS,MAAM,iBAAiB,KAAK,UAAU,OAAO,MAAM,MAAM,MAAM;EAC9E,OAAO,WAAW,KAAK,MAAM;CAC/B;CAEA,MAAM,QAAQ,MAAkB,MAA+C;EAC7E,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,WAAW,MAAM,KAAK,SAAS,QAAQ,OAAO,MAAM,YAAY,IAAI,CAAC;EAC3E,OAAO;GACL,OAAO,WAAW,QAAQ;GAC1B,OAAO,SAAS;GAChB,QAAQ,SAAS;EACnB;CACF;CAEA,MAAM,YAAY,OAAe,MAAkD;EACjF,MAAM,WAAW,MAAM,KAAK,SAAS,QAAQ,OAAO,gBAAgB,OAAO,IAAI,CAAC,CAAC;EACjF,OAAO;GACL,OAAO,WAAW,QAAQ;GAC1B,OAAO,SAAS;GAChB,QAAQ,SAAS;EACnB;CACF;AACF;AAEA,SAAS,iBACP,UACA,MACA,MACA,QACiB;CACjB,MAAM,QAAQ,KAAK;CACnB,MAAM,SAAS,KAAK;CACpB,MAAM,MAAM,OAAO;CACnB,MAAM,SAAS,OAAO;CACtB,IAAI,KAAK,WAAW,QAAQ;EAC1B,IAAI,WAAW,QACb,OAAO,SAAS,OAAO,MAAM;GAAE;GAAO;GAAQ,QAAQ;GAAQ;GAAK;EAAO,CAAC;EAE7E,OAAO,SAAS,OAAO,MAAM;GAAE;GAAO;GAAQ,QAAQ;GAAQ;EAAI,CAAC;CACrE;CACA,IAAI,KAAK,WAAW,QAAQ;EAC1B,IAAI,WAAW,QACb,OAAO,SAAS,OAAO,MAAM;GAAE;GAAO;GAAQ,QAAQ;GAAQ;GAAK;EAAO,CAAC;EAE7E,OAAO,SAAS,OAAO,MAAM;GAAE;GAAO;GAAQ,QAAQ;GAAQ;EAAI,CAAC;CACrE;CACA,IAAI,WAAW,QACb,OAAO,SAAS,OAAO,MAAM;EAAE;EAAO;EAAQ,QAAQ;EAAO;EAAK;CAAO,CAAC;CAE5E,OAAO,SAAS,OAAO,MAAM;EAAE;EAAO;EAAQ,QAAQ;EAAO;CAAI,CAAC;AACpE;AAEA,SAAS,YAAY,MAA4D;CAC/E,MAAM,MAA2C,CAAC;CAClD,IAAI,MAAM,UAAU,QAClB,IAAI,QAAQ,KAAK;CAEnB,IAAI,MAAM,WAAW,QACnB,IAAI,SAAS,KAAK;CAEpB,OAAO;AACT;AAEA,SAAS,gBAAgB,OAAe,MAAsC;CAC5E,MAAM,QAOF;EACF,YAAY,KAAK;EACjB,UAAU,KAAK;EACf,YAAY,KAAK;EACjB,YAAY,KAAK,cAAc;EAC/B,UAAU,KAAK;CACjB;CACA,IAAI,KAAK,eAAe,QACtB,MAAM,aAAa,KAAK;CAE1B,OAAOD,KAAS,OAAO,KAAK;AAC9B;AAEA,SAAS,OAAO,MAAwB;CACtC,OAAO,OAAO,IAAI,CAAC,CAAC;AACtB;AAIA,SAAS,KAAK,MAAY,MAAgB,CAAC,GAAe;CAExD,OAAO;EADwB,YAAY;EAAM;EAAM;CAC3C;AACd;AAEA,SAAS,OAAO,MAAgC;CAC9C,IAAI,SAAS,IAAI,GACf,OAAO;CAET,IAAI,aAAa,IAAI,GACnB,OAAO;EAAE,YAAY;EAAM;EAAM,KAAK,CAAC;CAAE;CAE3C,MAAM,IAAI,cACR,uBACA,mEACA,oFACF;AACF;AAEA,SAAS,SAAS,MAAwC;CACxD,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,gBAAgB;AACtE;AAEA,SAAS,aAAa,MAAgC;CACpD,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU;AAChE;AAEA,SAAS,mBAAmB,SAAyE;CACnG,IAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,EAAE,UAAU,UACjE,MAAM,IAAI,cACR,sBACA,uDACA,6CACF;CAEF,MAAM,SAAS;CAIf,OAAO;EAAE,MAHI,UAAU,SAAS,OAAO,OAAO;EAG/B,OAFD,WAAW,SAAS,OAAO,QAAQ;EAE3B,KADV,SAAS,UAAU,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;CACnD;AAC5B;;;;ACrNA,eAAsB,uBAAiD;CACrE,MAAM,WAAW,KAAK,mBAAmB,GAAG,QAAQ;CACpD,MAAM,OAAO,MAAM,SAAS,QAAQ;CACpC,OAAO,uBAAuB,IAAI;AACpC;AAEA,SAAgB,mBAAmB,OAAO,YAAY,KAAa;CACjE,IAAI,MAAM,QAAQ,cAAc,IAAI,CAAC;CACrC,SAAS;EACP,IAAI,WAAW,KAAK,KAAK,cAAc,CAAC,KAAK,WAAW,KAAK,uCAAa,CAAC,GACzE,OAAO;EAET,MAAM,SAAS,QAAQ,GAAG;EAC1B,IAAI,WAAW,KACb,MAAM,IAAI,cACR,uBACA,gCAAgC,SAAS,IACzC,yFACF;EAEF,MAAM;CACR;AACF;;;;ACzCA,SAAgB,eAAe,OAA2B;CACxD,MAAM,0BAAU,IAAI,IAAY;CAChC,MAAM,SAAS,UAAyB;EACtC,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;GACvD,UAAU,SAAS,KAAK;GACxB;EACF;EACA,IAAI,OAAO,UAAU,UAAU;GAC7B,KAAK,MAAM,SAAS,MAAM,MAAM,gBAAgB,KAAK,CAAC,GACpD,QAAQ,IAAI,KAAK;GAEnB;EACF;EACA,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,KAAK,MAAM,QAAQ,OACjB,MAAM,IAAI;GAEZ;EACF;EACA,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM;GAC/C,IAAI,WAAW,SAAS,gBAAgB,OAAO;IAC7C,MAAM,MAAM,KAAK;IACjB;GACF;GACA,KAAK,MAAM,UAAU,OAAO,OAAO,KAAK,GACtC,MAAM,MAAM;EAEhB;CACF;CACA,MAAM,KAAK;CACX,OAAO;AACT;AAEA,SAAgB,gBAAgB,MAAc,SAAgC;CAC5E,MAAM,QAAkB,CAAC;CACzB,MAAM,iBAAiB,KAAK,QAAQ,wBAAwB,UAAU;EACpE,MAAM,UAAU,MAAM,WAAW,KAAK,EAAE;EACxC,IAAI,CAAC,QAAQ,IAAI,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,GAC7C,MAAM,KAAK,KAAK;EAElB,OAAO;CACT,CAAC;CACD,KAAK,MAAM,SAAS,eAAe,MAAM,gBAAgB,KAAK,CAAC,GAC7D,IAAI,CAAC,QAAQ,IAAI,KAAK,GACpB,MAAM,KAAK,KAAK;CAGpB,OAAO;AACT;AAEA,SAAgB,UAAU,MAAY,OAA4E;CAChH,MAAM,UAAU,eAAe,KAAK;CACpC,MAAM,QAAiC;EACrC,CAAC,YAAY,KAAK,QAAQ;EAC1B,CAAC,eAAe,KAAK,WAAW;EAChC,CAAC,OAAO,KAAK,GAAG;CAClB;CACA,IAAI,KAAK,kBAAkB,QACzB,MAAM,KAAK,CAAC,iBAAiB,KAAK,aAAa,CAAC;CAElD,KAAK,WAAW,SAAS,MAAM,UAAU;EACvC,MAAM,KAAK,CAAC,cAAc,OAAO,KAAK,EAAE,IAAI,IAAI,CAAC;CACnD,CAAC;CACD,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO;EAChC,MAAM,SAAS,gBAAgB,MAAM,OAAO;EAC5C,IAAI,OAAO,SAAS,GAClB,OAAO;GAAE,IAAI;GAAO;GAAM;EAAO;CAErC;CACA,OAAO,EAAE,IAAI,KAAK;AACpB;AAEA,SAAS,UAAU,SAAsB,OAAqB;CAC5D,QAAQ,IAAI,OAAO,KAAK,CAAC;CACzB,IAAI,OAAO,UAAU,KAAK,GACxB,QAAQ,IAAI,MAAM,eAAe,OAAO,CAAC;AAE7C;;;;ACzEA,MAAM,gBAAgB,EAAE,OAAO;CAC7B,UAAU,EAAE,OAAO;CACnB,aAAa,EAAE,OAAO;CACtB,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,KAAkB;CAClD,KAAK,EAAE,OAAO;AAChB,CAAC;AAUD,eAAsB,QACpB,OACA,SACA,WAAW,kBAAkB,KAAK,GACwC;CAC1E,MAAM,UAAU,YAAY,KAAK;CACjC,IAAI;CACJ,MAAM,UAAU,KAAK,IAAI,GAAG,QAAQ,UAAU;CAC9C,KAAK,IAAI,UAAU,GAAG,WAAW,SAAS,WAAW,GAAG;EACtD,IAAI;EACJ,IAAI;GAGF,MAAM,MAAM,MAAM,YAAY,SAAS,OAAO;GAC9C,SAAS,cAAc,MAAM,KAAK,MAAM,GAAG,CAAC;EAC9C,SAAS,OAAO;GACd,YAAY,iBAAiB,QAAQ,MAAM,UAAU;GACrD;EACF;EACA,MAAM,WAAW,mBAAmB,QAAQ,KAAK;EACjD,MAAM,SAAe;GACnB,UAAU,WAAW,SAAS,QAAQ,CAAC,CAAC,MAAM,GAAG,YAAY,QAAQ;GACrE,aAAa,WAAW,SAAS,WAAW,CAAC,CAAC,MAAM,GAAG,YAAY,WAAW;GAC9E,YAAY,SAAS,WAAW,KAAK,SAAS,WAAW,IAAI,CAAC,CAAC,MAAM,GAAG,YAAY,SAAS,CAAC;GAC9F,KAAK,WAAW,SAAS,GAAG,CAAC,CAAC,MAAM,GAAG,YAAY,GAAG;EACxD;EACA,MAAM,UAAU,UAAU,QAAQ,KAAK;EACvC,IAAI,CAAC,QAAQ,IAAI;GACf,YAAY,yBAAyB,QAAQ,KAAK,IAAI,QAAQ,OAAO,KAAK,IAAI;GAC9E;EACF;EACA,OAAO;GAAE,MAAM;GAAQ,MAAM;EAAM;CACrC;CACA,OAAO;EACL,MAAM;EACN,MAAM;EACN,SAAS,aAAa;CACxB;AACF;AAEA,SAAS,YAAY,OAAuC;CAC1D,OAAO;EACL,SAAS;GACP,MAAM,MAAM,QAAQ,KAAK;GACzB,SAAS,MAAM,QAAQ,SAAS;GAChC,YAAY,MAAM,QAAQ,YAAY;GACtC,KAAK,MAAM,QAAQ,KAAK;EAC1B;EACA,SAAS,MAAM,YAAY,SACvB,SACA;GACE,SAAS;GACT,UAAU,MAAM,QAAQ,SAAS,KAAK,SAAS,KAAK,KAAK;GACzD,OAAO,MAAM,QAAQ,MAAM,KAAK,SAAS,KAAK,KAAK;GACnD,UAAU,MAAM,QAAQ,SAAS,KAAK,SAAS,KAAK,KAAK;EAC3D;EACJ,SAAS;GACP,OAAO,MAAM,SAAS,UAAU,SAAY,SAAY;GACxD,iBAAiB,MAAM,SAAS,oBAAoB,SAAY,SAAY;GAC5E,kBAAkB,MAAM,SAAS,qBAAqB,SAAY,SAAY;EAChF;CACF;AACF;AAEA,SAAS,mBAAmB,MAAqC,OAA6C;CAC5G,MAAM,MAA8B;EAClC,aAAa,MAAM,SAAS,QAAQ,SAAS;EAC7C,WAAW,MAAM,SAAS,UAAU,SAAY,KAAK,YAAY,MAAM,QAAQ,MAAM,KAAK;EAC1F,qBACE,MAAM,SAAS,oBAAoB,SAAY,KAAK,YAAY,MAAM,QAAQ,gBAAgB,KAAK;EACrG,sBACE,MAAM,SAAS,qBAAqB,SAAY,KAAK,YAAY,MAAM,QAAQ,iBAAiB,KAAK;CACzG;CACA,MAAM,UAAU,SAAyB;EACvC,IAAI,MAAM;EACV,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,GAAG,GAC7C,MAAM,IAAI,WAAW,OAAO,KAAK;EAEnC,OAAO;CACT;CACA,OAAO;EACL,UAAU,OAAO,KAAK,QAAQ;EAC9B,aAAa,OAAO,KAAK,WAAW;EACpC,YAAY,KAAK,WAAW,IAAI,MAAM;EACtC,KAAK,OAAO,KAAK,GAAG;CACtB;AACF;AAEA,SAAS,WAAW,MAAsB;CACxC,OAAO,KAAK,WAAW,KAAU,GAAG,CAAC,CAAC,WAAW,KAAU,GAAG,CAAC,CAAC,WAAW,KAAK,GAAG;AACrF;AAEA,SAAS,YAAY,OAAuB;CAC1C,OAAO,MAAM,eAAe,OAAO;AACrC;AAEA,eAAe,YAAY,OAAgC,SAA0C;CACnG,MAAM,QAAQ,QAAQ,WAAW,4BAA2B,CAAE,QAAQ,OAAO,EAAE;CAE/E,MAAM,WAAW,OADC,QAAQ,aAAa,MACP,CAAC,GAAG,KAAK,oBAAoB;EAC3D,QAAQ;EACR,SAAS;GACP,eAAe,UAAU,QAAQ;GACjC,gBAAgB;EAClB;EACA,MAAM,KAAK,UAAU;GACnB,OAAO,QAAQ;GACf,iBAAiB,EAAE,MAAM,cAAc;GACvC,UAAU,CACR;IACE,MAAM;IACN,SACE;GACJ,GACA;IAAE,MAAM;IAAQ,SAAS,KAAK,UAAU,KAAK;GAAE,CACjD;EACF,CAAC;CACH,CAAC;CACD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,cACR,iBACA,8BAA8B,OAAO,SAAS,MAAM,EAAE,IACtD,oEACF;CAEF,MAAM,OAAgB,MAAM,SAAS,KAAK;CAM1C,MAAM,QALU,EACb,OAAO,EACN,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAClF,CAAC,CAAC,CACD,MAAM,IACW,CAAC,CAAC,QAAQ;CAC9B,IAAI,UAAU,QACZ,MAAM,IAAI,cAAc,kBAAkB,4BAA4B,+BAA+B;CAEvG,OAAO,MAAM,QAAQ;AACvB;;;;AClIA,SAAgB,cAAc,OAKjB;CACX,OAAO;EACL,UAAU,MAAM;EAChB,OAAO,MAAM;EACb,aAAa,MAAM,OAAO;EAC1B,OAAO;GACL,MAAM,MAAM,MAAM;GAClB,OAAO,MAAM,MAAM;GACnB,QAAQ;EACV;EACA,MAAM,EAAE,MAAM,MAAM,OAAO,SAAS;EACpC,OAAO,MAAM,OAAO,MAAM,KAAK,UAAU;GACvC,MAAM,KAAK;GACX,UAAU,KAAK;GACf,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,QAAQ,KAAK;GACb,OAAO,KAAK,MAAM;GAClB,QAAQ,KAAK;EACf,EAAE;EACF,OAAO,aAAa,MAAM,OAAO,KAAK;EACtC,UAAU,MAAM,OAAO;EACvB,UAAU,MAAM,OAAO;EACvB,SAAS,MAAM,OAAO;CACxB;AACF;AAEA,SAAgB,aACd,OACoF;CACpF,MAAM,MAA0F,CAAC;CACjG,MAAM,QAAQ,QAAgB,UAAyB;EACrD,IAAI,OAAO,KAAK,GAAG;GACjB,IAAI,UAAU;IACZ,OAAO,MAAM;IACb,QAAQ,MAAM,WAAW;IACzB,KAAK,MAAM,WAAW;IACtB,WAAW,MAAM,WAAW;GAC9B;GACA;EACF;EACA,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,MAAM,SAAS,MAAM,UAAU;IAC7B,KAAK,GAAG,OAAO,GAAG,OAAO,KAAK,EAAE,IAAI,IAAI;GAC1C,CAAC;GACD;EACF;EACA,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,KAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,KAAK,GAC9C,KAAK,OAAO,WAAW,IAAI,MAAM,GAAG,OAAO,GAAG,OAAO,MAAM;CAGjE;CACA,KAAK,WAAW,MAAM,OAAO;CAC7B,IAAI,MAAM,UAAU,QAClB,KAAK,SAAS,MAAM,KAAK;CAE3B,IAAI,MAAM,YAAY,QACpB,KAAK,WAAW,MAAM,OAAO;CAE/B,IAAI,MAAM,YAAY,QACpB,KAAK,WAAW,MAAM,OAAO;CAE/B,IAAI,MAAM,UAAU,QAClB,KAAK,SAAS,MAAM,KAAK;CAE3B,IAAI,MAAM,cAAc,QACtB,KAAK,aAAa,MAAM,SAAS;CAEnC,OAAO;AACT;AAEA,SAAS,OACP,OAC6F;CAC7F,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,IAAI,EAAE,WAAW,UAAU,EAAE,gBAAgB,QAC3C,OAAO;CAET,MAAM,aAAa,MAAM;CACzB,OACE,OAAO,eAAe,YACtB,eAAe,QACf,YAAY,cACZ,SAAS,cACT,eAAe;AAEnB;;;;ACnHA,eAAsB,UAAU,OAOiB;CAC/C,MAAM,MAAM,KAAK,MAAM,QAAQ,MAAM,OAAO;CAC5C,MAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;CACpC,MAAM,QAAQ,IAAI,MAAM,OAAO,MAAM,KAAK,SAAS,UAAU,KAAK,KAAK,KAAK,QAAQ,GAAG,KAAK,KAAK,CAAC,CAAC;CACnG,MAAM,WAAW,cAAc;EAC7B,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,OAAO,MAAM;EACb,iBAAiB,MAAM;CACzB,CAAC;CACD,MAAM,UAAU,KAAK,KAAK,eAAe,GAAG,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,KAAK,MAAM;CAC5F,OAAO;EAAE;EAAK;CAAS;AACzB;AAEA,SAAgB,iBAAiB,KAAa,YAA4B;CACxE,OAAO,WAAW,UAAU,IAAI,aAAa,KAAK,KAAK,UAAU;AACnE;AAEA,SAAgB,QAAQ,OAAsB,cAAc,IAAY;CACtE,IAAI,MAAM,SAAS,WACjB,OAAO,MAAM;CAEf,IAAI,MAAM,SAAS,aACjB,OAAO,aAAa,MAAM,OAAO,GAAG,OAAO,MAAM,SAAS;CAE5D,MAAM,MAAM,YAAY,MAAM,GAAG,EAAE;CACnC,OAAO,sBAAsB,KAAK,GAAG,IAAI,SAAS,QAAQ;AAC5D;;;;ACjCA,MAAME,kBAAgB,UAAU,QAAQ;AAQxC,eAAsB,oBAAoB,SAMxB;CAChB,IAAI,QAAQ,MAAM,WAAW,GAC3B;CAEF,MAAM,OAAO,QAAQ,QAAQA;CAC7B,MAAM,OAAO;EAAC;EAAW;EAAU,QAAQ;EAAK,GAAG,QAAQ;EAAO;CAAW;CAC7E,IAAI,QAAQ,SAAS,QACnB,KAAK,KAAK,UAAU,QAAQ,IAAI;CAElC,MAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;CAC7B,IAAI,QAAQ,UAAU,QAAW;EAC/B,IAAI,WAAW,QAAQ;EACvB,IAAI,eAAe,QAAQ;CAC7B;CACA,IAAI;EACF,MAAM,KAAK,MAAM,MAAM,EAAE,IAAI,CAAC;CAChC,SAAS,OAAO;EACd,MAAM,IAAI,cACR,iBACA,6CAA6C,QAAQ,IAAI,IACzD,qFACA,EAAE,OAAO,MAAM,CACjB;CACF;AACF;AAEA,eAAsB,iBAAiB,MAAc,UAAoB,KAA4B;CACnG,MAAM,WAAW,MAAM,GAAG,mBAAmB,UAAU,GAAG,EAAE,KAAK,MAAM;AACzE;AAEA,SAAgB,mBAAmB,UAAoB,KAAqB;CAC1E,MAAM,QAAQ;EACZ;EACA;EACA,eAAe,OAAO,SAAS,MAAM,MAAM,EAAE,gBAAgB,IAAI;EACjE;CACF;CACA,MAAM,OAAO,QAAQ,IAAI;CACzB,MAAM,MAAM,SAAS,MAAM,SAAS,YAAY,SAAS,MAAM,MAAM;CACrE,IAAI,SAAS,UAAa,QAAQ,QAChC,KAAK,MAAM,QAAQ,SAAS,OAAO;EACjC,MAAM,MAAM,sBAAsB,KAAK,qBAAqB,IAAI,GAAG,KAAK;EACxE,MAAM,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,IAAI,EAAE;CAC1C;MACK;EACL,MAAM,KAAK,gCAAgC,eAAe;EAC1D,KAAK,MAAM,QAAQ,SAAS,OAC1B,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,GAAG;EAEnE,MAAM,KAAK,EAAE;CACf;CACA,MAAM,KAAK,aAAa,EAAE;CAC1B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,KAAK,GACtD,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,UAAU,MAAM,KAAK,EAAE,IAAI,MAAM,OAAO,EAAE;CAE7E,IAAI,OAAO,KAAK,SAAS,QAAQ,CAAC,CAAC,SAAS,GAAG;EAC7C,MAAM,KAAK,IAAI,gBAAgB,EAAE;EACjC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,QAAQ,GACzD,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,UAAU,MAAM,KAAK,GAAG;CAE7D;CACA,IAAI,SAAS,SAAS,SAAS,GAAG;EAChC,MAAM,KAAK,IAAI,gBAAgB,EAAE;EACjC,KAAK,MAAM,WAAW,SAAS,UAC7B,MAAM,KAAK,KAAK,QAAQ,SAAS,GAAG,QAAQ,OAAO,GAAG,QAAQ,KAAK,IAAI,QAAQ,QAAQ;CAE3F;CACA,MAAM,KAAK,EAAE;CACb,OAAO,MAAM,KAAK,IAAI;AACxB;;;;AC7DA,SAAgB,eAAe,QAAgB,OAA4B;CACzE,MAAM,UAAkB,EAAE,GAAG,OAAO;CACpC,IAAI,MAAM,YAAY,QACpB,QAAQ,UAAU,aAAa,MAAM,OAAO;CAE9C,IAAI,MAAM,QAAQ,QAChB,QAAQ,YAAY,MAAM;CAE5B,OAAO,YAAY,gBAAgB,OAAO;AAC5C;AAEA,SAAgB,aAAa,MAA0B;CACrD,MAAM,UAAsB,CAAC;CAC7B,KAAK,MAAM,QAAQ,KAAK,MAAM,GAAG,GAAG;EAClC,MAAM,KAAK,KAAK,KAAK;EACrB,IAAI,GAAG,WAAW,GAChB;EAEF,MAAM,QAAQ,WAAW,MAAM,WAAW,WAAW,EAAE;EACvD,IAAI,UAAU,QACZ,MAAM,IAAI,cACR,sBACA,mBAAmB,GAAG,KACtB,oCAAoC,WAAW,KAAK,IAAI,EAAE,EAC5D;EAEF,QAAQ,KAAK,KAAK;CACpB;CACA,OAAO;AACT;AAEA,SAAgB,cAAc,MAA0B,YAAqD;CAC3G,IAAI,SAAS,QACX,OAAO,CAAC,QAAQ,OAAO;CAEzB,IAAI,SAAS,UAAU,SAAS,SAC9B,OAAO,CAAC,IAAI;CAEd,OAAO,CAAC,UAAU;AACpB;AAEA,eAAsB,YACpB,OACA,QACA,QACA,UAC8E;CAC9E,IAAI,UAAU,OAAO,MAAM,QAAQ,MACjC,OAAO;EAAE,MAAM;EAAU,UAAU;CAAgB;CAErD,MAAM,SAAS,QAAQ,IAAI;CAC3B,IAAI,WAAW,UAAa,OAAO,WAAW,GAC5C,MAAM,IAAI,cACR,oBACA,4DACA,qEACF;CAEF,MAAM,UAAyC;EAC7C;EACA,OAAO,OAAO,KAAK,SAAS;EAC5B,YAAY,OAAO,KAAK,cAAc;CACxC;CACA,IAAI,QAAQ,IAAI,0BAA0B,QACxC,QAAQ,UAAU,QAAQ,IAAI;CAEhC,MAAM,SAAS,MAAM,QAAQ,OAAO,SAAS,QAAQ;CACrD,MAAM,MAA2E;EAC/E,MAAM,OAAO;EACb,UAAU,OAAO;CACnB;CACA,IAAI,OAAO,YAAY,QACrB,IAAI,UAAU,OAAO;CAEvB,OAAO;AACT;AAEA,eAAsB,UAAU,KAAa,OAA8E;CACzH,IAAI,MAAM,SAAS,QACjB;CAEF,MAAM,QAAmD,EACvD,OAAO,MAAM,SAAS,KAAK,MAAM,KAAK,KAAK,EAC7C;CACA,IAAI,MAAM,KAAK,SAAS,QACtB,MAAM,OAAO,MAAM,SAAS,KAAK,MAAM,KAAK,IAAI;CAElD,OAAO;AACT;AAEA,eAAe,SAAS,KAAa,MAAmC;CACtE,MAAM,WAAW,WAAW,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI;CACzD,OAAO,IAAI,WAAW,MAAM,SAAS,QAAQ,CAAC;AAChD;AAEA,SAAgB,sBAA8B;CAC5C,MAAM,MAAe,KAAK,MAAM,aAAa,KAAK,mBAAmB,GAAG,cAAc,GAAG,MAAM,CAAC;CAChG,IAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,aAAa,OAAO,OAAO,IAAI,YAAY,UACxF,OAAO,IAAI;CAEb,OAAO;AACT;AAEA,SAAgB,WAAW,OAKzB;CAEA,MAAM,MAAqC,EAAE,aADzB,MAAM,WAAW,QAAQ,QAAQ,IAAI,iBAAiB,OACjB;CACzD,IAAI,QAAQ,IAAI,iBAAiB,QAC/B,IAAI,cAAc,QAAQ,IAAI;CAEhC,IAAI,MAAM,YAAY,QACpB,IAAI,cAAc,MAAM;CAE1B,IAAI,MAAM,cAAc,QACtB,IAAI,YAAY,MAAM;CAExB,OAAO;AACT;AAEA,eAAsB,WAAW,OAoB9B;CACD,MAAM,cAAc,MAAM,OAAO;CACjC,MAAM,UAAU,MAAM,UAAU;EAC9B,QAAQ,iBACN,MAAM,MAAM,KACZ,MAAM,MAAM,OAAO,MAAM,OAAO,aAAa,kBAC/C;EACA,SAAS,QAAQ,MAAM,OAAO,WAAW;EACzC,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,OAAO,MAAM;EACb,iBAAiB,oBAAoB;CACvC,CAAC;CACD,IAAI,MAAM,MAAM,WAAW,QAAQ,MAAM,MAAM,SAAS,WAAW;EACjE,MAAM,QAAQ,MAAM,OAAO,MAAM,KAAK,SAAS,KAAK,QAAQ,KAAK,KAAK,QAAQ,CAAC;EAC/E,MAAM,aAAwD;GAAE,KAAK,MAAM,MAAM;GAAK;EAAM;EAC5F,IAAI,QAAQ,IAAI,sBAAsB,QACpC,WAAW,OAAO,QAAQ,IAAI;EAEhC,IAAI,QAAQ,IAAI,iBAAiB,QAC/B,WAAW,QAAQ,QAAQ,IAAI;EAEjC,MAAM,oBAAoB,UAAU;CACtC;CACA,MAAM,cAAc,QAAQ,IAAI;CAChC,IAAI,gBAAgB,UAAa,YAAY,SAAS,GACpD,MAAM,iBAAiB,aAAa,QAAQ,UAAU,QAAQ,GAAG;CAEnE,MAAM,WAAsB,MAAM,MAAM,WAAW,QAAQ,MAAM,OAAO,SAAS,SAAS,IAAI,IAAI;CAClG,MAAM,OAUF;EACF,QAAQ;EACR,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,UAAU,MAAM;EAChB,KAAK,QAAQ;EACb,UAAU,QAAQ;EAClB,UAAU,MAAM,OAAO;EACvB;CACF;CACA,IAAI,MAAM,gBAAgB,QACxB,KAAK,cAAc,MAAM;CAE3B,OAAO;AACT;;;;ACjMA,eAAsB,SAAS,OAAyC;CACtE,MAAM,MAAM,MAAM;CAClB,MAAM,SAAS,eAAe,MAAM,WAAW,GAAG,GAAG,KAAK;CAC1D,MAAM,QAAQ,MAAM,UAAU,GAAG;CACjC,MAAM,OAAO,MAAM,QAAQ,OAAO,OAAO,QAAQ;CACjD,MAAM,QAAuB;EAAE,MAAM;EAAS;CAAK;CACnD,MAAM,MAAM,WAAW,KAAK;CAC5B,MAAM,cAAkD;EACtD;EACA;EACA,aAAa;EACb,WAAW;CACb;CACA,IAAI,IAAI,gBAAgB,QACtB,YAAY,cAAc,IAAI;CAEhC,MAAM,QAAQ,MAAM,aAAa,WAAW;CAC5C,MAAM,WAAW,MAAM,YAAY,OAAO,QAAQ,MAAM,SAAS,OAAO,UAAU,KAAK,CAAC;CAExF,IAAI,MAAM,WAAW,MAAM;EACzB,MAAM,MAAmB;GACvB,QAAQ;GACR;GACA,MAAM,SAAS;GACf,UAAU,SAAS;GACnB,UAAU,CAAC;GACX,UAAU;EACZ;EACA,IAAI,SAAS,YAAY,QACvB,IAAI,cAAc,SAAS;EAE7B,OAAO;CACT;CAEA,MAAM,WAAW,MAAM,qBAAqB;CAC5C,MAAM,gBAAgD;EACpD;EACA;EACA;EACA;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;EACA,QAAQ,cAAc,MAAM,QAAQ,MAAM,KAAK;EAC/C,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACtC;CACA,MAAM,QAAQ,MAAM,UAAU,KAAK,KAAK;CACxC,IAAI,UAAU,QACZ,cAAc,QAAQ;CAGxB,MAAM,YAA8C;EAClD;EACA;EACA;EACA,cALmB,SAAS,aAAa;EAMzC;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;CACF;CACA,IAAI,SAAS,YAAY,QACvB,UAAU,cAAc,SAAS;CAEnC,OAAO,WAAW,SAAS;AAC7B;;;;ACxFA,MAAMC,kBAAgB,UAAU,QAAQ;AACxC,MAAM,iBAAiB;AAgBvB,eAAsB,UAAU,KAAoC;CAClE,MAAM,SAAwB,CAAC;CAC/B,OAAO,KAAK,UAAU,CAAC;CACvB,OAAO,KAAK,MAAM,SAAS,GAAG,CAAC;CAC/B,OAAO,KAAK,MAAM,aAAa,GAAG,CAAC;CACnC,OAAO,KAAK,MAAM,WAAW,GAAG,CAAC;CACjC,OAAO,KAAK,MAAM,UAAU,CAAC;CAC7B,OAAO,KAAK,MAAM,UAAU,GAAG,CAAC;CAChC,OAAO,KAAK,iBAAiB,CAAC;CAC9B,OAAO,KAAK,MAAM,YAAY,CAAC;CAE/B,OAAO;EACL,IAAI,OAAO,OAAO,UAAU,MAAM,WAAW,MAAM;EACnD;CACF;AACF;AAEA,SAAS,YAAyB;CAChC,MAAM,UAAU,QAAQ,SAAS;CAEjC,IADc,OAAO,SAAS,QAAQ,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,EACpD,KAAK,gBACX,OAAO;EAAE,MAAM;EAAQ,QAAQ;EAAQ,SAAS,WAAW;CAAU;CAEvE,OAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS,WAAW,QAAQ,2BAA2B,eAAe;EACtE,KAAK,mBAAmB,eAAe;CACzC;AACF;AAEA,eAAe,SAAS,KAAmC;CACzD,IAAI;EACF,MAAM,EAAE,WAAW,MAAMA,gBAAc,OAAO,CAAC,WAAW,GAAG,EAAE,IAAI,CAAC;EACpE,OAAO;GAAE,MAAM;GAAO,QAAQ;GAAQ,SAAS,OAAO,KAAK;EAAE;CAC/D,QAAQ;EACN,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;CACF;AACF;AAEA,eAAe,aAAa,KAAmC;CAC7D,IAAI;EACF,MAAM,EAAE,WAAW,MAAMA,gBAAc,OAAO,CAAC,aAAa,yBAAyB,GAAG,EACtF,IACF,CAAC;EACD,IAAI,OAAO,KAAK,MAAM,QACpB,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;EAEF,OAAO;GAAE,MAAM;GAAe,QAAQ;GAAQ,SAAS;EAAiC;CAC1F,QAAQ;EACN,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;EACX;CACF;AACF;AAEA,eAAe,WAAW,KAAmC;CAC3D,MAAM,OAAO,KAAK,KAAK,aAAa,YAAY;CAChD,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS;EACT,KAAK;CACP;CAEF,IAAI;EACF,MAAM,MAAe,KAAK,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC;EAC5D,MAAM,SAAS,YAAY,UAAU,GAAG;EACxC,IAAI,CAAC,OAAO,SACV,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK,OAAO,MAAM,OAAO,KAAK,UAAU,MAAM,OAAO,CAAC,CAAC,KAAK,IAAI;EAClE;EAEF,OAAO;GAAE,MAAM;GAAc,QAAQ;GAAQ,SAAS,SAAS,OAAO,KAAK,KAAK;EAAY;CAC9F,SAAS,OAAO;EACd,IAAI,iBAAiB,aACnB,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;EAEF,MAAM;CACR;AACF;AAEA,eAAe,YAAkC;CAC/C,IAAI;EACF,MAAM,OAAO,mBAAmB;EAChC,MAAM,WAAW,KAAK,MAAM,UAAU,SAAS,qBAAqB;EACpE,IAAI,CAAC,WAAW,QAAQ,GACtB,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;EAEF,OAAO;GAAE,MAAM;GAAS,QAAQ;GAAQ,SAAS,uBAAuB;EAAW;CACrF,QAAQ;EACN,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;CACF;AACF;AAEA,eAAe,UAAU,KAAmC;CAC1D,MAAM,OAAO,KAAK,KAAK,aAAa,YAAY;CAChD,IAAI,CAAC,WAAW,IAAI,GAClB,OAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS;CACX;CAEF,MAAM,MAAe,KAAK,MAAM,MAAM,SAAS,MAAM,MAAM,CAAC;CAC5D,MAAM,SAAS,YAAY,UAAU,GAAG;CACxC,IAAI,CAAC,OAAO,WAAW,OAAO,KAAK,SAAS,QAC1C,OAAO;EAAE,MAAM;EAAQ,QAAQ;EAAQ,SAAS;CAA8B;CAEhF,MAAM,QAAQ,KAAK,KAAK,OAAO,KAAK,KAAK,KAAK;CAC9C,IAAI,CAAC,WAAW,KAAK,GACnB,OAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS,aAAa,OAAO,KAAK,KAAK,MAAM;EAC7C,KAAK;CACP;CAEF,OAAO;EAAE,MAAM;EAAQ,QAAQ;EAAQ,SAAS,oBAAoB,OAAO,KAAK,KAAK;CAAQ;AAC/F;AAEA,SAAS,mBAAgC;CACvC,IAAI,QAAQ,IAAI,iBAAiB,UAAa,QAAQ,IAAI,aAAa,SAAS,GAC9E,OAAO;EAAE,MAAM;EAAgB,QAAQ;EAAQ,SAAS;CAAuB;CAEjF,OAAO;EACL,MAAM;EACN,QAAQ;EACR,SAAS;CACX;AACF;AAEA,eAAe,cAAoC;CACjD,IAAI;EAEF,MAAM,MAAM,OAAM,MADK,qBAAqB,EAClB,CAAC,OAAO,aAAa,GAAG;GAChD,OAAO,QAAQ,GAAG;GAClB,QAAQ,QAAQ,GAAG;GACnB,QAAQ;EACV,CAAC;EACD,IAAI,IAAI,SAAS,KAAK,IAAI,OAAO,OAAQ,IAAI,OAAO,IAClD,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,KAAK;EACP;EAEF,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS,cAAc,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,cAAc,IAAI,OAAO;EACxF;CACF,SAAS,OAAO;EACd,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;GAClD,KAAK;EACP;CACF;AACF;;;;AC3NA,MAAM,MAAM;AAEZ,SAAgB,cAAc,OAAmC;CAC/D,MAAM,UAAU,MAAM,KAAK;CAC3B,MAAM,MAAM,aAAa,OAAO;CAChC,IAAI,QAAQ,QACV,OAAO;CAET,MAAM,QAAQ,WAAW,OAAO;CAChC,IAAI,UAAU,QACZ,OAAO,WAAW,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAE7C,MAAM,MAAM,SAAS,OAAO;CAC5B,IAAI,QAAQ,QACV,OAAO,SAAS,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;CAExC,MAAM,MAAM,SAAS,OAAO;CAC5B,IAAI,QAAQ,QACV,OAAO,SAAS,GAAG,SAAS,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;AAGvD;AAEA,SAAgB,aAAa,OAAmC;CAC9D,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,CAAC;CACnC,IAAI,UAAU,MACZ;CAEF,MAAM,MAAM,MAAM;CAClB,IAAI,QAAQ,QACV;CAEF,IAAI,IAAI,WAAW,GACjB,OAAO,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,YAAY;CAE/E,OAAO,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY;AACzC;AAEA,SAAgB,WAAW,GAAW,GAAW,GAAmB;CAClE,MAAM,KAAM,IAAI,KAAK,KAAM;CAC3B,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE;CACzB,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE;CACzB,MAAM,QAAQ,IAAI,cAAe,IAAI,cAAe;CACpD,MAAM,QAAQ,IAAI,cAAe,IAAI,cAAe;CACpD,MAAM,QAAQ,IAAI,cAAe,IAAI,cAAc;CACnD,MAAM,KAAK,QAAQ,QAAQ;CAC3B,MAAM,KAAK,QAAQ,QAAQ;CAC3B,MAAM,KAAK,QAAQ,QAAQ;CAC3B,MAAM,IAAI,eAAe,KAAK,eAAe,KAAK,cAAe;CACjE,MAAM,IAAI,gBAAgB,KAAK,eAAe,KAAK,cAAe;CAClE,MAAM,OAAO,eAAgB,KAAK,cAAe,KAAK,cAAc;CACpE,OAAO,SAAS,WAAW,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,GAAG;AAClF;AAEA,SAAgB,cAAc,MAAc,MAAsB;CAChE,MAAM,IAAI,kBAAkB,IAAI;CAChC,MAAM,IAAI,kBAAkB,IAAI;CAChC,MAAM,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;CACvC,QAAQ,KAAK,QAAS,KAAK;AAC7B;AAEA,MAAa,sBAAsB;AAEnC,SAAgB,yBACd,YACA,YAC2C;CAC3C,IAAI,cAAc,YAAY,UAAU,QACtC,OAAO;EAAE;EAAY,UAAU;CAAM;CAEvC,MAAM,QAAQ;CACd,MAAM,OAAO;CAGb,OAAO;EAAE,YAFU,cAAc,YAAY,KAEf,KADZ,cAAc,YAAY,IACD,IAAI,QAAQ;EAAM,UAAU;CAAK;AAC9E;AAEA,SAAgB,qBAAqB,YAAoB,WAA4B;CACnF,OAAO,cAAc,YAAY,SAAS;AAC5C;AAEA,SAAS,WAAW,SAAyB;CAC3C,MAAM,MAAM,KAAK,IAAI,OAAO;CAC5B,MAAM,UAAU,OAAO,WAAY,QAAQ,MAAM,QAAQ,QAAQ,IAAI,OAAO;CAC5E,OAAO,KAAK,KAAK,OAAO,IAAI;AAC9B;AAEA,SAAS,SAAS,GAAW,GAAW,GAAmB;CACzD,OAAO,IAAI,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,OAAO,CAAC;AAC7C;AAEA,SAAS,OAAO,GAAmB;CACjC,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAC7C,SAAS,EAAE,CAAC,CACZ,SAAS,GAAG,GAAG;AACpB;AAEA,SAAS,kBAAkB,KAAqB;CAC9C,MAAM,MAAM,SAAS,GAAG;CACxB,IAAI,QAAQ,QACV,OAAO;CAET,MAAM,MAAM,IAAI,KAAK,YAAY;EAC/B,MAAM,IAAI,UAAU;EACpB,OAAO,KAAK,SAAU,IAAI,UAAU,IAAI,QAAS,UAAU;CAC7D,CAAC;CACD,OAAO,SAAU,IAAI,MAAM,KAAK,SAAU,IAAI,MAAM,KAAK,SAAU,IAAI,MAAM;AAC/E;AAEA,SAAgB,aAAa,KAAsB;CACjD,MAAM,MAAM,SAAS,GAAG;CACxB,IAAI,QAAQ,QACV,OAAO;CAIT,OAFY,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAEhC,IADG,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAC1B,IAAI;AACrB;AAEA,SAAS,SAAS,KAAmD;CACnE,MAAM,aAAa,aAAa,GAAG;CACnC,IAAI,eAAe,QACjB;CAKF,OAAO;EAHG,OAAO,SAAS,WAAW,MAAM,GAAG,CAAC,GAAG,EAG1C;EAFE,OAAO,SAAS,WAAW,MAAM,GAAG,CAAC,GAAG,EAEvC;EADD,OAAO,SAAS,WAAW,MAAM,GAAG,CAAC,GAAG,EACpC;CAAC;AACjB;AAEA,SAAS,WAAW,OAAgE;CAClF,MAAM,QAAQ,gDAAgD,KAAK,KAAK;CACxE,IAAI,UAAU,MACZ;CAEF,MAAM,OAAO,MAAM;CACnB,IAAI,SAAS,QACX;CAEF,MAAM,QAAQ,aAAa,IAAI;CAC/B,IAAI,MAAM,SAAS,GACjB;CAEF,MAAM,IAAI,eAAe,MAAM,MAAM,EAAE;CACvC,MAAM,IAAI,YAAY,MAAM,MAAM,EAAE;CACpC,MAAM,IAAI,SAAS,MAAM,MAAM,EAAE;CACjC,IAAI,MAAM,UAAa,MAAM,UAAa,MAAM,QAC9C;CAEF,OAAO;EAAE;EAAG;EAAG;CAAE;AACnB;AAEA,SAAS,SAAS,OAAqD;CACrE,MAAM,QAAQ,gDAAgD,KAAK,KAAK;CACxE,IAAI,UAAU,MACZ;CAEF,MAAM,QAAQ,aAAa,MAAM,MAAM,EAAE;CACzC,IAAI,MAAM,SAAS,GACjB;CAEF,MAAM,IAAI,gBAAgB,MAAM,MAAM,EAAE;CACxC,MAAM,IAAI,gBAAgB,MAAM,MAAM,EAAE;CACxC,MAAM,IAAI,gBAAgB,MAAM,MAAM,EAAE;CACxC,IAAI,MAAM,UAAa,MAAM,UAAa,MAAM,QAC9C;CAEF,OAAO;EAAC;EAAG;EAAG;CAAC;AACjB;AAEA,SAAS,SAAS,OAAqD;CACrE,MAAM,QAAQ,gDAAgD,KAAK,KAAK;CACxE,IAAI,UAAU,MACZ;CAEF,MAAM,QAAQ,aAAa,MAAM,MAAM,EAAE;CACzC,IAAI,MAAM,SAAS,GACjB;CAEF,MAAM,IAAI,SAAS,MAAM,MAAM,EAAE;CACjC,MAAM,IAAI,aAAa,MAAM,MAAM,EAAE;CACrC,MAAM,IAAI,aAAa,MAAM,MAAM,EAAE;CACrC,IAAI,MAAM,UAAa,MAAM,UAAa,MAAM,QAC9C;CAEF,OAAO;EAAC;EAAG;EAAG;CAAC;AACjB;AAEA,SAAS,SAAS,GAAW,GAAW,GAAqC;CAC3E,MAAM,MAAM,IAAI;CAChB,MAAM,QAAQ,IAAI;CAClB,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK;CAC1C,MAAM,MAAQ,IAAI,MAAO,OAAO,MAAO;CACvC,MAAM,IAAI,KAAK,IAAI,KAAK,IAAK,KAAK,IAAK,CAAC;CACxC,IAAI,IAAI;CACR,IAAI,IAAI;CACR,IAAI,IAAI;CACR,IAAI,KAAK,GAAG;EACV,IAAI;EACJ,IAAI;CACN,OAAO,IAAI,KAAK,GAAG;EACjB,IAAI;EACJ,IAAI;CACN,OAAO,IAAI,KAAK,GAAG;EACjB,IAAI;EACJ,IAAI;CACN,OAAO,IAAI,KAAK,GAAG;EACjB,IAAI;EACJ,IAAI;CACN,OAAO,IAAI,KAAK,GAAG;EACjB,IAAI;EACJ,IAAI;CACN,OAAO;EACL,IAAI;EACJ,IAAI;CACN;CACA,MAAM,IAAI,QAAQ,IAAI;CACtB,OAAO;GAAE,IAAI,KAAK;GAAM,IAAI,KAAK;GAAM,IAAI,KAAK;CAAG;AACrD;AAEA,SAAS,aAAa,MAAwB;CAC5C,OAAO,KACJ,MAAM,QAAQ,CAAC,CACf,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,QAAQ,SAAS,KAAK,SAAS,CAAC;AACrC;AAEA,SAAS,eAAe,OAAmC;CACzD,IAAI,MAAM,SAAS,GAAG,GAAG;EACvB,MAAM,IAAI,OAAO,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;EAC9C,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,MAAM;CACxC;CACA,OAAO,YAAY,KAAK;AAC1B;AAEA,SAAS,SAAS,OAAmC;CACnD,IAAI,UAAU,QACZ,OAAO;CAET,IAAI,MAAM,SAAS,KAAK,GACtB,OAAO,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;CAEvC,IAAI,MAAM,SAAS,KAAK,GAAG;EACzB,MAAM,IAAI,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;EACxC,OAAO,MAAM,SAAY,SAAa,IAAI,MAAO,KAAK;CACxD;CACA,IAAI,MAAM,SAAS,MAAM,GAAG;EAC1B,MAAM,IAAI,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;EACxC,OAAO,MAAM,SAAY,SAAY,IAAI;CAC3C;CACA,IAAI,MAAM,SAAS,MAAM,GAAG;EAC1B,MAAM,IAAI,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;EACxC,OAAO,MAAM,SAAY,SAAY,IAAI;CAC3C;CACA,OAAO,YAAY,KAAK;AAC1B;AAEA,SAAS,aAAa,OAAmC;CACvD,IAAI,CAAC,MAAM,SAAS,GAAG,GACrB,OAAO,YAAY,KAAK;CAE1B,OAAO,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;AACvC;AAEA,SAAS,gBAAgB,OAAmC;CAC1D,IAAI,MAAM,SAAS,GAAG,GAAG;EACvB,MAAM,IAAI,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;EACxC,OAAO,MAAM,SAAY,SAAa,IAAI,MAAO;CACnD;CACA,OAAO,YAAY,KAAK;AAC1B;AAEA,SAAS,YAAY,OAAmC;CACtD,IAAI,UAAU,QACZ,OAAO;CAET,MAAM,IAAI,OAAO,WAAW,KAAK;CACjC,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;;;;ACjRA,MAAM,OACJ;;AAGF,MAAM,WAAW;;;;;AAMjB,MAAM,YAAY;CAChB;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,qBAAqB,KAA8B;CACjE,MAAM,OAAO,aAAa,GAAG;CAC7B,MAAM,QAAgC,CAAC;CAEvC,KAAK,MAAM,YAAY,WACrB,OAAO,OAAO,OAAO,mBAAmB,KAAK,UAAU,IAAI,CAAC;CAE9D,OAAO,eAAe,KAAK;AAC7B;AAEA,SAAS,aAAa,KAAqC;CACzD,MAAM,OAA+B,CAAC;CACtC,SAAS,YAAY;CACrB,IAAI;CACJ,QAAQ,QAAQ,SAAS,KAAK,GAAG,OAAO,MAAM;EAC5C,MAAM,OAAO,MAAM;EACnB,MAAM,QAAQ,MAAM;EACpB,IAAI,SAAS,UAAa,UAAU,QAClC,KAAK,QAAQ,MAAM,KAAK;CAE5B;CACA,OAAO;AACT;;;;;;;;;;AAWA,SAAS,aAAa,KAAa,MAA8B,QAAQ,GAAuB;CAC9F,MAAM,QAAQ,IAAI,KAAK;CACvB,IAAI,QAAQ,GAAG;EACb,MAAM,MAAM,uCAAuC,KAAK,KAAK;EAC7D,MAAM,SAAS,MAAM,OAAO,SAAY,SAAY,KAAK,IAAI;EAC7D,IAAI,WAAW,QACb,OAAO,aAAa,QAAQ,MAAM,QAAQ,CAAC;CAE/C;CACA,MAAM,SAAS,cAAc,KAAK;CAClC,IAAI,WAAW,QACb,OAAO;CAET,MAAM,QAAQ,MAAM,MAAM,QAAQ,CAAC,CAAC,QAAQ,MAAM,EAAE,SAAS,CAAC;CAC9D,IAAI,MAAM,WAAW,GAAG;EACtB,IAAI,MAAM,EAAE,EAAE,SAAS,GAAG,MAAM,QAAQ,MAAM,EAAE,EAAE,SAAS,GAAG,MAAM,MAClE,OAAO,cAAc,OAAO,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE;EAEjE,IAAI,MAAM,OAAO,MAAM,gBAAgB,KAAK,CAAC,CAAC,GAC5C,OAAO,cAAc,OAAO,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,EAAE;CAEnE;AAEF;AAEA,SAAS,mBACP,KACA,SACA,MACwB;CACxB,MAAM,QAAgC,CAAC;CACvC,QAAQ,YAAY;CACpB,IAAI;CACJ,QAAQ,QAAQ,QAAQ,KAAK,GAAG,OAAO,MAAM;EAC3C,MAAM,OAAO,IAAI,QAAQ,KAAK,MAAM,KAAK;EACzC,IAAI,SAAS,IACX;EAEF,MAAM,QAAQC,gBAAc,KAAK,IAAI;EACrC,IAAI,UAAU,IACZ;EAEF,MAAM,OAAO,IAAI,MAAM,OAAO,GAAG,KAAK;EACtC,KAAK,YAAY;EACjB,IAAI;EACJ,QAAQ,OAAO,KAAK,KAAK,IAAI,OAAO,MAAM;GACxC,MAAM,OAAO,KAAK;GAClB,MAAM,MAAM,KAAK;GACjB,IAAI,SAAS,UAAa,QAAQ,QAChC;GAEF,MAAM,MAAM,aAAa,KAAK,IAAI;GAClC,IAAI,QAAQ,QACV,MAAM,QAAQ;EAElB;CACF;CACA,OAAO;AACT;AAEA,SAAS,eAAe,OAAgD;CACtE,MAAM,MAAuB,CAAC;CAC9B,MAAM,aAAa,MAAM;CACzB,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,MAAM,aAAa,MAAM;CACzB,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,MAAM,QAAQ,MAAM,uBAAuB,MAAM;CACjD,IAAI,UAAU,QACZ,IAAI,QAAQ;CAEd,MAAM,UAAU,MAAM,WAAW,MAAM;CACvC,IAAI,YAAY,QACd,IAAI,UAAU;CAEhB,IAAI,MAAM,WAAW,QACnB,IAAI,SAAS,MAAM;CAErB,OAAO;AACT;AAEA,SAASA,gBAAc,QAAgB,WAA2B;CAChE,IAAI,QAAQ;CACZ,KAAK,IAAI,IAAI,WAAW,IAAI,OAAO,QAAQ,KAAK,GAAG;EACjD,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KACT,SAAS;OACJ,IAAI,OAAO,KAAK;GACrB,SAAS;GACT,IAAI,UAAU,GACZ,OAAO;EAEX;CACF;CACA,OAAO;AACT;;;;ACxJA,SAAgB,kBAAkB,QAAkC;CAClE,MAAM,QAAgC,CAAC;CACvC,KAAK,QAAQ,CAAC,GAAG,KAAK;CACtB,MAAM,MAAuB,CAAC;CAC9B,MAAM,aAAa,MAAM,cAAc,MAAM;CAC7C,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,MAAM,aAAa,MAAM,cAAc,MAAM;CAC7C,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,IAAI,MAAM,UAAU,QAClB,IAAI,QAAQ,MAAM;CAEpB,MAAM,UAAU,MAAM,WAAW,MAAM;CACvC,IAAI,YAAY,QACd,IAAI,UAAU;CAEhB,MAAM,SAAS,MAAM,UAAU,MAAM;CACrC,IAAI,WAAW,QACb,IAAI,SAAS;CAEf,OAAO;AACT;AAEA,SAAS,KAAK,MAAe,MAAgB,OAAqC;CAChF,IAAI,CAAC,SAAS,IAAI,GAChB;CAEF,IAAI,KAAK,UAAU,SAAS;EAC1B,MAAM,MAAM,WAAW,KAAK,MAAM;EAClC,MAAM,OAAO,KAAK,KAAK,SAAS;EAChC,IAAI,QAAQ,UAAa,SAAS,UAAa,MAAM,UAAU,QAC7D,MAAM,QAAQ;EAEhB;CACF;CACA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;EAC/C,IAAI,IAAI,WAAW,GAAG,GACpB;EAEF,KAAK,OAAO,CAAC,GAAG,MAAM,GAAG,GAAG,KAAK;CACnC;AACF;AAEA,SAAS,WAAW,OAAoC;CACtD,IAAI,OAAO,UAAU,UACnB,OAAO,cAAc,KAAK;CAE5B,IAAI,SAAS,KAAK,KAAK,OAAO,MAAM,QAAQ,UAC1C,OAAO,cAAc,MAAM,GAAG;AAGlC;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;;ACnDA,MAAM,aAAa;AACnB,MAAM,cAAc;AACpB,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAS;CAAW;CAAQ;CAAU;CAAS;AAAa,CAAC;AAE5F,SAAgB,wBAAwB,KAA8B;CACpE,MAAM,SAAS,YAAY,GAAG;CAC9B,MAAM,SAAS,wBAAwB,GAAG;CAC1C,MAAM,YAAoC,CAAC;CAC3C,KAAK,MAAM,SAAS,QAAQ;EAC1B,WAAW,YAAY;EACvB,IAAI;EACJ,QAAQ,QAAQ,WAAW,KAAK,KAAK,OAAO,MAAM;GAChD,MAAM,OAAO,MAAM;GACnB,MAAM,MAAM,MAAM;GAClB,IAAI,SAAS,UAAa,QAAQ,UAAa,WAAW,IAAI,GAC5D;GAEF,UAAU,QAAQ,IAAI,KAAK;EAC7B;CACF;CACA,MAAM,WAAmC,CAAC;CAC1C,KAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,SAAS,GAAG;EACnD,MAAM,MAAM,aAAa,KAAK,QAAQ,CAAC;EACvC,IAAI,QAAQ,QACV,SAAS,QAAQ;CAErB;CACA,OAAO,eAAe,QAAQ;AAChC;AAEA,SAAgB,wBAAwB,QAAiC;CACvE,MAAM,QAAgC,CAAC;CACvC,MAAM,KACJ;CACF,IAAI;CACJ,QAAQ,QAAQ,GAAG,KAAK,MAAM,OAAO,MAAM;EACzC,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,MAAM;EAClB,IAAI,SAAS,UAAa,QAAQ,QAChC;EAEF,MAAM,MAAM,cAAc,GAAG;EAC7B,IAAI,QAAQ,QACV,MAAM,QAAQ;CAElB;CACA,OAAO,eAAe,KAAK;AAC7B;AAEA,SAAS,YAAY,KAAuB;CAC1C,MAAM,SAAmB,CAAC;CAC1B,MAAM,KAAK;CACX,IAAI;CACJ,QAAQ,QAAQ,GAAG,KAAK,GAAG,OAAO,MAAM;EACtC,MAAM,OAAO,IAAI,QAAQ,KAAK,MAAM,KAAK;EACzC,IAAI,SAAS,IACX;EAEF,MAAM,QAAQ,cAAc,KAAK,IAAI;EACrC,IAAI,UAAU,IACZ;EAEF,OAAO,KAAK,IAAI,MAAM,OAAO,GAAG,KAAK,CAAC;CACxC;CACA,OAAO;AACT;AAEA,SAAS,cAAc,QAAgB,WAA2B;CAChE,IAAI,QAAQ;CACZ,KAAK,IAAI,IAAI,WAAW,IAAI,OAAO,QAAQ,KAAK,GAAG;EACjD,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,KACT,SAAS;OACJ,IAAI,OAAO,KAAK;GACrB,SAAS;GACT,IAAI,UAAU,GACZ,OAAO;EAEX;CACF;CACA,OAAO;AACT;AAEA,SAAS,wBAAwB,KAAkC;CACjE,MAAM,wBAAQ,IAAI,IAAoB;CACtC,YAAY,YAAY;CACxB,IAAI;CACJ,QAAQ,QAAQ,YAAY,KAAK,GAAG,OAAO,MAAM;EAC/C,MAAM,OAAO,MAAM;EACnB,MAAM,QAAQ,MAAM;EACpB,IAAI,SAAS,UAAa,UAAU,QAClC,MAAM,IAAI,KAAK,QAAQ,MAAM,KAAK,CAAC;CAEvC;CACA,OAAO;AACT;AAEA,SAAS,aACP,KACA,QACA,OACoB;CACpB,IAAI,QAAQ,GACV;CAEF,MAAM,SAAS,cAAc,GAAG;CAChC,IAAI,WAAW,QACb,OAAO;CAET,MAAM,WAAW,8CAA8C,KAAK,GAAG;CACvE,IAAI,aAAa,MACf;CAEF,MAAM,MAAM,SAAS;CACrB,IAAI,QAAQ,QACV;CAEF,MAAM,OAAO,OAAO,IAAI,GAAG;CAC3B,IAAI,SAAS,QACX;CAEF,OAAO,aAAa,MAAM,QAAQ,QAAQ,CAAC;AAC7C;AAEA,SAAS,WAAW,MAAuB;CACzC,MAAM,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC;CAC7B,OAAO,SAAS,UAAa,cAAc,IAAI,IAAI;AACrD;AAEA,SAAS,eAAe,OAAgD;CACtE,MAAM,MAAuB,CAAC;CAC9B,MAAM,aAAa,MAAM,cAAc,MAAM;CAC7C,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,MAAM,aAAa,MAAM,cAAc,MAAM;CAC7C,IAAI,eAAe,QACjB,IAAI,aAAa;CAEnB,MAAM,QAAQ,MAAM,uBAAuB,MAAM;CACjD,IAAI,UAAU,QACZ,IAAI,QAAQ;CAEd,MAAM,UAAU,MAAM,WAAW,MAAM;CACvC,IAAI,YAAY,QACd,IAAI,UAAU;CAEhB,MAAM,SAAS,MAAM,UAAU,MAAM;CACrC,IAAI,WAAW,QACb,IAAI,SAAS;CAEf,OAAO;AACT;;;;;AC7IA,SAASC,WAAS,MAAsB;CACtC,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;AAClC;AAEA,SAAS,SAAS,MAAc,MAAsB;CACpD,MAAM,SAAS,KAAK,SAAS,GAAG,IAAI,OAAO,GAAG,KAAK;CACnD,OAAO,KAAK,WAAW,MAAM,IAAI,KAAK,MAAM,OAAO,MAAM,IAAI;AAC/D;AAEA,eAAsB,iBACpB,OACA,KACA,UACA,SACA,OACA,kBAA6B,QAAQ,QAAQ,MAAS,GAC5B;CAC1B,MAAM,SAA0B,CAAC;CACjC,MAAM,QAAQ,MAAM,MAAM,KAAK;CAE/B,MAAM,WAAW,MAAM,QAAQ,SAAS,KAAK,SAAS,MAAM,CAAC;CAC7D,MAAM,cAAc,MAAM,QAAQ,IAChC,SAAS,IAAI,OAAO,UAAU;EAAE;EAAM,KAAK,MAAM,MAAM,KAAK,IAAI;CAAE,EAAE,CACtE;CACA,KAAK,MAAM,EAAE,MAAM,SAAS,aAAa;EACvC,IAAI,QAAQ,QACV;EAEF,MAAM,YAAY,wBAAwB,GAAG;EAC7C,MAAM,WAAW,qBAAqB,GAAG;EACzC,MAAM,MAAM,SAAS,KAAK,IAAI;EAC9B,YAAY,QAAQ,WAAW,SAAS,yBAAyB,KAAK;EACtE,YAAY,QAAQ,UAAU,SAAS,sBAAsB,KAAK;CACpE;CAEA,MAAM,cAAc,MAAM,QAAQ,SAASA,WAAS,IAAI,CAAC,CAAC,WAAW,kBAAkB,CAAC;CACxF,MAAM,iBAAiB,MAAM,QAAQ,IACnC,YAAY,IAAI,OAAO,UAAU;EAAE;EAAM,QAAQ,MAAM,MAAM,KAAK,IAAI;CAAE,EAAE,CAC5E;CACA,KAAK,MAAM,EAAE,MAAM,YAAY,gBAAgB;EAC7C,IAAI,WAAW,QACb;EAEF,YACE,QACA,wBAAwB,MAAM,GAC9B,SACA,mBAAmB,SAAS,KAAK,IAAI,GACvC;CACF;CAEA,MAAM,YAAY,MAAM,MAAM,SAAS,KAAK,SAAS,cAAc,CAAC;CACpE,IAAI,cAAc,QAAW;EAC3B,MAAM,MAAM,MAAM,MAAM,KAAK,SAAS;EACtC,IAAI,QAAQ,QACV,IAAI;GACF,MAAM,SAAkB,KAAK,MAAM,GAAG;GACtC,YAAY,QAAQ,kBAAkB,MAAM,GAAG,SAAS,SAAS,KAAK,SAAS,CAAC;EAClF,SAAS,OAAO;GACd,IAAI,iBAAiB,aACnB,MAAM,KAAK,sCAAsC,SAAS,KAAK,SAAS,EAAE,EAAE;QAE5E,MAAM;EAEV;CAEJ;CAEA,IAAI,OAAO,YAAY,UAAa,aAAa,QAAW;EAC1D,MAAM,UAAU,SAAS,SAAS,MAAM,IAAI,MAAM,UAAU,OAAO,QAAQ,IAAI;EAC/E,IAAI,YAAY,QAAW;GACzB,OAAO,UAAU;GACjB,QAAQ,KAAK;IAAE,OAAO;IAAkB,QAAQ,qBAAqB;GAAW,CAAC;EACnF;EACA,MAAM,MAAM,SAAS,SAAS,MAAM,IAAI,MAAM,MAAM,KAAK,QAAQ,IAAI;EACrE,IAAI,QAAQ,QAAW;GACrB,MAAM,WAAW,wBAAwB,GAAG;GAC5C,IAAI,aAAa,QAAW;IAC1B,OAAO,UAAU;IACjB,QAAQ,KAAK;KAAE,OAAO;KAAkB,QAAQ,eAAe;IAAW,CAAC;GAC7E;EACF;CACF;CAKA,MAAM,WAAY;EAAC;EAAc;EAAc;EAAS;EAAW;CAAQ,CAAC,CAAW,QACpF,UAAU,OAAO,WAAW,MAC/B;CACA,IAAI,SAAS,SAAS,GACpB,MAAM,KACJ,+BAA+B,SAAS,KAAK,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE,+EAE/E;CAGF,OAAO;EACL,YAAY,OAAO,cAAc,qBAAqB;EACtD,YAAY,OAAO,cAAc,qBAAqB;EACtD,OAAO,OAAO,SAAS,qBAAqB;EAC5C,SAAS,OAAO,WAAW,qBAAqB;EAChD,QAAQ,OAAO,UAAU,qBAAqB;CAChD;AACF;AAEA,SAAS,YACP,QACA,UACA,SACA,QACM;CAEN,KAAK,MAAM,OAAO;EADJ;EAAc;EAAc;EAAS;EAAW;CACzC,GAAG;EACtB,MAAM,QAAQ,SAAS;EACvB,IAAI,UAAU,UAAa,OAAO,SAAS,QAAW;GACpD,OAAO,OAAO;GACd,QAAQ,KAAK;IAAE,OAAO,UAAU;IAAO;GAAO,CAAC;EACjD;CACF;AACF;AAEA,SAAgB,mBACd,QACA,SACA,OACM;CACN,IAAI,OAAO,UAAU,UAAa,qBAAqB,OAAO,YAAY,OAAO,KAAK,GACpF;CAEF,OAAO,QAAQ,qBAAqB;CACpC,MAAM,KACJ,kGAAkG,qBAAqB,MAAM,EAC/H;CACA,aAAa,SAAS,gBAAgB,qBAAqB;AAC7D;AAEA,SAAgB,oBACd,QACA,SACA,OACM;CACN,IAAI,OAAO,WAAW,UAAa,qBAAqB,OAAO,YAAY,OAAO,MAAM,GACtF;CAEF,OAAO,SAAS,OAAO,WAAW,qBAAqB;CACvD,MAAM,KAAK,0EAA0E;CACrF,aAAa,SAAS,iBAAiB,qBAAqB;AAC9D;AAEA,SAAgB,aAAa,SAAwB,OAAe,QAAsB;CACxF,MAAM,WAAW,QAAQ,MAAM,UAAU,MAAM,UAAU,KAAK;CAC9D,IAAI,aAAa,QAAW;EAC1B,SAAS,SAAS;EAClB;CACF;CACA,QAAQ,KAAK;EAAE;EAAO;CAAO,CAAC;AAChC;AAEA,SAAS,wBAAwB,KAAiC;CAChE,MAAM,KAAK;CACX,IAAI;CACJ,QAAQ,QAAQ,GAAG,KAAK,GAAG,OAAO,MAAM;EACtC,MAAM,MAAM,MAAM;EAClB,IAAI,QAAQ,UAAa,QAAQ,UAAU,QAAQ,gBACjD;EAEF,MAAM,MAAM,cAAc,GAAG;EAC7B,IAAI,QAAQ,UAAa,CAAC,aAAa,GAAG,GACxC,OAAO;CAEX;AAEF;;;;AC/LA,MAAM,cAAc;CAAC;CAAI;CAAU;CAAgB;CAAU;CAAgB;CAAW;CAAQ;CAAU;AAAU;AACpH,MAAM,aAAa,CAAC,YAAY,UAAU;AAC1C,MAAM,QAAQ;CAAC;CAAY;CAAY;CAAkB;AAAgB;AACzE,MAAM,YAAY,CAAC,GAAG,YAAY,aAAa;AAE/C,SAAgB,SAAS,KAAiC;CACxD,KAAK,MAAM,OAAO,aAChB,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAW,QAAQ,KAAK,OAAO,KAAK,KAAK,IAAI;EACnD,IAAI,WAAW,KAAK,KAAK,QAAQ,CAAC,GAChC,OAAO;CAEX;CAEF,KAAK,MAAM,OAAO,aAChB,KAAK,MAAM,QAAQ,WAAW;EAC5B,MAAM,WAAW,QAAQ,KAAK,OAAO,KAAK,KAAK,IAAI;EACnD,IAAI,WAAW,KAAK,KAAK,QAAQ,CAAC,GAChC,OAAO;CAEX;AAGJ;AAEA,SAAgB,aAAa,KAA2D;CACtF,MAAM,QAAQ,SAAS,GAAG;CAC1B,IAAI,UAAU,QACZ;CAEF,MAAM,YAAY,CAAC,iBAAiB,eAAe;CACnD,KAAK,MAAM,OAAO,aAChB,KAAK,MAAM,QAAQ,WAAW;EAC5B,MAAM,WAAW,QAAQ,KAAK,OAAO,KAAK,KAAK,IAAI;EACnD,IAAI,WAAW,KAAK,KAAK,QAAQ,CAAC,GAChC,OAAO;GAAE;GAAO,MAAM;EAAS;CAEnC;CAEF,OAAO,EAAE,MAAM;AACjB;;;;ACpCA,MAAM,YAAY,OAAO,KAAK;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;AAAI,CAAC;;AAG9E,MAAM,WAAmC;CAAE,GAAG;CAAG,GAAG;CAAG,GAAG;CAAG,GAAG;CAAG,GAAG;AAAE;AASxE,SAAgB,UAAU,QAAwC;CAChE,IAAI,OAAO,SAAS,KAAK,CAAC,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,OAAO,SAAS,GAC9D;CAGF,IAAI,QAAQ;CACZ,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,YAAY;CAChB,IAAI,YAAY;CAChB,IAAI;CACJ,IAAI;CACJ,MAAM,OAAiB,CAAC;CAExB,IAAI,SAAS;CACb,OAAO,SAAS,KAAK,OAAO,QAAQ;EAClC,MAAM,SAAS,OAAO,aAAa,MAAM;EACzC,MAAM,OAAO,OAAO,SAAS,SAAS,SAAS,GAAG,SAAS,CAAC;EAC5D,MAAM,QAAQ,SAAS;EACvB,MAAM,MAAM,QAAQ;EACpB,IAAI,MAAM,OAAO,QACf;EAGF,IAAI,SAAS,QAAQ;GACnB,QAAQ,OAAO,aAAa,KAAK;GACjC,SAAS,OAAO,aAAa,QAAQ,CAAC;GACtC,WAAW,OAAO,QAAQ,MAAM;GAChC,YAAY,OAAO,QAAQ,MAAM;GACjC,YAAY,OAAO,QAAQ,OAAO;EACpC,OAAO,IAAI,SAAS,QAClB,UAAU,OAAO,SAAS,OAAO,GAAG;OAC/B,IAAI,SAAS,QAClB,eAAe,OAAO,SAAS,OAAO,GAAG;OACpC,IAAI,SAAS,QAClB,KAAK,KAAK,OAAO,SAAS,OAAO,GAAG,CAAC;OAChC,IAAI,SAAS,QAClB;EAGF,SAAS,MAAM;CACjB;CAEA,MAAM,WAAW,SAAS;CAC1B,IACE,UAAU,KACV,WAAW,KACX,aAAa,UACb,cAAc,KACb,aAAa,KAAK,aAAa,MAChC,KAAK,WAAW,KACf,cAAc,KAAK,YAAY,QAEhC;CAIF,IAAI,QAAQ,SAAS,MACnB;CAGF,IAAI;CACJ,IAAI;EACF,MAAM,YAAY,OAAO,OAAO,IAAI,CAAC;CACvC,QAAQ;EACN;CACF;CAEA,MAAM,iBAAiB,WAAW;CAClC,MAAM,MAAM,WAAW;CACvB,MAAM,SAAS,QAAQ;CACvB,IAAI,IAAI,SAAS,UAAU,SAAS,IAClC;CAGF,MAAM,aAAa,SAAS,KAAK,QAAQ,QAAQ,GAAG;CACpD,IAAI,eAAe,QACjB;CAGF,OAAO;EAAE;EAAO;EAAQ,QAAQ,OAAO,YAAY,OAAO,QAAQ,WAAW,gBAAgB,SAAS,YAAY;CAAE;AACtH;;AAGA,SAAS,SAAS,KAAa,QAAgB,QAAgB,KAAiC;CAC9F,MAAM,MAAM,OAAO,MAAM,SAAS,MAAM;CACxC,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;EAC/B,MAAM,SAAS,IAAI;EACnB,OAAO;EACP,IAAI,WAAW,UAAa,SAAS,GACnC;EAEF,MAAM,WAAW,IAAI;EACrB,MAAM,YAAY,WAAW;EAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;GAC/B,MAAM,QAAQ,IAAI,MAAM,MAAM;GAC9B,MAAM,IAAI,KAAK,MAAO,IAAI,WAAW,IAAI,QAAQ,IAAK;GACtD,MAAM,IAAI,IAAI,IAAK,IAAI,YAAY,MAAM,IAAK;GAC9C,MAAM,IAAI,KAAK,OAAO,IAAI,IAAK,IAAI,YAAY,IAAI,QAAQ,IAAK;GAChE,IAAI;GACJ,QAAQ,QAAR;IACE,KAAK;KACH,WAAW,QAAQ;KACnB;IAEF,KAAK;KACH,WAAW,QAAQ;KACnB;IAEF,KAAK;KACH,WAAW,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC;KACzC;IAEF,KAAK;KACH,WAAW,QAAQ,MAAM,GAAG,GAAG,CAAC;KAChC;IAEF,SACE,WAAW;GAEf;GACA,IAAI,WAAW,KAAK,WAAW;EACjC;EACA,OAAO;CACT;CACA,OAAO;AACT;AAEA,SAAS,MAAM,GAAW,GAAW,GAAmB;CACtD,MAAM,IAAI,IAAI,IAAI;CAClB,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC;CACzB,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC;CACzB,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC;CACzB,IAAI,MAAM,MAAM,MAAM,IACpB,OAAO;CAET,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,OACP,MACA,OACA,QACA,WACA,gBACA,SACA,cACY;CACZ,MAAM,SAAS,IAAI,WAAW,QAAQ,SAAS,CAAC;CAEhD,MAAM,OADW,SAAS,cAAc,KACjB;CAEvB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EAEvC,MAAM,MAAM,YAA4B,KAAK,IAAI,MAAM,UAAU,mBAAmB;EACpF,MAAM,MAAM,IAAI;EAChB,QAAQ,WAAR;GACE,KAAK,GAAG;IACN,MAAM,IAAI,GAAG,CAAC;IACd,OAAO,OAAO;IACd,OAAO,MAAM,KAAK;IAClB,OAAO,MAAM,KAAK;IAClB,OAAO,MAAM,KAAK;IAClB;GACF;GACA,KAAK;IACH,OAAO,OAAO,GAAG,CAAC;IAClB,OAAO,MAAM,KAAK,GAAG,CAAC;IACtB,OAAO,MAAM,KAAK,GAAG,CAAC;IACtB,OAAO,MAAM,KAAK;IAClB;GAEF,KAAK,GAAG;IACN,MAAM,QAAQ,GAAG,CAAC;IAClB,OAAO,OAAO,UAAU,QAAQ,MAAM;IACtC,OAAO,MAAM,KAAK,UAAU,QAAQ,IAAI,MAAM;IAC9C,OAAO,MAAM,KAAK,UAAU,QAAQ,IAAI,MAAM;IAC9C,OAAO,MAAM,KAAK,eAAe,UAAU;IAC3C;GACF;GACA,KAAK,GAAG;IACN,MAAM,IAAI,GAAG,CAAC;IACd,OAAO,OAAO;IACd,OAAO,MAAM,KAAK;IAClB,OAAO,MAAM,KAAK;IAClB,OAAO,MAAM,KAAK,GAAG,CAAC;IACtB;GACF;GACA;IACE,OAAO,OAAO,GAAG,CAAC;IAClB,OAAO,MAAM,KAAK,GAAG,CAAC;IACtB,OAAO,MAAM,KAAK,GAAG,CAAC;IACtB,OAAO,MAAM,KAAK,GAAG,CAAC;EAE1B;CACF;CACA,OAAO;AACT;;;;;;;;;;AAWA,SAAgB,wBAAwB,KAAqC;CAC3E,MAAM,0BAAU,IAAI,IAAgE;CAEpF,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;EAE7C,KADU,IAAI,OAAO,IAAI,MAAM,KACvB,KACN;EAEF,MAAM,IAAI,IAAI,OAAO,MAAM;EAC3B,MAAM,IAAI,IAAI,OAAO,IAAI,MAAM;EAC/B,MAAM,IAAI,IAAI,OAAO,IAAI,MAAM;EAC/B,IAAI,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,IAC1C;EAEF,MAAM,MAAQ,KAAK,KAAM,IAAO,KAAK,KAAM,IAAM,KAAK;EACtD,MAAM,SAAS,QAAQ,IAAI,GAAG;EAC9B,IAAI,WAAW,QACb,QAAQ,IAAI,KAAK;GAAE,OAAO;GAAG;GAAG;GAAG;EAAE,CAAC;OACjC;GACL,OAAO,SAAS;GAChB,OAAO,KAAK;GACZ,OAAO,KAAK;GACZ,OAAO,KAAK;EACd;CACF;CAEA,IAAI;CACJ,KAAK,MAAM,UAAU,QAAQ,OAAO,GAClC,IAAI,SAAS,UAAa,OAAO,QAAQ,KAAK,OAC5C,OAAO;CAGX,IAAI,SAAS,QACX;CAGF,MAAM,WAAW,UACf,KAAK,MAAM,QAAQ,KAAK,KAAK,CAAC,CAC3B,SAAS,EAAE,CAAC,CACZ,SAAS,GAAG,GAAG;CACpB,OAAO,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC;AAC/D;;;;;ACpPA,SAAS,SAAS,MAAsB;CACtC,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;AAClC;AASA,MAAM,gBAAgB,EAAE,OAAO;CAC7B,SAAS,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC9B,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;CAC1B,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;AACvF,CAAC;;;;;AAOD,eAAsB,gBAAgB,OAAqB,MAAM,KAA8B;CAC7F,MAAM,UAAyB,CAAC;CAChC,MAAM,QAAkB,CAAC;CACzB,MAAM,MAAM,MAAM,YAAY,KAAK;CACnC,MAAM,SAAS,MAAM,MAAM,KAAK,WAAW;CAE3C,MAAM,OAAO,WAAW,KAAK,QAAQ,KAAK,OAAO;CACjD,MAAM,UAAU,cAAc,KAAK,QAAQ,OAAO;CAClD,MAAM,MAAM,MAAM,UAAU,OAAO,KAAK,KAAK,OAAO;CACpD,MAAM,OAAO,aAAa,GAAG;CAC7B,IAAI,SAAS,QACX,QAAQ,KAAK;EAAE,OAAO;EAAQ,QAAQ,KAAK;CAAM,CAAC;CAGpD,MAAM,SAAS,MAAM,iBAAiB,OAAO,KAAK,MAAM,OAAO,SAAS,OAAO,iBAAiB;CAChG,MAAM,WAAW,yBAAyB,OAAO,YAAY,OAAO,UAAU;CAC9E,IAAI,SAAS,UAAU;EACrB,OAAO,aAAa,SAAS;EAC7B,MAAM,KACJ,4FAA4F,SAAS,WAAW,EAClH;EACA,aAAa,SAAS,qBAAqB,qBAAqB;CAClE;CACA,mBAAmB,QAAQ,SAAS,KAAK;CACzC,oBAAoB,QAAQ,SAAS,KAAK;CAE1C,MAAM,QAAe;EACnB,SAAS;EACT;EACA;EACA,OAAO;GACL,SAAS,EAAE,GAAG,oBAAoB,QAAQ;GAC1C,MAAM,EAAE,GAAG,oBAAoB,KAAK;GACpC,MAAM,EAAE,GAAG,oBAAoB,KAAK;EACtC;EACA,QAAQ;EACR,OAAO;EACP,OAAO;EACP,QAAQ;CACV;CACA,IAAI,YAAY,QACd,MAAM,UAAU;CAElB,IAAI,QAAQ,QACV,MAAM,MAAM;CAEd,IAAI,SAAS,QACX,MAAM,OAAO,KAAK,SAAS,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI;EAAE,OAAO,KAAK;EAAO,MAAM,KAAK;CAAK;CAEtG,QAAQ,KAAK;EAAE,OAAO;EAAS,QAAQ;CAAuC,CAAC;CAC/E,OAAO;EAAE;EAAO;EAAS;CAAM;AACjC;AAEA,SAAS,WACP,KACA,QACA,KACA,SACQ;CAGR,IAAI,KAAK,SAAS,UAAa,IAAI,YAAY,MAAM;EACnD,MAAM,UAAU,WAAW,IAAI,IAAI;EACnC,MAAM,KAAK,WAAW,SAAY,SAAY,UAAU,MAAM;EAC9D,IAAI,OAAO,UAAa,GAAG,YAAY,MAAM,QAAQ,YAAY,KAAK,OAAO,SAAS;GACpF,QAAQ,KAAK;IAAE,OAAO;IAAQ,QAAQ;GAAe,CAAC;GACtD,OAAO;EACT;EACA,QAAQ,KAAK;GAAE,OAAO;GAAQ,QAAQ;EAAoB,CAAC;EAC3D,OAAO;CACT;CACA,MAAM,KAAK,WAAW,SAAY,SAAY,UAAU,MAAM;CAC9D,IAAI,OAAO,QAAW;EACpB,QAAQ,KAAK;GAAE,OAAO;GAAQ,QAAQ;EAAe,CAAC;EACtD,OAAO;CACT;CACA,QAAQ,KAAK;EAAE,OAAO;EAAQ,QAAQ;CAAiB,CAAC;CACxD,MAAM,UAAU,SAAS,GAAG;CAC5B,OAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,cACP,KACA,QACA,SACoB;CACpB,IAAI,KAAK,gBAAgB,UAAa,IAAI,YAAY,KAAK,CAAC,CAAC,SAAS,GAAG;EACvE,QAAQ,KAAK;GAAE,OAAO;GAAW,QAAQ;EAA2B,CAAC;EACrE,OAAO,IAAI,YAAY,KAAK;CAC9B;CACA,IAAI,WAAW,QAAW;EACxB,MAAM,UAAU,eAAe,MAAM;EACrC,IAAI,YAAY,QAAW;GACzB,QAAQ,KAAK;IAAE,OAAO;IAAW,QAAQ;GAA4B,CAAC;GACtE,OAAO;EACT;CACF;AAEF;AAEA,eAAe,UACb,OACA,KACA,KACA,SAC6B;CAC7B,IAAI,KAAK,aAAa,UAAa,IAAI,SAAS,SAAS,GAAG;EAC1D,QAAQ,KAAK;GAAE,OAAO;GAAO,QAAQ;EAAwB,CAAC;EAC9D,OAAO,IAAI;CACb;CACA,MAAM,OAAO,cAAc,KAAK,UAAU;CAC1C,IAAI,SAAS,QAAW;EACtB,QAAQ,KAAK;GAAE,OAAO;GAAO,QAAQ;EAA0B,CAAC;EAChE,OAAO;CACT;CACA,MAAM,SAAS,MAAM,MAAM,YAAY;CACvC,IAAI,WAAW,QAAW;EACxB,QAAQ,KAAK;GAAE,OAAO;GAAO,QAAQ;EAAoB,CAAC;EAC1D,OAAO;CACT;AAEF;AAOA,eAAe,YAAY,OAAyE;CAClG,MAAM,MAAM,MAAM,MAAM,KAAK,cAAc;CAC3C,IAAI,QAAQ,QACV;CAEF,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,MAAM,SAAS,cAAc,UAAU,MAAM;EAC7C,OAAO,OAAO,UAAU,OAAO,OAAO;CACxC,SAAS,OAAO;EACd,IAAI,iBAAiB,aACnB;EAEF,MAAM;CACR;AACF;AAMA,SAAS,WAAW,MAAsB;CACxC,MAAM,QAAQ,KAAK,MAAM,GAAG;CAC5B,OAAO,MAAM,MAAM,SAAS,MAAM;AACpC;AAGA,SAAS,cAAc,YAA6E;CAClG,IAAI,OAAO,eAAe,UACxB,OAAO,gBAAgB,UAAU;CAEnC,IAAI,YAAY,QAAQ,QACtB,OAAO,gBAAgB,WAAW,GAAG;AAGzC;AAEA,SAAgB,gBAAgB,KAAqB;CACnD,MAAM,MAAM,qBAAqB,KAAK,GAAG;CACzC,IAAI,QAAQ,QAAQ,IAAI,OAAO,UAAa,IAAI,OAAO,QACrD,OAAO,WAAW,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,QAAQ,UAAU,EAAE;CAEzD,OAAO,IAAI,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,UAAU,EAAE;AACvD;;;;;;AAOA,eAAe,kBAAkB,OAAqB,MAA2C;CAC/F,MAAM,SAAS,MAAM,MAAM,WAAW,IAAI;CAC1C,IAAI,WAAW,QACb;CAEF,MAAM,MAAM,UAAU,OAAO,KAAK,MAAM,CAAC;CACzC,IAAI,QAAQ,QACV;CAEF,OAAO,wBAAwB,GAAG;AACpC;;;;ACpOA,MAAM,gBAAgB,UAAU,QAAQ;AAExC,MAAM,4BAAY,IAAI,IAAI;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,eAAsB,YAAY,KAAsC;CACtE,OAAO,gBAAgB,UAAU,GAAG,GAAG,GAAG;AAC5C;;AAGA,SAAgB,UAAU,KAAa,WAAW,GAAiB;CACjE,OAAO;EACL,YAAY,UAAU,KAAK,QAAQ;EACnC,MAAM,OAAO,SAAS;GACpB,IAAI;IACF,OAAO,MAAM,SAAS,WAAW,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,GAAG,MAAM;GACzE,QAAQ;IACN;GACF;EACF;EACA,iBAAiB,UAAU,GAAG;EAC9B,YAAY,OAAO,SAAS;GAC1B,IAAI;IACF,OAAO,MAAM,SAAS,WAAW,IAAI,IAAI,OAAO,KAAK,KAAK,IAAI,CAAC;GACjE,QAAQ;IACN;GACF;EACF;CACF;AACF;AAEA,eAAe,UAAU,MAAc,UAAqC;CAC1E,MAAM,MAAgB,CAAC;CACvB,MAAM,OAAO,OAAO,KAAa,UAAiC;EAChE,IAAI,QAAQ,GACV;EAEF,IAAI;EACJ,IAAI;GACF,UAAU,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;EACtD,QAAQ;GACN;EACF;EACA,MAAM,SAA0B,CAAC;EACjC,KAAK,MAAM,SAAS,SAAS;GAC3B,IAAI,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,SAAS,WAC/C;GAEF,MAAM,OAAO,KAAK,KAAK,MAAM,IAAI;GACjC,IAAI,MAAM,YAAY,GAAG;IACvB,IAAI,UAAU,IAAI,MAAM,IAAI,GAC1B;IAEF,OAAO,KAAK,KAAK,MAAM,QAAQ,CAAC,CAAC;GACnC,OACE,IAAI,KAAK,IAAI;EAEjB;EACA,MAAM,QAAQ,IAAI,MAAM;CAC1B;CACA,MAAM,KAAK,MAAM,QAAQ;CACzB,OAAO;AACT;AAEA,eAAe,UAAU,KAA0C;CACjE,IAAI;EACF,MAAM,EAAE,WAAW,MAAM,cAAc,OAAO;GAAC;GAAU;GAAW;EAAQ,GAAG,EAAE,IAAI,CAAC;EACtF,OAAO,gBAAgB,OAAO,KAAK,CAAC;CACtC,SAAS,OAAO;EACd,IAAI,iBAAiB,OACnB;EAEF,MAAM;CACR;AACF;;;;AC/DA,eAAsB,QAAQ,SAA2C;CACvE,MAAM,YAAY,MAAM,YAAY,QAAQ,GAAG;CAC/C,MAAM,WAAW,KAAK,QAAQ,KAAK,WAAW;CAC9C,MAAM,YAAY,KAAK,UAAU,YAAY;CAC7C,MAAM,aAAa,KAAK,UAAU,aAAa;CAE/C,IAAI,CAAC,QAAQ,UAAU,WAAW,SAAS,KAAK,WAAW,UAAU,IACnE,MAAM,IAAI,cACR,eACA,uDACA,8DACF;CAGF,IAAI,CAAC,QAAQ,KAEX;MAAI,CAAC,MADkB,YAAY,SAAS,GAE1C,MAAM,IAAI,cACR,kBACA,0CACA,uEACF;CACF;CAGF,MAAM,QAAQ,YAAY,MAAM,UAAU,KAAK;CAC/C,MAAM,SAAS,aAAa,MAAM,cAAc;CAChD,MAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;CACzC,MAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,KAAK,MAAM;CACxE,MAAM,UAAU,YAAY,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK,MAAM;CAC1E,MAAM,gBAAgB,QAAQ,GAAG;CAEjC,MAAM,YAAY,KAAK,UAAU,UAAU,QAAQ;CACnD,MAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;CAC1C,MAAM,aAAa,KAAK,WAAW,qBAAqB;CACxD,MAAM,WAAW,MAAM,qBAAqB;CAI5C,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,aAAa;EAAE,QAAQ;EAAkB,KAAK;EAAwB;CAAU;CACtF,MAAM,cAAqB,EACzB,SAAS,EAAE,MAAM,KAAK,MAAM,MAAM,UAAU,EAAE,EAChD;CACA,IAAI,MAAM,YAAY,QACpB,YAAY,QAAQ,UAAU,KAAK,MAAM,SAAS,UAAU;CAE9D,IAAI,MAAM,QAAQ,QAChB,YAAY,QAAQ,MAAM,KAAK,MAAM,KAAK,UAAU;CAatD,MAAM,SAAQ,MAXO,SAAS;EAC5B,OAAO;GAAE,MAAM;GAAW,KAAK;EAAS;EACxC,OAAO;EACP;EACA,QAAQ;GAAE,GAAG;GAAQ,SAAS,CAAC,IAAI;GAAG,SAAS;IAAE,GAAG,OAAO;IAAS,WAAW,CAAC,cAAc;GAAE;EAAE;EAClG,MAAM,kBAAkB,WAAW;EACnC,UAAU;EACV;EACA,QAAQ,CAAC,MAAM,KAAK;EACpB,aAAa;CACf,CAAC,EACmB,CAAC,MAAM;CAC3B,IAAI,UAAU,QACZ,MAAM,IAAI,cACR,sBACA,qCACA,sDACF;CAEF,MAAM,UAAU,YAAY,MAAM,KAAK;CAEvC,OAAO;EAAE;EAAW;EAAY;EAAY;CAAU;AACxD;AAEA,eAAe,YAAY,WAA6C;CACtE,IAAI,CAACC,MAAM,OACT,MAAM,IAAI,cACR,mBACA,4DACA,iEACF;CAEF,OAAO,MAAM,mBAAmB;CAChC,KAAK,MAAM,SAAS,UAAU,SAC5B,OAAO,MAAM,KAAK,MAAM,MAAM,SAAS,MAAM,OAAO,GAAG;CAEzD,KAAK,MAAM,QAAQ,UAAU,OAC3B,OAAO,MAAM,WAAW,KAAK,GAAG;CAElC,MAAM,KAAK,gBAAgB;EAAE;EAAO;CAAO,CAAC;CAC5C,IAAI;EACF,MAAM,SAAS,MAAM,GAAG,SAAS,oDAAoD;EACrF,OAAO,OAAO,KAAK,CAAC,CAAC,YAAY,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC,YAAY,MAAM;CAChF,UAAU;EACR,GAAG,MAAM;CACX;AACF;AAEA,eAAe,gBAAgB,KAA4B;CACzD,MAAM,OAAO,KAAK,KAAK,YAAY;CACnC,MAAM,QAAQ;CACd,IAAI,CAAC,WAAW,IAAI,GAAG;EACrB,MAAM,UAAU,MAAM,GAAG,MAAM,KAAK,MAAM;EAC1C;CACF;CACA,MAAM,UAAU,MAAM,SAAS,MAAM,MAAM;CAC3C,IAAI,QAAQ,MAAM,OAAO,CAAC,CAAC,MAAM,SAAS,KAAK,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,kBAAkB,GACnG;CAEF,MAAM,SAAS,QAAQ,SAAS,IAAI,KAAK,QAAQ,WAAW,IAAI,KAAK;CACrE,MAAM,UAAU,MAAM,GAAG,UAAU,SAAS,MAAM,KAAK,MAAM;AAC/D;;;;AClGA,eAAsB,aAAa,OAAiD;CAClF,MAAM,MAAM,MAAM;CAClB,MAAM,SAAS,eAAe,MAAM,WAAW,GAAG,GAAG,KAAK;CAC1D,MAAM,QAAQ,MAAM,UAAU,GAAG;CACjC,MAAM,cAA6B;EAAE,MAAM;EAAa,QAAQ;EAAS,WAAW;CAAE;CACtF,MAAM,MAAM,WAAW,KAAK;CAC5B,MAAM,cAAkD;EACtD;EACA,OAAO;EACP,aAAa,IAAI;CACnB;CACA,IAAI,IAAI,gBAAgB,QACtB,YAAY,cAAc,IAAI;CAEhC,IAAI,IAAI,gBAAgB,QACtB,YAAY,cAAc,IAAI;CAEhC,IAAI,IAAI,cAAc,QACpB,YAAY,YAAY,IAAI;CAE9B,MAAM,YAAY,MAAM,aAAa,WAAW;CAChD,MAAM,WAAW,gBAAgB,WAAW,QAAQ,YAAY,MAAM,MAAM,GAAG,eAAe,MAAM,SAAS,CAAC;CAC9G,IAAI,aAAa,QACf,OAAO;EACL,QAAQ,MAAM,WAAW;EACzB,SAAS;EACT,SAAS;EACT,OAAO;EACP,UAAU,CAAC;EACX,UAAU;CACZ;CAGF,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,YAAY,SAAS,WAAW,cAAc,cAAc,SAAS;CAC3E,MAAM,QAAe;EACnB,GAAG;EACH,WAAW;GACT,QAAQ,KAAK,SAAS,QAAQ;IAAE,QAAQ;IAAe,KAAK;IAA+B;GAAU,CAAC;GACtG,WAAW,KAAK,SAAS,WAAW;IAClC,QAAQ;IACR,KAAK,0BAA0B;IAC/B;GACF,CAAC;EACH;CACF;CACA,MAAM,QAAuB;EAAE,MAAM;EAAa,QAAQ,SAAS;EAAQ,WAAW,SAAS;CAAU;CACzG,MAAM,WAAW,cAAc,OAAO,SAAS,QAAQ,SAAS,SAAS;CACzE,MAAM,WAAW,MAAM,YAAY,OAAO,QAAQ,MAAM,SAAS,OAAO,QAAQ;CAEhF,IAAI,MAAM,WAAW,MAAM;EACzB,MAAM,MAAuB;GAC3B,QAAQ;GACR,SAAS;GACT;GACA,MAAM,SAAS;GACf,UAAU,SAAS;GACnB,UAAU,CAAC;GACX,UAAU;EACZ;EACA,IAAI,SAAS,YAAY,QACvB,IAAI,cAAc,SAAS;EAE7B,OAAO;CACT;CAEA,MAAM,WAAW,MAAM,qBAAqB;CAC5C,MAAM,gBAAgD;EACpD;EACA;EACA;EACA;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;EACA,QAAQ,cAAc,MAAM,QAAQ,MAAM,KAAK;EAC/C,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACtC;CACA,MAAM,QAAQ,MAAM,UAAU,KAAK,KAAK;CACxC,IAAI,UAAU,QACZ,cAAc,QAAQ;CAGxB,MAAM,YAA8C;EAClD;EACA;EACA;EACA,cALmB,SAAS,aAAa;EAMzC;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;CACF;CACA,IAAI,SAAS,YAAY,QACvB,UAAU,cAAc,SAAS;CAGnC,OAAO;EAAE,GAAG,MADS,WAAW,SAAS;EACrB,SAAS;CAAM;AACrC;AAEA,SAAgB,eAAe,YAAsB,SAAqC;CAExF,OADgB,WAAW,QAAQ,SAAS,WAAW,IAAI,CAAC,CAAC,UAAU,GAAG,MAAM,IAAI,CACvE,CAAC,CAAC;AACjB;AAEA,SAAgB,gBACd,OACA,QACA,QACA,WAC4D;CAC5D,MAAM,UAA6B,WAAW,SAAY;EAAC;EAAS;EAAa;CAAc,IAAI,CAAC,MAAM;CAC1G,MAAM,aAAoE,CAAC;CAC3E,KAAK,MAAM,QAAQ,SAAS;EAC1B,MAAM,UAAU,aAAa,OAAO,IAAI;EACxC,IAAI,YAAY,QAAW;GACzB,IAAI,WAAW,QACb,MAAM,cAAc,IAAI;GAE1B;EACF;EACA,MAAM,OAAO,cAAc,QAAQ,IAAI;EACvC,IAAI,cAAc,QAAW;GAC3B,IAAI,WAAW,UAAa,KAAK,SAAS,SAAS,GACjD,OAAO;IAAE,QAAQ;IAAM;GAAU;GAEnC;EACF;EACA,MAAM,UAAU,eAAe,MAAM,OAAO;EAC5C,IAAI,YAAY,QACd,WAAW,KAAK;GAAE,QAAQ;GAAM,WAAW;EAAQ,CAAC;CAExD;CACA,OAAO,WAAW,UACf,GAAG,MAAM,EAAE,YAAY,EAAE,aAAa,QAAQ,QAAQ,EAAE,MAAM,IAAI,QAAQ,QAAQ,EAAE,MAAM,CAC7F,CAAC,CAAC;AACJ;AAEA,SAAS,aAAa,OAAc,QAA6C;CAC/E,IAAI,WAAW,SACb,OAAO,MAAM,SAAS,OAAO;CAE/B,IAAI,WAAW,aACb,OAAO,MAAM,SAAS,iBAAiB;CAEzC,OAAO,MAAM,SAAS,kBAAkB;AAC1C;AAEA,SAAS,cAAc,QAAgB,QAAmC;CACxE,IAAI,WAAW,SACb,OAAO,OAAO,YAAY,SAAS,CAAC;CAEtC,IAAI,WAAW,aACb,OAAO,OAAO,YAAY,aAAa,CAAC;CAE1C,OAAO,OAAO,YAAY,gBAAgB,CAAC;AAC7C;AAEA,SAAS,YAAY,OAAwD;CAC3E,IAAI,UAAU,QACZ;CAEF,IAAI,UAAU,WAAW,UAAU,eAAe,UAAU,gBAC1D,OAAO;CAET,MAAM,IAAI,cACR,wBACA,mBAAmB,MAAM,KACzB,mEACF;AACF;AAEA,SAAS,eAAe,OAA+C;CACrE,IAAI,UAAU,QACZ;CAEF,MAAM,SAAS,OAAO,SAAS,OAAO,EAAE;CACxC,IAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GACzC,MAAM,IAAI,cACR,2BACA,sBAAsB,MAAM,KAC5B,wDACF;CAEF,OAAO;AACT;AAEA,SAAS,cAAc,QAAwC;CAC7D,IAAI,WAAW,SACb,OAAO,IAAI,cACT,2BACA,8CACA,sFACF;CAEF,IAAI,WAAW,aACb,OAAO,IAAI,cACT,+BACA,yDACA,8EACF;CAEF,OAAO,IAAI,cACT,kCACA,8DACA,sFACF;AACF;;;;;AC5NA,MAAM,iBAAiB;CAAC;CAAS;CAAS;AAAO;AAgBjD,eAAsB,WAAW,OAA6C;CAC5E,MAAM,MAAM,MAAM;CAClB,MAAM,SAAS,qBAAqB,MAAM,WAAW,GAAG,GAAG,KAAK;CAChE,MAAM,QAAQ,MAAM,UAAU,GAAG;CACjC,MAAM,MAAM,MAAM,OAAQ,MAAM,cAAc,GAAG;CACjD,IAAI,QAAQ,QACV,MAAM,IAAI,cACR,kBACA,sCACA,yCACF;CAEF,MAAM,QACJ,MAAM,SAAS,SACX;EAAE,MAAM;EAAW;CAAI,IACvB;EAAE,MAAM;EAAW;EAAK,aAAa,MAAM;CAAK;CAEtD,MAAM,MAAM,WAAW,KAAK;CAC5B,MAAM,cAAkD;EACtD;EACA;EACA,aAAa,IAAI;CACnB;CACA,IAAI,IAAI,gBAAgB,QACtB,YAAY,cAAc,IAAI;CAEhC,IAAI,OAAO,SAAS,kBAAkB,QACpC,YAAY,gBAAgB,OAAO,QAAQ;CAE7C,IAAI,OAAO,SAAS,YAAY,QAC9B,YAAY,UAAU,OAAO,QAAQ;CAEvC,IAAI,IAAI,gBAAgB,QACtB,YAAY,cAAc,IAAI;CAEhC,IAAI,IAAI,cAAc,QACpB,YAAY,YAAY,IAAI;CAE9B,MAAM,WAAW,MAAM,YAAY,OAAO,SAAS,YAAY;CAC/D,IAAI,aAAa,QACf,YAAY,WAAW;CAEzB,MAAM,cAAc,MAAM,eAAe,OAAO,SAAS,eAAe;CACxE,IAAI,gBAAgB,QAClB,YAAY,cAAc;CAE5B,MAAM,QAAQ,MAAM,aAAa,WAAW;CAI5C,MAAM,WAAW,OAAO,SAAS,YAAY;CAC7C,MAAM,OAAO,MAAM,SAAS,MAAM;CAClC,IAAI,SAAS,UAAa,eAAe,QAAQ,IAAI,IAAI,eAAe,QAAQ,QAAQ,GACtF,OAAO;EACL,QAAQ,MAAM,WAAW;EACzB,SAAS;EACT,SAAS,aAAa,KAAK,oCAAoC,SAAS;EACxE;EACA,MAAM,kBAAkB,OAAO,OAAO,SAAS,eAAe,MAAM,IAAI;EACxE,UAAU;EACV,UAAU,CAAC;EACX,UAAU;CACZ;CAGF,MAAM,SAAS,MAAM,SAAS;CAC9B,MAAM,WAAW,MAAM,YAAY,OAAO,QAAQ,QAAQ,kBAAkB,OAAO,OAAO,SAAS,eAAe,MAAM,IAAI,CAAC;CAE7H,IAAI,MAAM,WAAW,MAAM;EACzB,MAAM,MAAqB;GACzB,QAAQ;GACR;GACA,MAAM,SAAS;GACf,UAAU,SAAS;GACnB,UAAU,CAAC;GACX,UAAU;EACZ;EACA,IAAI,SAAS,YAAY,QACvB,IAAI,cAAc,SAAS;EAE7B,OAAO;CACT;CAEA,MAAM,WAAW,MAAM,qBAAqB;CAC5C,MAAM,gBAAgD;EACpD;EACA;EACA;EACA;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;EACA,QAAQ,cAAc,MAAM,QAAQ,MAAM,KAAK;EAC/C,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACtC;CACA,MAAM,QAAQ,MAAM,UAAU,KAAK,KAAK;CACxC,IAAI,UAAU,QACZ,cAAc,QAAQ;CAGxB,MAAM,YAA8C;EAClD;EACA;EACA;EACA,cALmB,SAAS,aAAa;EAMzC;EACA,MAAM,SAAS;EACf,UAAU,SAAS;EACnB;CACF;CACA,IAAI,SAAS,YAAY,QACvB,UAAU,cAAc,SAAS;CAEnC,OAAO,WAAW,SAAS;AAC7B;AAEA,SAAS,qBAAqB,QAAgB,OAA6B;CACzE,MAAM,UAAU,eAAe,QAAQ,KAAK;CAC5C,IAAI,MAAM,cAAc,QACtB,OAAO;CAET,OAAO,YAAY,gBAAgB;EACjC,GAAG;EACH,SAAS;GACP,GAAG,QAAQ;GACX,WAAW,MAAM,UACd,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,QAAQ,SAAS,KAAK,SAAS,CAAC;EACrC;CACF,CAAC;AACH;;;;ACrKA,MAAM,uBAAuB;AAC7B,MAAMC,kBAAgB;AAEtB,SAAgB,WACd,OACA,QACA,OACA,aACO;CACP,MAAM,UAAU,MAAM;CACtB,IAAI,YAAY,QACd,MAAM,IAAI,cACR,oBACA,+CACA,iEACF;CAEF,MAAM,OAAO,kBAAkB,OAAO,OAAO,SAAS,eAAe,MAAM,IAAI;CAC/E,MAAM,cAAc,OAAe,QACjC,KAAK,OAAO;EAAE,QAAQ;EAAe;EAAK,WAAW;CAAY,CAAC;CAEpE,MAAM,UAAU;EAAC,GAAG,QAAQ;EAAU,GAAG,QAAQ;EAAU,GAAG,QAAQ;CAAK;CAG3E,MAAM,iBACJ,QAAQ,YACR,QAAQ,MAAM,SAAS,UAAU,cAAc,KAAK,KAAK,CAAC,MAAM,KAAK,QAAQ,KAC7E,QAAQ;CACV,MAAM,QAAqB,CACzB;EACE,MAAM;EACN,OAAO,KAAK,KAAK,UAAU,eAAe,UAAU;EAGpD,MACE,QAAQ,eACR,MAAM,QAAQ,YACb,MAAM,YAAY,SACf,KAAK,iBAAiB,QAAQ,IAAI,UAAU,IAC5C,KAAK,MAAM,SAAS;GAClB,QAAQ;GACR,KAAK;GACL,WAAW;EACb,CAAC;CACT,CACF;CAEA,KAAK,MAAM,QAAQ,QAAQ,MAAM,GAAG,OAAO,SAAS,iBAAiB,oBAAoB,GAAG;EAG1F,MAAM,YAAY,KAAK,MAAM,WAAW,QAAQ,GAAG,CAAC,CAAC,KAAK;EAC1D,MAAM,WAAW,cAAc,SAAS;EACxC,MAAM,YAAY,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,KAAK;EACxD,MAAM,KAAK;GACT,MAAM;GACN,OAAO,KAAK,UAAU,QAAQ,GAAG,KAAK,UAAU;GAChD,MAAM,KAAK,UAAU,SAAS,IAAI,UAAU,SAAS,IAAI,IAAI,KAAK,UAAU;EAC9E,CAAC;CACH;CAEA,IAAI,QAAQ,gBAAgB,QAC1B,MAAM,KAAK;EACT,MAAM;EACN,OAAO,KAAK,gBAAgB,QAAQ,YAAY,UAAU;EAC1D,MAAM,KAAK,QAAQ,YAAY,MAAM,MAAM,QAAQ,YAAY,UAAU;CAC3E,CAAC;CAGH,MAAM,UAAU,OAAO,SAAS;CAChC,IAAI,SAAS,WAAW,UAAa,QAAQ,UAAU,QACrD,MAAM,KAAK;EACT,MAAM;EACN,OAAO,WAAW,oBAAoB,4CAA4C;EAClF,MAAM,WAAW,wBAAwB,eAAe;EACxD,QAAQ,WAAW,QAAQ,QAAQ,sBAAsB;EACzD,OAAO,WAAW,QAAQ,OAAO,qBAAqB;CACxD,CAAC;CAGH,MAAM,aAAa,SAAS,YAAY,UAAa,QAAQ,QAAQ,KAAK,CAAC,CAAC,SAAS;CACrF,IAAI;CACJ,IAAI,cAAc,SAAS,YAAY,QAIrC,UAAU,WAAW,QAAQ,QAAQ,KAAK,GAAG,uBAAuB;MAC/D;EAGL,MAAM,OAAO,MAAM,QAAQ;EAC3B,UACE,SAAS,SACL,KAAK,KAAK,KAAK,MAAM,QAAQ,KAAK,cAAc,MAAM,QAAQ,KAAK,UAAU,IAC7E,KACE,wCAAwC,KAAK,MAAM,gBAAgB,mBAAmB,QAAQ,IAAI,KAAK,KACvG,KAAK,UACP;CACR;CACA,MAAM,KAAK;EACT,MAAM;EACN,OAAO,KAAK,aAAa,mBAAmB,mBAAmB,QAAQ,UAAU;EACjF,MAAM;CACR,CAAC;CAED,OAAO;EAAE,GAAG;EAAO,OAAO;CAAM;AAClC;AAEA,eAAsB,cAAc,OAA+C;CACjF,MAAM,QAAQ,WAAW,MAAM,OAAO,MAAM,QAAQ,MAAM,OAAO,MAAM,WAAW;CAClF,MAAM,QAAQ,MAAM,SAAS,CAAC;CAC9B,MAAM,SAAyB;EAC7B,OAAO,CAAC;EACR,UAAU,CAAC;EACX,SAAS,CAAC;EACV;EACA,MAAM,MAAM;EACZ,UAAU;EACV,aAAa,MAAM;EACnB,UAAU,CAAC;CACb;CACA,MAAM,UAAU,MAAM,OAAO,WAAW,CAAC,UAAU;CACnD,IAAI,QAAQ,WAAW,KAAK,QAAQ,SAAS,eAAe,GAC1D,MAAM,IAAI,cACR,oBACA,sFACA,OAAOA,gBAAc,EACvB;CAGF,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,QAAQ,GAAG;EAG3C,MAAM,WAAW,MAAM,SAAS;GAC9B,GAAG;GACH,OAAO;IAAE,GAAG;IAAO,OAAO,CAAC,IAAI;GAAE;GACjC,QAAQ;IACN,GAAG,MAAM;IACT;IACA,SAAS;KAAE,GAAG,MAAM,OAAO;KAAS,WAAW,CAAC,YAAY;IAAE;GAChE;EACF,CAAC;EACD,MAAM,KAAK,SAAS,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,KAAK;EAC/D,OAAO,MAAM,KACX,GAAG,SAAS,MAAM,KAAK,UAAU;GAC/B,GAAG;GACH,UAAU,KAAK,SAAS,QAAQ,cAAc,EAAE;EAClD,EAAE,CACJ;EACA,OAAO,SAAS,KACd,GAAG,SAAS,SAAS,KAAK,aAAa;GACrC,GAAG;GACH,MAAM,QAAQ,OAAO,QAAQ,CAAC,EAAE,GAAG,QAAQ;EAC7C,EAAE,CACJ;EACA,OAAO,QAAQ,KAAK,GAAG,SAAS,OAAO;EACvC,OAAO,SAAS,eAAe,OAAO,KAAK,EAAE,MAAM;GACjD,OAAO;IACL,MAAM,KAAK;IACX,OAAO,OAAO,MACX,QAAQ,SAAS,KAAK,SAAS,WAAW,EAAE,CAAC,CAAC,CAC9C,KAAK,SAAS,KAAK,QAAQ;GAChC;GACA,cAAc,CAAC,SAAS,OAAO,KAAK,EAAE,UAAU,SAAS,OAAO,KAAK,EAAE,OAAO;EAChF;CACF;CAEA,IAAI,MAAM,SAAS,gBAAgB,QACjC,OAAO,QAAQ,KAAK;EAClB,UAAU;EACV,MAAM;EACN,QAAQ;CACV,CAAC;CAEH,IAAI,MAAM,OAAO,SAAS,KAAK,SAAS,QAAQ,GAC9C,OAAO,QAAQ,KAAK;EAClB,UAAU;EACV,MAAM;EACN,QAAQ;CACV,CAAC;CAEH,OAAO;AACT;;;;AC5LA,MAAM,UAAU,UAA8B,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK;AAE5E,MAAM,UAAU,UAA+B,MAAM,OAAO,OAAO,MAAM,OAAO;AAEhF,SAAgB,UAAU,OAAiC;CACzD,MAAM,SAAS,IAAI,WAAW,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,QAAQ,CAAC,CAAC;CAC/E,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,OAAO;EACxB,OAAO,IAAI,MAAM,MAAM;EACvB,UAAU,KAAK;CACjB;CACA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,YACd,OACY;CACZ,IAAI,MAAM,WAAW,KAAK,MAAM,MAAM,SAAS,CAAC,OAAO,KAAK,KAAK,CAAC,GAChE,MAAM,IAAI,cACR,qBACA,4CACA,mDACF;CAEF,MAAM,UAAwB,CAC5B,OAAO,mCAAmC,GAC1C,OACE,0BAA0B,OAAO,MAAM,MAAM,EAAE,UAAU,MACtD,KAAK,GAAG,UAAU,GAAG,OAAO,IAAI,QAAQ,CAAC,EAAE,KAAK,CAAC,CACjD,KAAK,GAAG,EAAE,KACf,CACF;CACA,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,QAAQ,GAAG;EAC3C,MAAM,KAAK,IAAI,QAAQ;EACvB,MAAM,QAAQ,KAAK,QAAQ;EAC3B,MAAM,SAAS,KAAK,SAAS;EAC7B,QAAQ,KACN,OACE,+CAA+C,OAAO,KAAK,EAAE,GAAG,OAAO,MAAM,EAAE,qCACzC,OAAO,KAAK,CAAC,EAAE,uBACtC,OAAO,KAAK,CAAC,EAAE,QAChC,CACF;EAEA,QAAQ,KACN,UAAU;GACR,OACE,4CAA4C,OAAO,KAAK,KAAK,EAAE,WAClD,OAAO,KAAK,MAAM,EAAE,yEACD,OAAO,KAAK,MAAM,MAAM,EAAE,cAC5D;GACA,KAAK;GACL,OAAO,aAAa;EACtB,CAAC,CACH;EACA,MAAM,UAAU,KAAK,OAAO,KAAK,EAAE,OAAO,OAAO,MAAM,EAAE;EACzD,QAAQ,KACN,OAAO,cAAc,OAAO,OAAO,OAAO,CAAC,CAAC,MAAM,EAAE,eAAe,QAAQ,YAAY,CACzF;CACF;CAEA,MAAM,SAAS,OAAO,uBAAuB;CAC7C,MAAM,QAAsB,CAAC,MAAM;CACnC,MAAM,UAAoB,CAAC;CAC3B,IAAI,WAAW,OAAO;CACtB,KAAK,MAAM,CAAC,OAAO,WAAW,QAAQ,QAAQ,GAAG;EAC/C,QAAQ,KAAK,QAAQ;EACrB,MAAM,QAAQ,UAAU;GAAC,OAAO,GAAG,OAAO,QAAQ,CAAC,EAAE,SAAS;GAAG;GAAQ,OAAO,YAAY;EAAC,CAAC;EAC9F,MAAM,KAAK,KAAK;EAChB,YAAY,MAAM;CACpB;CACA,MAAM,OAAO,QAAQ,SAAS;CAC9B,MAAM,KACJ,OACE,WAAW,OAAO,IAAI,EAAE,2BACtB,QAAQ,KAAK,WAAW,GAAG,OAAO,MAAM,CAAC,CAAC,SAAS,IAAI,GAAG,EAAE,YAAY,CAAC,CAAC,KAAK,EAAE,IACjF,qBAAqB,OAAO,IAAI,EAAE,8BACpB,OAAO,QAAQ,EAAE,UACnC,CACF;CACA,OAAO,UAAU,KAAK;AACxB;AAEA,SAAS,MAAM,OAA2B;CACxC,IAAI,QAAQ;CACZ,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAS;EACT,KAAK,IAAI,MAAM,GAAG,MAAM,GAAG,OAAO,GAChC,QAAS,UAAU,MAAO,QAAQ,OAAO,IAAI,aAAa;CAE9D;CACA,QAAQ,QAAQ,gBAAgB;AAClC;;;;;;AAOA,SAAgB,SAAS,OAA+D;CACtF,MAAM,iBAAiB;CACvB,MAAM,wBAAQ,IAAI,IAAY;CAC9B,MAAM,QAAsB,CAAC;CAC7B,MAAM,UAAwB,CAAC;CAC/B,IAAI,SAAS;CAEb,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,CAAC,oBAAoB,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,IAAI,GAC7D,MAAM,IAAI,cACR,gBACA,iDACA,gDACF;EAEF,MAAM,IAAI,KAAK,IAAI;EACnB,MAAM,OAAO,OAAO,KAAK,IAAI;EAC7B,MAAM,WAAW,MAAM,KAAK,KAAK;EAIjC,MAAM,yBAAS,IAAI,WAAW,EAAE;EAChC,MAAM,aAAa,IAAI,SAAS,OAAO,MAAM;EAC7C,WAAW,UAAU,GAAG,UAAY,IAAI;EACxC,WAAW,UAAU,GAAG,IAAI,IAAI;EAChC,WAAW,UAAU,IAAI,gBAAgB,IAAI;EAC7C,WAAW,UAAU,IAAI,UAAU,IAAI;EACvC,WAAW,UAAU,IAAI,KAAK,MAAM,QAAQ,IAAI;EAChD,WAAW,UAAU,IAAI,KAAK,MAAM,QAAQ,IAAI;EAChD,WAAW,UAAU,IAAI,KAAK,QAAQ,IAAI;EAC1C,MAAM,KAAK,QAAQ,MAAM,KAAK,KAAK;EAGnC,MAAM,wBAAQ,IAAI,WAAW,EAAE;EAC/B,MAAM,YAAY,IAAI,SAAS,MAAM,MAAM;EAC3C,UAAU,UAAU,GAAG,UAAY,IAAI;EACvC,UAAU,UAAU,GAAG,IAAI,IAAI;EAC/B,UAAU,UAAU,GAAG,IAAI,IAAI;EAC/B,UAAU,UAAU,IAAI,gBAAgB,IAAI;EAC5C,UAAU,UAAU,IAAI,UAAU,IAAI;EACtC,UAAU,UAAU,IAAI,KAAK,MAAM,QAAQ,IAAI;EAC/C,UAAU,UAAU,IAAI,KAAK,MAAM,QAAQ,IAAI;EAC/C,UAAU,UAAU,IAAI,KAAK,QAAQ,IAAI;EACzC,UAAU,UAAU,IAAI,QAAQ,IAAI;EACpC,QAAQ,KAAK,OAAO,IAAI;EACxB,UAAU,OAAO,SAAS,KAAK,SAAS,KAAK,MAAM;CACrD;CAGA,MAAM,sBAAM,IAAI,WAAW,EAAE;CAC7B,MAAM,UAAU,IAAI,SAAS,IAAI,MAAM;CACvC,QAAQ,UAAU,GAAG,WAAY,IAAI;CACrC,QAAQ,UAAU,GAAG,MAAM,QAAQ,IAAI;CACvC,QAAQ,UAAU,IAAI,MAAM,QAAQ,IAAI;CACxC,QAAQ,UAAU,IAAI,QAAQ,QAAQ,KAAK,SAAS,MAAM,KAAK,QAAQ,CAAC,GAAG,IAAI;CAC/E,QAAQ,UAAU,IAAI,QAAQ,IAAI;CAClC,OAAO,UAAU;EAAC,GAAG;EAAO,GAAG;EAAS;CAAG,CAAC;AAC9C;;;;;ACzJA,MAAM,gBAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,cAAc,UAClB,IAAI,YAAY,CAAC,CAAC,OAAO,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,GAAG;AAEhE,MAAa,kBAAkB,EAC5B,OAAO;CACN,MAAM,EAAE,KAAK,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,QAAQ,OAAO;CAClD,OAAO,YAAY,MAAM;CACzB,OAAO,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC;CAC/B,QAAQ,YAAY,MAAM,OAAO,MAAM;CACvC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE;CACxC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,GAAI,CAAC,CAAC,QAAQ,EAAE;CACxC,QAAQ,EACL,KAAK,CAAC,GAAG,eAAe,KAAK,CAAC,CAAC,CAC/B,QAAQ,UAAU;AACvB,CAAC,CAAC,CACD,OAAO;AAGV,SAAgB,eAAe,QAAgB,WAAoC;CACjF,MAAM,UACJ,UAAU,WAAW,QACjB,UAAU,SAAS,UACjB,CAAC,GAAG,aAAa,IACjB,CAAC,GAAG,aAAa,IACnB,CAAC,UAAU,MAAM;CACvB,MAAM,YAAY,IAAI,IAAY,aAAa;CAC/C,IAAI,UAAU,SAAS,aAAa,QAAQ,MAAM,WAAW,CAAC,UAAU,IAAI,MAAM,CAAC,GACjF,MAAM,IAAI,cACR,kBACA,8DACA,sDACF;CAEF,OAAO;EACL,GAAG;EACH;EACA,SAAS;GACP,GAAG,OAAO;GACV,UAAU,UAAU,YAAY;GAChC,OAAO;IAAE,GAAG,OAAO,SAAS;IAAO,SAAS,UAAU;GAAQ;EAChE;EACA,QAAQ,EAAE,aAAa,MAAM;CAC/B;AACF;AAEA,SAAgB,cAAc,OAAc,WAAmC;CAG7E,OAAO;EACL,GAAG;EACH,OAAO,UAAU;EACjB,QAAQ;GAAE,GAAG,MAAM;GAAQ,SAAS,UAAU;EAAO;CACvD;AACF;AAEA,eAAsB,gBAAgB,OAWnC;CACD,MAAM,UAAU,MAAM,MAAM;CAC5B,IAAI,YAAY,QACd,MAAM,IAAI,cACR,sBACA,2BACA,kCACF;CAEF,MAAM,SAAS,eAAe,MAAM,QAAQ,MAAM,SAAS;CAC3D,MAAM,QAAQ,cAAc,MAAM,OAAO,MAAM,SAAS;CACxD,MAAM,QAAe;EAAE,GAAG,MAAM;EAAO,SAAS,EAAE,GAAG,QAAQ;CAAE;CAC/D,IAAI,MAAM,UAAU,UAClB,MAAM,UAAU;EACd,GAAG;EACH,UAAU,KAAK,MAAM,UAAU,UAAU;GACvC,QAAQ;GACR,KAAK;GACL,WAAW,MAAM;EACnB,CAAC;CACH;CAGF,MAAM,QAAQ;EAAE,MAAM;EAAoB,KAAK,QAAQ,IAAI;CAAM;CACjE,MAAM,UAAyB;EAC7B;EACA;EACA;EACA;EACA,MAAM,kBAAkB,OAAO,OAAO,SAAS,eAAe,MAAM,IAAI;EACxE,UAAU;EACV,UAAU,MAAM;EAChB,QAAQ,CAAC,MAAM,UAAU,KAAK;EAC9B,aAAa,MAAM;CACrB;CACA,IAAI,MAAM,UAAU,QAClB,QAAQ,QAAQ,MAAM;CAExB,IAAI,MAAM,WAAW,QACnB,QAAQ,SAAS,MAAM;CAGzB,MAAM,SAAS,OAAO,MAAM,UAAU,SAAS,UAAU,gBAAgB,SAAQ,CAAE,OAAO;CAC1F,MAAM,WAAW,cAAc;EAAE;EAAQ;EAAO;EAAO,iBAAiB,MAAM;CAAQ,CAAC;CACvF,SAAS,MAAM,SAAS,MAAM,eAAe;CAC7C,MAAM,YAAY,OAAO,MAAM,KAAK,UAAU;EAAE,MAAM,KAAK;EAAU,OAAO,KAAK;CAAM,EAAE;CAEzF,IAAI,MAAM,UAAU,SAAS,SAAS;EAGpC,MAAM,YAAY,OAAO,UAAU,MAAM;EACzC,MAAM,OAAO,MAAM,cAAc;GAC/B,GAAG;GACH,QAAQ;IAAE,GAAG;IAAQ,SAAS,CAAC,SAAS;IAAG,QAAQ,EAAE,aAAa,OAAO;GAAE;EAC7E,CAAC;EACD,MAAM,MAAM,YAAY,KAAK,KAAK;EAClC,UAAU,KAAK;GAAE,MAAM;GAAa,OAAO;EAAI,CAAC;EAChD,SAAS,SAAS,eAAe;GAC/B,OAAO;IAAE,QAAQ;IAAW,OAAO,KAAK,MAAM;IAAQ,OAAO,IAAI;GAAO;GACxE,cAAc,CAAC,OAAO;EACxB;CACF;CAEA,UAAU,KACR;EAAE,MAAM;EAAc,OAAO,WAAW,KAAK;CAAE,GAC/C;EAAE,MAAM;EAAe,OAAO,WAAW,MAAM;CAAE,GACjD;EAAE,MAAM;EAAiB,OAAO,WAAW,QAAQ;CAAE,CACvD;CACA,OAAO;EAAE;EAAQ;EAAU;EAAW,SAAS,SAAS,SAAS;EAAG;EAAO;CAAO;AACpF;;;;ACnJA,MAAM,qBAAqB,CAAC,UAAU,OAAO;AAC7C,MAAM,wBAAwB;;;;;AAQ9B,eAAe,eAAe,KAAa,OAAe,MAAmC;CAC3F,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,SAAS,QAAQ,KAAK,IAAI,CAAC;CAC1C,SAAS,OAAO;EACd,MAAM,IAAI,cACR,uBACA,sBAAsB,MAAM,eAAe,KAAK,IAChD,mFACA,EAAE,OAAO,MAAM,CACjB;CACF;CACA,MAAM,MAAM,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO;CAC/E,MAAM,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO;CAC5C,IAAK,CAAC,OAAO,CAAC,QAAS,KAAK,SAAS,uBACnC,MAAM,IAAI,cACR,uBACA,OAAO,MAAM,kEACb,sCACF;CAEF,OAAO;EAAE,KAAK,SAAS;EAAS;CAAK;AACvC;AAEA,eAAsB,gBAAgB,KAAa,QAAuC;CACxF,MAAM,aAAa,mBAAmB,SAAS,UAAU;EACvD,MAAM,OAAO,OAAO,SAAS,QAAQ;EACrC,OAAO,SAAS,SAAY,CAAC,IAAI,CAAC;GAAE;GAAO;EAAK,CAAC;CACnD,CAAC;CACD,OAAO,QAAQ,IAAI,WAAW,KAAK,UAAU,eAAe,KAAK,MAAM,OAAO,MAAM,IAAI,CAAC,CAAC;AAC5F;AAcA,eAAsB,SAAS,OAAmB;CAChD,MAAM,QAAQ,MAAM,UAAU,MAAM,GAAG;CACvC,MAAM,SAAS,MAAM,WAAW,MAAM,GAAG;CACzC,MAAM,MAAM,MAAM,OAAQ,MAAM,cAAc,MAAM,GAAG;CACvD,IAAI,QAAQ,QACV,MAAM,IAAI,cACR,gBACA,6BACA,0CACF;CAIF,MAAM,SAAS,gBAAgB,UAAU;EACvC,MAAM;EACN,OAAO,MAAM,SAAS,MAAM;EAC5B,OAAO,MAAM,SAAS,MAAM;EAC5B,QAAQ,MAAM,OAAO,WAAW;EAChC,UAAU,MAAM,YAAY,OAAO,SAAS,YAAY;EACxD,SAAS,OAAO,SAAS,OAAO,WAAW;EAC3C,QAAQ,MAAM,UAAU;CAC1B,CAAC;CACD,IAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC;EACpF,MAAM,IAAI,cACR,qBACA,sCAAsC,OAAO,KAAK,IAAI,EAAE,IACxD,qJACA,EAAE,OAAO,OAAO,MAAM,CACxB;CACF;CACA,MAAM,YAAY,OAAO;CAEzB,MAAM,iBAAqD;EACzD,KAAK,MAAM;EACX,OAAO;GAAE,MAAM;GAAW;EAAI;EAC9B,aAAa;CACf;CACA,IAAI,MAAM,YAAY,QACpB,eAAe,cAAc,MAAM;CAErC,IAAI,OAAO,SAAS,kBAAkB,QACpC,eAAe,gBAAgB,OAAO,QAAQ;CAEhD,IAAI,OAAO,SAAS,YAAY,QAC9B,eAAe,UAAU,OAAO,QAAQ;CAI1C,MAAM,QAA+C;EACnD,aAHkB,aAAa,cAAc;EAI7C;EACA;EACA;EACA,UAAU,MAAM,qBAAqB;EACrC,SAAS,oBAAoB;EAC7B,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;EACpC,QAAQ,MAAM,gBAAgB,MAAM,KAAK,MAAM;EAC/C,aAAa;CACf;CACA,MAAM,QAAQ,MAAM,UAAU,MAAM,KAAK,KAAK;CAC9C,IAAI,UAAU,QACZ,MAAM,QAAQ;CAEhB,MAAM,OAAO,MAAM,gBAAgB,KAAK;CAExC,MAAM,MAAM,QACV,MAAM,KACN,MAAM,OAAO,OAAO,aAAa,oBACjC,SAAS,IAAI,WAAW,oBAAoB,GAAG,GACjD;CACA,MAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;CACpC,MAAM,QAAQ,IAAI,KAAK,UAAU,KAAK,SAAS,UAAU,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC;CAC3F,MAAM,UAAU,KAAK,KAAK,WAAW,GAAG,KAAK,OAAO;CACpD,OAAO;EACL;EACA,UAAU,KAAK;EACf,UAAU,MAAM,WAAW,QAAQ,KAAK,SAAS,SAAS,SAAS,IAAI,IAAI;CAC7E;AACF;;;;;AChIA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;AAuBb,MAAM,eAAe;CACnB,gBAAgB;CAChB,iBAAiB;CACjB,mBAAmB;CACnB,2BACE;AACJ;AAEA,SAAS,KAAK,UAA0B,QAAgB,OAAsB;CAC5E,SAAS,UAAU,QAAQ;EACzB,gBAAgB;EAChB,iBAAiB;EACjB,0BAA0B;CAC5B,CAAC;CACD,SAAS,IAAI,KAAK,UAAU,KAAK,CAAC;AACpC;AAEA,eAAe,cAAc,SAA0B;CACrD,IAAI,OAAO;CACX,WAAW,MAAM,SAAS,SAAS;EACjC,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,MAAM,IAAI,cACR,gBACA,wCACA,qBACF;EAEF,QAAQ,MAAM,SAAS,MAAM;EAC7B,IAAI,KAAK,SAAS,OAChB,MAAM,IAAI,cACR,qBACA,qCACA,+CACF;CAEJ;CACA,IAAI;EACF,MAAM,MAAe,KAAK,MAAM,IAAI;EACpC,OAAO,gBAAgB,MAAM,GAAG;CAClC,SAAS,OAAO;EACd,MAAM,IAAI,cACR,qBACA,oCACA,oDACA,EAAE,OAAO,MAAM,CACjB;CACF;AACF;;AAGA,eAAe,YAAY,aAAqB,OAA+B;CAC7E,MAAM,YAAY,GAAG,YAAY,GAAG,WAAW,EAAE;CACjD,MAAM,UAAU,WAAW,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,KAAK,MAAM;CACxE,MAAM,OAAO,WAAW,WAAW;AACrC;AAEA,eAAsB,aAAa,SAKhC;CACD,MAAM,cAAc,QAAQ,OAAQ,MAAM,cAAc,QAAQ,GAAG;CACnE,IAAI,gBAAgB,QAClB,MAAM,IAAI,cACR,kBACA,6BACA,0CACF;CAGF,MAAM,MAAc;CAEpB,MAAM,UAAU,QAAQ,GAAG;CAC3B,MAAM,QAAQ,WAAW;CACzB,IAAI,SAAS;CAEb,eAAe,OAAO,SAA0B,UAAyC;EACvF,IAAI,QAAQ,QAAQ,SAAS,IAAI,IAAI,MAAM,CAAC,CAAC,MAAM;GACjD,KAAK,UAAU,KAAK,EAClB,OAAO,oEACT,CAAC;GACD;EACF;EACA,MAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,MAAM;EAC9C,IAAI,QAAQ,WAAW,SAAS,IAAI,aAAa,KAAK;GACpD,SAAS,UAAU,KAAK,YAAY;GACpC,SAAS,IAAI,IAAI;GACjB;EACF;EACA,IAAI,QAAQ,WAAW,SAAS,IAAI,aAAa,qBAAqB;GACpE,MAAM,SAAS,MAAM,SAAS,KAAK,mBAAmB,GAAG,QAAQ,kBAAkB,CAAC;GACpF,SAAS,UAAU,KAAK;IAAE,gBAAgB;IAAmB,iBAAiB;GAAW,CAAC;GAC1F,SAAS,IAAI,MAAM;GACnB;EACF;EACA,IACE,QAAQ,QAAQ,wBAAwB,SACvC,QAAQ,WAAW,UAAU,QAAQ,QAAQ,WAAW,QACzD;GACA,KAAK,UAAU,KAAK,EAClB,OACE,wFACJ,CAAC;GACD;EACF;EAEA,MAAM,QAAQ,MAAM,UAAU,QAAQ,GAAG;EACzC,MAAM,SAAS,MAAM,WAAW,QAAQ,GAAG;EAC3C,MAAM,UAA8C;GAClD,KAAK,QAAQ;GACb,OAAO;IAAE,MAAM;IAAW;GAAI;GAC9B,aAAa;EACf;EACA,IAAI,QAAQ,YAAY,QACtB,QAAQ,cAAc,QAAQ;EAEhC,IAAI,OAAO,SAAS,kBAAkB,QACpC,QAAQ,gBAAgB,OAAO,QAAQ;EAEzC,IAAI,OAAO,SAAS,YAAY,QAC9B,QAAQ,UAAU,OAAO,QAAQ;EAGnC,IAAI,QAAQ,WAAW,SAAS,IAAI,aAAa,cAAc;GAC7D,MAAM,QAAQ,MAAM,aAAa,OAAO;GAiBxC,KAAK,UAAU,KAAK;IAflB,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,OAAO,MAAM;IACb,QAAQ,MAAM,OAAO,WAAW;IAChC,UAAU,OAAO,SAAS,YAAY;IACtC,SAAS,OAAO,SAAS,OAAO,WAAW;IAC3C,WAAW,CAAC,GAAI,MAAM,SAAS,YAAY,CAAC,GAAI,GAAI,MAAM,SAAS,YAAY,CAAC,CAAE,CAAC,CAAC,KACjF,SAAS,UAAU,cAAc,KAAK,KAAK,CAAC,CAC/C;IACA,OAAO,CACL,sKACF;IACA,UAAU,CAAC;KAAE;KAAK,OAAO;IAAI,CAAC;IAC9B;GAEsB,CAAC;GACzB;EACF;EACA,IAAI,QAAQ,WAAW,QAAQ;GAC7B,KAAK,UAAU,KAAK,EAAE,OAAO,2BAA2B,CAAC;GACzD;EACF;EAEA,MAAM,YAAY,MAAM,cAAc,OAAO;EAC7C,IAAI,IAAI,aAAa,aAAa;GAChC,MAAM,aAAa,eAAe,QAAQ,SAAS;GAEnD,WAAW,UAAU,OAAO;GAC5B,MAAM,QAAQ,IAAI,CAChB,YAAY,KAAK,QAAQ,KAAK,aAAa,YAAY,GAAG,cAAc,OAAO,SAAS,CAAC,GACzF,YAAY,KAAK,QAAQ,KAAK,aAAa,aAAa,GAAG,UAAU,CACvE,CAAC;GACD,KAAK,UAAU,KAAK,EAAE,OAAO,KAAK,CAAC;GACnC;EACF;EACA,IAAI,IAAI,aAAa,eAAe;GAClC,KAAK,UAAU,KAAK,EAAE,OAAO,2BAA2B,CAAC;GACzD;EACF;EAGA,MAAM,YAAmD;GACvD,aAFkB,aAAa,OAAO;GAGtC;GACA;GACA;GACA,UAAU,MAAM,qBAAqB;GACrC,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;GACpC,SAAS,oBAAoB;GAC7B,QAAQ,MAAM,gBAAgB,QAAQ,KAAK,MAAM;EACnD;EACA,MAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK,KAAK;EAChD,IAAI,UAAU,QACZ,UAAU,QAAQ;EAEpB,MAAM,OAAO,MAAM,gBAAgB,SAAS;EAC5C,MAAM,SAAuB;GAC3B,OAAO,KAAK,OAAO,MAAM,KAAK,UAAU;IACtC,MAAM,KAAK;IACX,MAAM,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,SAAS,QAAQ;IAC/C,OAAO,KAAK;IACZ,QAAQ,KAAK;GACf,EAAE;GACF,SAAS,OAAO,KAAK,KAAK,OAAO,CAAC,CAAC,SAAS,QAAQ;GACpD,UAAU,KAAK;EACjB;EACA,MAAM,MAAM,KAAK,UAAU,MAAM,SAAS,KAAK,SAAS,WAAW;EACnE,IAAI,QAAQ,QACV,OAAO,MAAM,OAAO,KAAK,IAAI,KAAK,CAAC,CAAC,SAAS,QAAQ;EAEvD,KAAK,UAAU,KAAK,MAAM;CAC5B;CAEA,MAAM,SAAS,cAAc,SAAS,aAAa;EACjD,AAAK,OAAO,SAAS,QAAQ,CAAC,CAAC,OAAO,UAAmB;GACvD,KAAK,UAAU,KAAK,EAClB,OACE,iBAAiB,gBACb,YAAY,KAAK,IACjB,GAAG,iBAAiB,QAAQ,MAAM,UAAU,iBAAiB,8BACrE,CAAC;EACH,CAAC;CACH,CAAC;CACD,MAAM,IAAI,SAAe,QAAQ,WAAW;EAC1C,OAAO,KAAK,SAAS,MAAM;EAC3B,OAAO,OAAO,QAAQ,QAAQ,MAAM,mBAAmB;GACrD,OAAO,eAAe,SAAS,MAAM;GACrC,OAAO;EACT,CAAC;CACH,CAAC;CACD,MAAM,UAAU,OAAO,QAAQ;CAC/B,IAAI,YAAY,QAAQ,OAAO,YAAY,UACzC,MAAM,IAAI,cACR,kBACA,uCACA,kCACF;CAEF,SAAS,oBAAoB,OAAO,QAAQ,IAAI;CAChD,OAAO;EAAE;EAAQ,KAAK,GAAG,OAAO,UAAU;EAAS;CAAM;AAC3D;AAEA,eAAsB,WAAW,SAA4D;CAC3F,IAAI;CACJ,IAAI;EACF,UAAU,MAAM,aAAa,OAAO;CACtC,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,cAC9D,MAAM,IAAI,cACR,gBACA,uCACA,4CACA,EAAE,OAAO,MAAM,CACjB;EAEF,MAAM;CACR;CACA,QAAQ,OAAO,MAAM,YAAY,QAAQ,IAAI,0BAA0B;CACvE,MAAM,IAAI,SAAe,WAAW;EAClC,MAAM,aAAa;GACjB,QAAQ,OAAO,MAAM;GACrB,QAAQ,OAAO,oBAAoB;EACrC;EACA,QAAQ,KAAK,UAAU,IAAI;EAC3B,QAAQ,KAAK,WAAW,IAAI;EAC5B,QAAQ,OAAO,KAAK,eAAe;GACjC,QAAQ,eAAe,UAAU,IAAI;GACrC,QAAQ,eAAe,WAAW,IAAI;GACtC,OAAO;EACT,CAAC;CACH,CAAC;AACH;;;;AC5RA,eAAsB,OAAO,OAAO,QAAQ,MAAuB;CACjE,QAAQ,WAAW;CACnB,MAAM,MAAM,IAAI,UAAU;CAC1B,IAAI,OAAO,gBAAgB,qBAAqB,EAAE,SAAS,QAAQ,IAAI,EAAE,CAAC;CAC1E,IAAI,OAAO,UAAU,8BAA8B;CACnD,IAAI,OAAO,WAAW,2BAA2B;CACjD,IAAI,OAAO,aAAa,gBAAgB;CAExC,IACG,QAAQ,QAAQ,2DAA2D,CAAC,CAC5E,OAAO,SAAS,qCAAqC,CAAC,CACtD,OAAO,WAAW,+CAA+C,CAAC,CAClE,OAAO,OAAO,UAAmC;EAChD,MAAM,SAAS,MAAM,QAAQ;GAC3B,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC;GACxC,KAAK,MAAM,QAAQ;GACnB,OAAO,MAAM,UAAU;EACzB,CAAC;EACD,IAAI,MAAM,SAAS,MAAM;GACvB,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,UAAU,OAAO,MAAM,CAAC,EAAE,GAAG;GAC3E;EACF;EACA,IAAI,MAAM,UAAU,MAAM;GACxB,QAAQ,OAAO,MAAM,SAAS,OAAO,UAAU,GAAG;GAClD,QAAQ,OAAO,MAAM,SAAS,OAAO,WAAW,GAAG;GACnD,QAAQ,OAAO,MAAM,gBAAgB,OAAO,WAAW,GAAG;GAC1D,KAAK,MAAM,SAAS,OAAO,UAAU,SACnC,QAAQ,OAAO,MAAM,KAAK,MAAM,MAAM,IAAI,MAAM,OAAO,GAAG;GAK5D,KAAK,MAAM,QAAQ,OAAO,UAAU,OAClC,QAAQ,OAAO,MAAM,WAAW,KAAK,GAAG;EAE5C;CACF,CAAC;CAEH,IAAI,QAAQ,SAAS,yDAAyD,CAAC,CAC5E,OAAO,eAAe,aAAa,CAAC,CACpC,OAAO,qBAAqB,uEAAuE,CAAC,CACpG,OAAO,mBAAmB,iCAAiC,CAAC,CAC5D,OAAO,mBAAmB,eAAe,CAAC,CAC1C,OAAO,qBAAqB,6BAA6B,CAAC,CAC1D,OAAO,eAAe,kBAAkB,CAAC,CACzC,OAAO,oBAAoB,iCAAiC,CAAC,CAC7D,OAAO,YAAY,+BAA+B,CAAC,CACnD,OAAO,aAAa,8DAA8D,CAAC,CACnF,OAAO,OAAO,UAAmC;EAChD,MAAM,UAA0C;GAAE,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC;GAAG,QAAQ,MAAM,WAAW;EAAK;EAC3H,KAAK,MAAM,OAAO;GAAC;GAAO;GAAU;GAAS;GAAS;GAAY;GAAO;EAAS,GAAY;GAC5F,MAAM,QAAQ,eAAe,MAAM,IAAI;GAAG,IAAI,UAAU,QAAW,QAAQ,OAAO;EACpF;EACA,MAAM,SAAS,MAAM,SAAS,OAAO;EACrC,QAAQ,WAAW,OAAO;EAC1B,IAAI,MAAM,SAAS,MAAM,UAAU,MAAM;OACpC,IAAI,MAAM,UAAU,MAAM,iBAAiB;GAAE,GAAG;GAAQ,QAAQ;GAAO,OAAO,OAAO,SAAS;GAAO,UAAU,OAAO,SAAS;EAAS,CAAC;CAChJ,CAAC;CAEH,IAAI,QAAQ,WAAW,iEAAiE,CAAC,CACtF,OAAO,eAAe,aAAa,CAAC,CACpC,OAAO,iBAAiB,gCAAgC,CAAC,CACzD,OAAO,oBAAoB,iCAAiC,CAAC,CAC7D,OAAO,OAAO,UAAmC;EAChD,MAAM,UAA4C,EAAE,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC,EAAE;EAC9F,KAAK,MAAM,OAAO,CAAC,OAAO,SAAS,GAAY;GAAE,MAAM,QAAQ,eAAe,MAAM,IAAI;GAAG,IAAI,UAAU,QAAW,QAAQ,OAAO;EAAO;EAC1I,IAAI,MAAM,SAAS,QAAW;GAC5B,MAAM,OAAO,OAAO,MAAM,IAAI;GAC9B,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO,MAAM,IAAI,cAAc,gBAAgB,gCAAgC,uCAAuC;GACxK,QAAQ,OAAO;EACjB;EACA,MAAM,WAAW,OAAO;CAC1B,CAAC;CAEH,IAAI,QAAQ,UAAU,2CAA2C,CAAC,CAAC,OAAO,OAAO,UAAmC;EAClH,MAAM,SAAS,MAAM,UAAU,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC;EACnE,IAAI,MAAM,SAAS,MACjB,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;OACtD,IAAI,MAAM,UAAU,MACzB,KAAK,MAAM,SAAS,OAAO,QAAQ;GACjC,MAAM,OAAO,MAAM,WAAW,SAAS,OAAO,MAAM,WAAW,SAAS,SAAS;GACjF,QAAQ,OAAO,MAAM,IAAI,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,QAAQ,GAAG;GAClE,IAAI,MAAM,QAAQ,UAAa,MAAM,WAAW,QAC9C,QAAQ,OAAO,MAAM,cAAc,MAAM,IAAI,GAAG;EAEpD;EAEF,IAAI,CAAC,OAAO,IACV,QAAQ,WAAW;CAEvB,CAAC;CAED,IACG,QAAQ,WAAW,2BAA2B,CAAC,CAC/C,OAAO,eAAe,aAAa,CAAC,CACpC,OAAO,gBAAgB,cAAc,CAAC,CACtC,OAAO,oBAAoB,yBAAyB,CAAC,CACrD,OAAO,sBAAsB,2BAA2B,CAAC,CACzD,OAAO,8BAA8B,kBAAkB,CAAC,CACxD,OAAO,UAAU,oEAAoE,CAAC,CACtF,OAAO,eAAe,kBAAkB,CAAC,CACzC,OAAO,YAAY,+BAA+B,CAAC,CACnD,OAAO,aAAa,8CAA8C,CAAC,CACnE,OAAO,oBAAoB,iCAAiC,CAAC,CAC7D,OAAO,qBAAqB,kDAAkD,CAAC,CAC/E,OAAO,wBAAwB,2BAA2B,CAAC,CAC3D,OAAO,YAAY,wCAAwC,CAAC,CAC5D,OAAO,OAAO,UAAmC;EAChD,MAAM,eAA6B;GACjC,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC;GACxC,QAAQ,MAAM,WAAW;GACzB,QAAQ,MAAM,WAAW;EAC3B;EACA,iBAAiB,cAAc,KAAK;EACpC,MAAM,MAAM,eAAe,MAAM,GAAG;EACpC,IAAI,QAAQ,QACV,aAAa,MAAM;EAErB,MAAM,WAAW,eAAe,MAAM,QAAQ;EAC9C,IAAI,aAAa,QACf,aAAa,WAAW;EAE1B,MAAM,cAAc,eAAe,MAAM,WAAW;EACpD,IAAI,gBAAgB,QAClB,aAAa,cAAc;EAE7B,MAAM,OAAO,eAAe,MAAM,IAAI;EACtC,IAAI,SAAS,QACX,aAAa,OAAO;EAEtB,MAAM,YAAY,eAAe,MAAM,SAAS;EAChD,IAAI,cAAc,QAChB,aAAa,YAAY;EAE3B,MAAM,SAAS,MAAM,WAAW,YAAY;EAC5C,QAAQ,WAAW,OAAO;EAC1B,mBAAmB,OAAO,MAAM;CAClC,CAAC;CAEH,IACG,QAAQ,aAAa,6DAA6D,CAAC,CACnF,OAAO,2CAA2C,iBAAiB,CAAC,CACpE,OAAO,mBAAmB,4BAA4B,CAAC,CACvD,OAAO,oBAAoB,yBAAyB,CAAC,CACrD,OAAO,8BAA8B,kBAAkB,CAAC,CACxD,OAAO,UAAU,oEAAoE,CAAC,CACtF,OAAO,eAAe,kBAAkB,CAAC,CACzC,OAAO,YAAY,+BAA+B,CAAC,CACnD,OAAO,aAAa,8CAA8C,CAAC,CACnE,OAAO,oBAAoB,iCAAiC,CAAC,CAC7D,OAAO,OAAO,UAAmC;EAChD,MAAM,iBAAiC;GACrC,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC;GACxC,QAAQ,MAAM,WAAW;GACzB,QAAQ,MAAM,WAAW;EAC3B;EACA,iBAAiB,gBAAgB,KAAK;EACtC,MAAM,SAAS,eAAe,MAAM,MAAM;EAC1C,IAAI,WAAW,QACb,eAAe,SAAS;EAE1B,MAAM,YAAY,eAAe,MAAM,SAAS;EAChD,IAAI,cAAc,QAChB,eAAe,YAAY;EAE7B,MAAM,SAAS,MAAM,aAAa,cAAc;EAChD,QAAQ,WAAW,OAAO;EAC1B,IAAI,MAAM,SAAS,MAAM;GACvB,UAAU,aAAa,MAAM,CAAC;GAC9B;EACF;EACA,IAAI,MAAM,UAAU,MAClB;EAEF,IAAI,OAAO,SAAS;GAClB,QAAQ,OAAO,MAAM,GAAG,OAAO,WAAW,kCAAkC,GAAG;GAC/E;EACF;EACA,iBAAiB,MAAM;CACzB,CAAC;CAEH,IACG,QAAQ,SAAS,0CAA0C,CAAC,CAC5D,OAAO,iBAAiB,oBAAoB,CAAC,CAC7C,OAAO,oBAAoB,yBAAyB,CAAC,CACrD,OAAO,8BAA8B,kBAAkB,CAAC,CACxD,OAAO,UAAU,oEAAoE,CAAC,CACtF,OAAO,eAAe,kBAAkB,CAAC,CACzC,OAAO,YAAY,+BAA+B,CAAC,CACnD,OAAO,aAAa,8CAA8C,CAAC,CACnE,OAAO,oBAAoB,iCAAiC,CAAC,CAC7D,OAAO,OAAO,UAAmC;EAChD,MAAM,aAAyB;GAC7B,KAAK,WAAW,MAAM,KAAK,QAAQ,IAAI,CAAC;GACxC,QAAQ,MAAM,WAAW;GACzB,QAAQ,MAAM,WAAW;EAC3B;EACA,iBAAiB,YAAY,KAAK;EAClC,MAAM,OAAO,eAAe,MAAM,IAAI;EACtC,IAAI,SAAS,QACX,WAAW,OAAO;EAEpB,MAAM,SAAS,MAAM,SAAS,UAAU;EACxC,QAAQ,WAAW,OAAO;EAC1B,mBAAmB,OAAO,MAAM;CAClC,CAAC;CAEH,IAAI,KAAK;CACT,IAAI,QAAQ,YAAY,CAAC;CAEzB,IAAI;EACF,IAAI,MAAM,MAAM,EAAE,KAAK,MAAM,CAAC;EAC9B,MAAM,IAAI,kBAAkB;EAC5B,OAAO,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW;CACnE,SAAS,OAAO;EACd,IAAI,iBAAiB,eAAe;GAClC,QAAQ,OAAO,MAAM,GAAG,YAAY,KAAK,EAAE,GAAG;GAC9C,OAAO;EACT;EACA,IAAI,iBAAiB,OAAO;GAC1B,QAAQ,OAAO,MAAM,GAAG,MAAM,QAAQ,GAAG;GACzC,OAAO;EACT;EACA,MAAM;CACR;AACF;AAEA,SAAS,WAAW,OAAgB,UAA0B;CAC5D,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,eAAe,OAAoC;CAC1D,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,iBAAiB,QAAiH,OAAsC;CAC/K,MAAM,UAAU,eAAe,MAAM,OAAO;CAC5C,IAAI,YAAY,QACd,OAAO,UAAU;CAEnB,MAAM,SAAS,eAAe,MAAM,MAAM;CAC1C,IAAI,WAAW,QACb,OAAO,SAAS;CAElB,IAAI,MAAM,SAAS,OACjB,OAAO,OAAO;CAEhB,MAAM,MAAM,eAAe,MAAM,GAAG;CACpC,IAAI,QAAQ,QACV,OAAO,MAAM;CAEf,MAAM,MAAM,eAAe,MAAM,OAAO;CACxC,IAAI,QAAQ,QACV,OAAO,UAAU;CAEnB,IAAI,MAAM,WAAW,MACnB,OAAO,SAAS;AAEpB;AAEA,SAAS,mBACP,OACA,QAUM;CACN,IAAI,MAAM,SAAS,MAAM;EACvB,UAAU,aAAa,MAAM,CAAC;EAC9B;CACF;CACA,IAAI,MAAM,UAAU,MAClB;CAEF,iBAAiB,MAAM;AACzB;AAEA,SAAS,aAAa,QAOM;CAC1B,MAAM,UAAmC,CAAC;CAC1C,IAAI,OAAO,YAAY,MACrB,QAAQ,UAAU;CAEpB,IAAI,OAAO,YAAY,QACrB,QAAQ,UAAU,OAAO;CAE3B,IAAI,OAAO,QAAQ,QACjB,QAAQ,MAAM,OAAO;CAEvB,IAAI,OAAO,aAAa,QACtB,QAAQ,WAAW,OAAO;MAE1B,QAAQ,QAAQ,OAAO;CAEzB,OAAO;AACT;AAEA,SAAS,iBAAiB,QAQjB;CACP,IAAI,OAAO,YAAY,MAAM;EAC3B,QAAQ,OAAO,MAAM,GAAG,OAAO,WAAW,uBAAuB,GAAG;EACpE;CACF;CACA,IAAI,OAAO,QAAQ;EACjB,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,OAAO,MAAM,CAAC,EAAE,GAAG;EACjE;CACF;CACA,IAAI,OAAO,QAAQ,QACjB,QAAQ,OAAO,MAAM,SAAS,OAAO,IAAI,GAAG;CAE9C,IAAI,OAAO,gBAAgB,QACzB,QAAQ,OAAO,MAAM,SAAS,OAAO,YAAY,GAAG;CAEtD,KAAK,MAAM,WAAW,OAAO,UAC3B,QAAQ,OAAO,MAAM,YAAY,QAAQ,SAAS,GAAG,QAAQ,OAAO,GAAG,QAAQ,KAAK,GAAG,QAAQ,OAAO,GAAG;AAE7G;AAEA,SAAS,UAAU,OAAsB;CACvC,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE,GAAG;AAC5D;AAEA,SAAS,cAAsB;CAC7B,MAAM,MAAe,KAAK,MAAM,aAAa,KAAK,mBAAmB,GAAG,cAAc,GAAG,MAAM,CAAC;CAChG,IAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,aAAa,OAAO,OAAO,IAAI,YAAY,UACxF,OAAO,IAAI;CAEb,OAAO;AACT;AAEA,IAAI,UAAU,QAAQ,KAAK,EAAE,GAC3B,AAAK,OAAO,CAAC,CAAC,MAAM,SAAS;CAC3B,QAAQ,KAAK,IAAI;AACnB,CAAC;AAGH,SAAS,UAAU,SAAsC;CACvD,IAAI,YAAY,QACd,OAAO;CAET,MAAM,aAAa,QAAQ,WAAW,MAAM,GAAG;CAC/C,OACE,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,WAAW;AAEnC"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":["formatCount","measureOpts","propsSchema","propsSchema","propsSchema","formatCount","formatCount","propsSchema","propsSchema","execFileAsync","API_ROOT","stripScope","repositoryUrl","normalizeGitUrl","textNode","takumiFromJsx","execFileAsync","execFileAsync","matchingBrace","basename","input","STORY_FORMATS"],"sources":["../src/core/errors.ts","../src/brand/schema.ts","../src/brand/load.ts","../src/formats.ts","../src/config/schema.ts","../src/config/load.ts","../src/copy/slots.ts","../src/copy/headline.ts","../src/copy/deterministic.ts","../src/bench/percent.ts","../src/fit/fit-text.ts","../src/templates/theme.ts","../src/takumi-jsx/jsx-runtime.ts","../src/templates/code-card.tsx","../src/templates/highlight.ts","../src/templates/bench.tsx","../src/templates/milestone.tsx","../src/templates/primitives/seal.ts","../src/templates/release-hero.tsx","../src/templates/release-highlights.tsx","../src/facts/schema.ts","../src/templates/story-page.tsx","../src/templates/registry.ts","../src/core/generate.ts","../src/facts/fact.ts","../src/facts/merge.ts","../src/sources/bench-file.ts","../src/sources/readme.ts","../src/sources/release-line.ts","../src/sources/changelog.ts","../src/sources/git.ts","../src/sources/github.ts","../src/sources/npm.ts","../src/sources/package-json.ts","../src/sources/collect.ts","../src/render/takumi.ts","../src/render/takumi-node.ts","../src/copy/number-guard.ts","../src/copy/llm.ts","../src/outputs/manifest.ts","../src/outputs/files.ts","../src/outputs/github-release.ts","../src/commands/shared.ts","../src/commands/bench.ts","../src/commands/doctor.ts","../src/brand/color.ts","../src/brand/css-vars.ts","../src/brand/dtcg.ts","../src/brand/tailwind.ts","../src/brand/detect-colors.ts","../src/brand/logo.ts","../src/brand/png.ts","../src/brand/detect.ts","../src/brand/detect-node.ts","../src/commands/init.ts","../src/commands/milestone.ts","../src/commands/release.ts","../src/core/story.ts","../src/outputs/downloads.ts","../src/studio/pack.ts","../src/commands/story.ts","../src/commands/preview.ts","../src/cli.ts"],"sourcesContent":["// Typed errors: what went wrong, why, how to fix\n// Spec: docs/PROJECT_PLAN.md §0.3\n\nexport class ShipsealError extends Error {\n readonly code: string;\n readonly fix: string;\n\n constructor(code: string, message: string, fix: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = \"ShipsealError\";\n this.code = code;\n this.fix = fix;\n }\n}\n\nexport function formatError(error: ShipsealError): string {\n return `${error.message}\\nFix: ${error.fix}`;\n}\n","// brand.json zod schema\n// Spec: docs/PROJECT_PLAN.md §10.2\n\nimport { z } from \"zod\";\n\nexport const hexColorSchema = z\n .string()\n .regex(/^#([\\da-f]{6})$/i, \"Expected a 6-digit hex color like #0b0b0c\");\n\nexport const fontFaceSchema = z.object({\n family: z.string().min(1),\n weight: z.number().int().min(100).max(900),\n file: z.string().min(1).optional(),\n});\n\nexport const brandSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n name: z.string().min(1),\n tagline: z.string().optional(),\n url: z.string().optional(),\n logo: z\n .object({\n light: z.string().min(1),\n dark: z.string().min(1).optional(),\n })\n .optional(),\n colors: z.object({\n background: hexColorSchema,\n foreground: hexColorSchema,\n muted: hexColorSchema.optional(),\n primary: hexColorSchema.optional(),\n accent: hexColorSchema.optional(),\n }),\n fonts: z.object({\n heading: fontFaceSchema,\n body: fontFaceSchema,\n mono: fontFaceSchema,\n }),\n radius: z.number().nonnegative(),\n theme: z.enum([\"dark\", \"light\"]),\n style: z.enum([\"minimal\", \"editorial\", \"terminal\"]),\n tokens: z.string().nullable(),\n});\n\nexport type Brand = z.infer<typeof brandSchema>;\n\nexport const DEFAULT_BRAND_COLORS = {\n background: \"#0b0b0c\",\n foreground: \"#fafafa\",\n muted: \"#a1a1aa\",\n primary: \"#ff4d4d\",\n accent: \"#fbbf24\",\n} as const;\n\nexport const DEFAULT_BRAND_FONTS = {\n heading: { family: \"Geist\", weight: 700 },\n body: { family: \"Geist\", weight: 400 },\n mono: { family: \"Geist Mono\", weight: 400 },\n} as const;\n","// Load .shipseal/brand.json\n// Spec: docs/PROJECT_PLAN.md §10.1\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { brandSchema, type Brand } from \"./schema.js\";\n\nexport async function loadBrand(cwd: string): Promise<Brand> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n return brandSchema.parse(raw);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n throw new ShipsealError(\n \"brand.missing\",\n \"No .shipseal/brand.json found.\",\n \"Run shipseal init to detect brand colors and write brand.json.\",\n );\n }\n throw error;\n }\n}\n","// Single table of platform sizes\n// Spec: docs/PROJECT_PLAN.md §14.2\n\nexport const FORMAT_IDS = [\n \"og\",\n \"github-social\",\n \"x\",\n \"linkedin\",\n \"square\",\n \"portrait\",\n \"producthunt\",\n \"readme-banner\",\n] as const;\n\nexport type FormatId = (typeof FORMAT_IDS)[number];\n\nexport interface Format {\n id: FormatId;\n width: number;\n height: number;\n /** Minimum inset for critical text on landscape formats, in px. */\n safeZone: number;\n}\n\nconst LANDSCAPE_SAFE_ZONE = 64;\n\nexport const FORMATS: Record<FormatId, Format> = {\n og: { id: \"og\", width: 1200, height: 630, safeZone: LANDSCAPE_SAFE_ZONE },\n \"github-social\": {\n id: \"github-social\",\n width: 1280,\n height: 640,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n x: { id: \"x\", width: 1200, height: 675, safeZone: LANDSCAPE_SAFE_ZONE },\n linkedin: { id: \"linkedin\", width: 1200, height: 627, safeZone: LANDSCAPE_SAFE_ZONE },\n square: { id: \"square\", width: 1080, height: 1080, safeZone: LANDSCAPE_SAFE_ZONE },\n portrait: { id: \"portrait\", width: 1080, height: 1350, safeZone: LANDSCAPE_SAFE_ZONE },\n producthunt: {\n id: \"producthunt\",\n width: 1270,\n height: 760,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n \"readme-banner\": {\n id: \"readme-banner\",\n width: 1280,\n height: 400,\n safeZone: LANDSCAPE_SAFE_ZONE,\n },\n};\n\nexport const V1_FORMAT_IDS = [\"og\", \"github-social\", \"x\", \"linkedin\"] as const satisfies readonly FormatId[];\n","// config.json zod schema\n// Spec: docs/PROJECT_PLAN.md §11\n\nimport { z } from \"zod\";\nimport { FORMAT_IDS } from \"../formats.js\";\n\nexport const configSchema = z.object({\n $schema: z.string().optional(),\n version: z.literal(1),\n outputDir: z.string().optional(),\n formats: z.array(z.enum(FORMAT_IDS)).optional(),\n release: z\n .object({\n templates: z.array(z.string()).optional(),\n maxHighlights: z.number().int().positive().optional(),\n changelogPath: z.string().optional(),\n snippet: z.string().nullable().optional(),\n announce: z.enum([\"major\", \"minor\", \"patch\"]).optional(),\n headline: z.string().nullable().optional(),\n subheadline: z.string().nullable().optional(),\n story: z.object({\n upgrade: z.string().max(4000).optional(),\n before: z.string().optional(),\n after: z.string().optional(),\n }).refine((value) => Boolean(value.before) === Boolean(value.after), {\n message: \"Supply both story.before and story.after screenshot paths, or neither.\",\n }).optional(),\n })\n .optional(),\n milestones: z\n .object({\n stars: z.array(z.number().int().positive()).optional(),\n downloads: z.array(z.number().int().positive()).optional(),\n contributors: z.array(z.number().int().positive()).optional(),\n })\n .optional(),\n bench: z\n .object({\n file: z.string().optional(),\n })\n .optional(),\n copy: z\n .object({\n llm: z.boolean().optional(),\n provider: z.string().nullable().optional(),\n model: z.string().nullable().optional(),\n maxRetries: z.number().int().nonnegative().optional(),\n })\n .optional(),\n output: z\n .object({\n imageFormat: z.enum([\"png\", \"webp\", \"jpeg\"]).optional(),\n })\n .optional(),\n attribution: z.boolean().optional(),\n});\n\nexport type Config = z.infer<typeof configSchema>;\n\nexport const DEFAULT_CONFIG: Config = {\n version: 1,\n outputDir: \".shipseal/output\",\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\"],\n release: {\n templates: [\"release-hero\", \"release-highlights\", \"code-card\"],\n maxHighlights: 4,\n changelogPath: \"CHANGELOG.md\",\n // Announce everything by default. The review proposed \"minor\", but a project whose release\n // script copies the rendered hero (this one does) breaks when a patch produces nothing.\n announce: \"patch\",\n snippet: null,\n },\n milestones: {\n // Starts at 10. A ladder beginning at 100 meant a new project saw no\n // milestone card for months, which is exactly when it is deciding whether this is\n // worth keeping. The first few stars are the ones worth celebrating.\n stars: [10, 50, 100, 250, 500, 1000, 2500, 5000, 10000],\n downloads: [1000, 10000, 100000, 1000000],\n contributors: [10, 25, 50, 100],\n },\n bench: {\n file: \".shipseal/bench.json\",\n },\n copy: {\n llm: false,\n provider: null,\n model: null,\n maxRetries: 2,\n },\n output: {\n imageFormat: \"png\",\n },\n attribution: true,\n};\n","// Load and merge config (flags > file > defaults)\n// Spec: docs/PROJECT_PLAN.md §11\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { DEFAULT_CONFIG, configSchema, type Config } from \"./schema.js\";\n\nexport async function loadConfig(cwd: string): Promise<Config> {\n const path = join(cwd, \".shipseal\", \"config.json\");\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = configSchema.parse(raw);\n return mergeConfig(DEFAULT_CONFIG, parsed);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return DEFAULT_CONFIG;\n }\n throw error;\n }\n}\n\nexport function mergeConfig(base: Config, overlay: Config): Config {\n return {\n ...base,\n ...overlay,\n release: { ...base.release, ...overlay.release },\n milestones: { ...base.milestones, ...overlay.milestones },\n bench: { ...base.bench, ...overlay.bench },\n copy: { ...base.copy, ...overlay.copy },\n output: { ...base.output, ...overlay.output },\n };\n}\n","// Copy slots filled by the copy layer\n// Spec: docs/PROJECT_PLAN.md §13.1\n\nexport const COPY_LIMITS = {\n headline: 48,\n subheadline: 90,\n highlight: 56,\n cta: 32,\n milestoneLine: 48,\n} as const;\n\nexport const MAX_HIGHLIGHTS = 4;\n\nexport interface Copy {\n headline: string;\n subheadline: string;\n highlights: string[];\n cta: string;\n milestoneLine?: string;\n codeLines?: CodeLine[];\n /** Title for the code card, when reusing the release headline would not make sense. */\n codeTitle?: string;\n}\n\nexport type CodeLine = Array<{ text: string; color: string }>;\n","// Whether a release-note line can carry a card.\n//\n// Rendering fourteen real repositories on 2026-09-15 produced eight headlines nobody would post.\n// novuhq/novu led with \"Adam Chmara\", a contributor's name. tanstack/query led with\n// \"/solid-query.0.0-rc.3\", directus with \"/api\", vitest with \"Ui\". Changesets bodies in a\n// monorepo are full of package fragments, and a release opened with credits puts a person's\n// name where the release title belongs.\n//\n// The rule is deliberately conservative: reject what is clearly not a sentence about a change,\n// and let the caller fall back to \"{project} {version}\", which is always correct if dull.\n\n/** Below this a line is a fragment or a label, not a description of a change. */\nconst MIN_WORDS = 3;\nconst MIN_CHARS = 12;\n\n/** Housekeeping prefixes. A chore is not what a release is about. */\nconst CHORE = /^(chore|docs?|ci|build|test|refactor|style|revert|bump|deps?|dependencies)\\b[:(]?/i;\n\n/** A line that is only a person's name: \"Adam Chmara\", \"Jane Q. Smith\". */\nconst PERSON_NAME = /^[A-Z][\\p{L}'’-]+(?:\\s+[A-Z][.\\p{L}'’-]*){1,2}$/u;\n\n/** Package-ish fragments: \"/api\", \"@scope/pkg\", \"solid-query.0.0-rc.3\", \"v1.2.3\". */\nconst FRAGMENT = /^[@/]|^v?\\d+\\.\\d+|^[\\w@/.-]+$/;\n\nexport function isHeadlineWorthy(line: string): boolean {\n const text = line.trim();\n if (text.length < MIN_CHARS || text.split(/\\s+/).length < MIN_WORDS) {\n return false;\n }\n if (CHORE.test(text) || PERSON_NAME.test(text) || FRAGMENT.test(text)) {\n return false;\n }\n // A headline that is mostly a URL describes a link, not a change.\n return !/https?:\\/\\//.test(text);\n}\n","// No-LLM copy rules (default path)\n// Spec: docs/PROJECT_PLAN.md §13.2\n\nimport type { Facts } from \"../facts/schema.js\";\nimport { MAX_HIGHLIGHTS, type Copy } from \"./slots.js\";\nimport { isHeadlineWorthy } from \"./headline.js\";\n\nexport function deterministicCopy(\n facts: Facts,\n maxHighlights = MAX_HIGHLIGHTS,\n // The card shows the brand wordmark beside the headline. Falling back to the raw project\n // fact put \"shipseal 0.0.8\" under \"Shipseal\" on the same card.\n displayName?: string,\n): Copy {\n const name = facts.project.name.value;\n const version = facts.release?.version.value;\n const features = (facts.release?.features ?? []).map((item) => item.value);\n const fixes = (facts.release?.fixes ?? []).map((item) => item.value);\n const breaking = (facts.release?.breaking ?? []).map((item) => item.value);\n\n // Breaking changes lead, then features. Fixes are deliberately excluded: every Changesets\n // \"Patch Changes\" entry maps to a fix, so including them put a maintainer's note on the hero.\n // v0.0.6 announced itself as \"Never put a truncated headline on a card\", which reads as a\n // strange instruction rather than a release, and nobody posts that. A release with only fixes\n // is better titled by its name and version.\n //\n // Prefer the first entry whose opening sentence actually fits. Taking the first sentence is\n // not enough on its own: a single long sentence still overflowed, and the v0.0.5 card shipped\n // with a headline truncated mid-phrase.\n // Fits, and reads like a change. Length alone let \"Adam Chmara\" and \"/api\" onto cards.\n const headlineSource = [...breaking, ...features]\n .map((line) => cleanLine(firstSentence(line)))\n .find((line) => line.length <= HEADLINE_MAX_CHARS && isHeadlineWorthy(line));\n const title = displayName ?? name;\n const headline =\n facts.release?.headline?.value ??\n headlineSource ??\n (version === undefined ? title : `${title} ${version}`);\n\n const tagline = facts.release?.subheadline?.value ?? facts.project.tagline?.value;\n const subheadline =\n tagline !== undefined && tagline.length > 0\n ? cleanLine(tagline)\n : cleanLine(features[1] ?? fixes[1] ?? fixes[0] ?? `What's new in ${version ?? name}`);\n\n // One sentence per highlight, for the same reason the headline takes one: changelog entries\n // are prose paragraphs, so whole entries could only be truncated mid-word on a card.\n const highlights: string[] = [];\n const addHighlight = (line: string, prefix = \"\"): void => {\n if (highlights.length >= maxHighlights) {\n return;\n }\n highlights.push(`${prefix}${cleanLine(firstSentence(line))}`);\n };\n for (const line of breaking) {\n addHighlight(line, \"Breaking: \");\n }\n for (const line of features) {\n addHighlight(line);\n }\n for (const line of fixes) {\n addHighlight(line);\n }\n\n const copy: Copy = {\n headline,\n subheadline,\n highlights,\n cta: ctaFor(facts),\n };\n const snippet = facts.release?.codeSnippet?.value.code;\n if (snippet !== undefined && isInstallOnly(snippet)) {\n copy.codeTitle = \"Get started\";\n }\n return copy;\n}\n\n/**\n * Is this snippet nothing but install commands?\n *\n * Pairing \"npm i thing\" with a release headline reads as though the release was about\n * installing, which is how v0.0.6 shipped a bug-fix headline over the README's install block.\n * Install commands are still worth showing, they just need their own title.\n */\nconst INSTALL_COMMAND =\n /^\\s*(?:\\$\\s*)?(?:npm\\s+(?:i|install|add)|pnpm\\s+(?:i|install|add|dlx)|yarn\\s+(?:add|install)|bun\\s+(?:a|add|install)|npx|deno\\s+add|pip\\s+install|cargo\\s+add|go\\s+get|gem\\s+install|brew\\s+install)\\b/;\n\nexport function isInstallOnly(code: string): boolean {\n const lines = code\n .split(\"\\n\")\n .map((line) => line.replace(/\\s+#.*$/, \"\").trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n return lines.length > 0 && lines.every((line) => INSTALL_COMMAND.test(line));\n}\n\nexport function formatCount(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nexport function milestoneCopy(\n facts: Facts,\n metric: \"stars\" | \"downloads\" | \"contributors\",\n threshold: number,\n): Copy {\n const formatted = formatCount(threshold);\n const line =\n metric === \"stars\"\n ? `Thank you for ${formatted} stars`\n : metric === \"downloads\"\n ? `${formatted} weekly downloads`\n : `Thank you, ${formatted} contributors`;\n const tagline = facts.project.tagline?.value;\n return {\n headline: facts.project.name.value,\n subheadline: tagline !== undefined && tagline.length > 0 ? cleanLine(tagline) : \"\",\n highlights: [],\n cta: ctaFor(facts),\n milestoneLine: line,\n };\n}\n\nexport function benchCopy(facts: Facts): Copy {\n const title = facts.bench?.title.value ?? facts.project.name.value;\n const note = facts.bench?.note?.value;\n return {\n headline: title,\n subheadline: note !== undefined && note.length > 0 ? note : (facts.project.tagline?.value ?? \"\"),\n highlights: [],\n cta: ctaFor(facts),\n };\n}\n\n/**\n * First sentence of an entry, for use as a headline.\n *\n * Changesets entries are prose paragraphs written for a changelog, so using one whole made a\n * headline that could only be truncated mid-word. The first sentence is the part a person\n * actually wrote as the summary. Abbreviations are not special-cased: a sentence ending is a\n * period followed by a space and a capital, which leaves \"e.g. foo\" and version numbers alone.\n */\nexport function firstSentence(text: string): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n const match = /^(.+?[.?!])\\s+[A-Z]/.exec(collapsed);\n return match?.[1] ?? collapsed;\n}\n\n/**\n * Longest headline that fits two lines at the minimum font size on a 1200 wide card.\n * Measured rather than guessed: §13.1 originally said 48, which rejects most real changelog\n * sentences, and the fitting pass comfortably handles more.\n */\nconst HEADLINE_MAX_CHARS = 72;\n\n/**\n * Emoji ranges, removed from anything that reaches a card.\n *\n * No font we register carries these glyphs, so `\\u{1F310} Human-friendly ...` (got's real\n * GitHub description) rendered a tofu box on shipseal.dev. Takumi ships an emoji helper, but it\n * rewrites each emoji into an <img> pointing at jsDelivr, and `generate()` does no network.\n *\n * The ranges deliberately start at U+2600, which keeps the textual symbols people put in real\n * product names: (c) U+00A9, (r) U+00AE and (tm) U+2122 all sit below it.\n */\n// Alternation rather than one class: variation selectors and the zero-width joiner are\n// combining marks, which lint rejects when mixed into a class with ordinary code points.\nconst EMOJI = /[\\u{1F000}-\\u{1FAFF}]|[\\u{2600}-\\u{27BF}]|[\\u{FE00}-\\u{FE0F}]|\\u200D/gu;\n\nexport function stripEmoji(text: string): string {\n return text.replaceAll(EMOJI, \"\").replace(/\\s+/g, \" \").trim();\n}\n\nexport function cleanLine(text: string): string {\n // Replace an em dash with a colon and swallow the space in front of it, so \"shops \\u2014 mobile\"\n // becomes \"shops: mobile\" rather than \"shops : mobile\". Spaced en dashes become a comma for\n // the same reason: a bare hyphen with spaces reads like a stray dash on a card.\n const stripped = stripEmoji(text)\n .replace(/\\s*\\u2014\\s*/g, \": \")\n .replace(/\\s+\\u2013\\s+/g, \", \")\n .replaceAll(\"\\u2013\", \"-\")\n .replaceAll(\"!\", \".\")\n .replace(/\\s+/g, \" \")\n .trim();\n const noTrail = stripped.endsWith(\".\") ? stripped.slice(0, -1) : stripped;\n const first = noTrail.at(0);\n if (first === undefined) {\n return noTrail;\n }\n return first.toUpperCase() + noTrail.slice(1);\n}\n\nfunction ctaFor(facts: Facts): string {\n const npm = facts.project.npmPackage?.value;\n if (npm !== undefined && npm.length > 0) {\n // A package with a bin is run, not installed as a dependency. `@latest` because npx reuses\n // a cached copy otherwise, which is the footgun the README already warns about.\n return facts.project.cli?.value === true ? `npx ${npm}@latest` : `npm i ${npm}`;\n }\n const url = facts.project.url?.value ?? facts.project.repo?.value;\n if (url === undefined) {\n return facts.project.name.value;\n }\n return url.replace(/^https?:\\/\\//, \"\");\n}\n","// Percent change for benchmark cards. Display numbers are computed here, never by an LLM.\n// Spec: docs/PROJECT_PLAN.md §12.7\n\nexport interface PercentChange {\n signed: number;\n absPercent: number;\n regression: boolean;\n}\n\nexport function percentChange(before: number, after: number, better: \"lower\" | \"higher\"): PercentChange {\n if (before === 0) {\n if (after === 0) {\n return { signed: 0, absPercent: 0, regression: false };\n }\n const improved = better === \"higher\" ? after > 0 : after < 0;\n return { signed: improved ? 100 : -100, absPercent: 100, regression: !improved };\n }\n const raw = better === \"lower\" ? (before - after) / before : (after - before) / before;\n const signed = Math.round(raw * 100);\n return { signed, absPercent: Math.abs(signed), regression: signed < 0 };\n}\n\nexport function changePhrase(unit: string, better: \"lower\" | \"higher\", change: PercentChange): string {\n if (change.absPercent === 0) {\n return \"unchanged\";\n }\n return `${String(change.absPercent)}% ${deltaWord(unit, better, change.regression)}`;\n}\n\nfunction deltaWord(unit: string, better: \"lower\" | \"higher\", regression: boolean): string {\n if (better === \"higher\") {\n return regression ? \"lower\" : \"higher\";\n }\n const normalized = unit.toLowerCase();\n if (normalized === \"ms\" || normalized === \"s\" || normalized === \"sec\" || normalized === \"seconds\") {\n return regression ? \"slower\" : \"faster\";\n }\n if (\n normalized === \"kb\" ||\n normalized === \"mb\" ||\n normalized === \"b\" ||\n normalized === \"bytes\" ||\n normalized === \"gzip\"\n ) {\n return regression ? \"larger\" : \"smaller\";\n }\n return regression ? \"worse\" : \"better\";\n}\n","// Text fitting: shrink, then retry/truncate + manifest warning\n// Spec: docs/PROJECT_PLAN.md §15\n\nimport type { MeasureTextOptions, RendererAdapter } from \"../render/adapter.js\";\n\nexport interface TextSlotSpec {\n maxLines: number;\n maxFontSize: number;\n minFontSize: number;\n step: number;\n box: { width: number };\n}\n\nexport interface FittedText {\n fontSize: number;\n text: string;\n lines: number;\n truncated: boolean;\n}\n\nexport interface FitFont {\n family: string;\n lineHeight: number;\n weight?: number;\n whiteSpace?: \"normal\" | \"pre\";\n}\n\nexport async function fitText(\n renderer: Pick<RendererAdapter, \"measureText\">,\n text: string,\n spec: TextSlotSpec,\n font: FitFont,\n): Promise<FittedText> {\n const sizes = fontSizes(spec);\n for (const fontSize of sizes) {\n // Sizes must be tried largest-first; the first fit wins.\n // eslint-disable-next-line no-await-in-loop -- sequential by spec §15.2\n const measured = await renderer.measureText(text, measureOpts(spec, font, fontSize));\n if (measured.lines <= spec.maxLines) {\n return { fontSize, text, lines: measured.lines, truncated: false };\n }\n }\n\n const fontSize = spec.minFontSize;\n const truncated = await truncateToFit(renderer, text, spec, font, fontSize);\n const measured = await renderer.measureText(truncated, measureOpts(spec, font, fontSize));\n return { fontSize, text: truncated, lines: measured.lines, truncated: truncated !== text };\n}\n\nfunction fontSizes(spec: TextSlotSpec): number[] {\n const sizes: number[] = [];\n for (let size = spec.maxFontSize; size >= spec.minFontSize; size -= spec.step) {\n sizes.push(size);\n }\n const last = sizes[sizes.length - 1];\n if (last !== spec.minFontSize) {\n sizes.push(spec.minFontSize);\n }\n return sizes;\n}\n\nfunction measureOpts(spec: TextSlotSpec, font: FitFont, fontSize: number): MeasureTextOptions {\n const opts: MeasureTextOptions = {\n fontFamily: font.family,\n fontSize,\n maxWidth: spec.box.width,\n lineHeight: font.lineHeight,\n };\n if (font.weight !== undefined) {\n opts.fontWeight = font.weight;\n }\n if (font.whiteSpace !== undefined) {\n opts.whiteSpace = font.whiteSpace;\n }\n return opts;\n}\n\nasync function truncateToFit(\n renderer: Pick<RendererAdapter, \"measureText\">,\n text: string,\n spec: TextSlotSpec,\n font: FitFont,\n fontSize: number,\n): Promise<string> {\n const words = text.trim().length === 0 ? [] : text.trim().split(/\\s+/);\n if (words.length === 0) {\n return text;\n }\n\n const fits = async (candidate: string): Promise<boolean> => {\n const measured = await renderer.measureText(\n candidate,\n measureOpts(spec, font, fontSize),\n );\n return measured.lines <= spec.maxLines;\n };\n\n for (let count = words.length - 1; count >= 1; count -= 1) {\n const candidate = `${words.slice(0, count).join(\" \")}...`;\n // eslint-disable-next-line no-await-in-loop -- drop words until the truncated text fits\n if (await fits(candidate)) {\n return candidate;\n }\n }\n\n const first = words[0];\n if (first === undefined) {\n return \"...\";\n }\n for (let length = first.length; length >= 1; length -= 1) {\n const candidate = `${first.slice(0, length)}...`;\n // eslint-disable-next-line no-await-in-loop -- hard-cut the first word as a last resort\n if (await fits(candidate)) {\n return candidate;\n }\n }\n return \"...\";\n}\n","// Dark/light palette derived from brand.json\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { DEFAULT_BRAND_COLORS, type Brand } from \"../brand/schema.js\";\n\nexport interface ThemeColors {\n background: string;\n foreground: string;\n muted: string;\n primary: string;\n accent: string;\n card: string;\n}\n\nexport function themeColors(brand: Brand, theme: \"dark\" | \"light\"): ThemeColors {\n const primary = brand.colors.primary ?? DEFAULT_BRAND_COLORS.primary;\n const accent = brand.colors.accent ?? DEFAULT_BRAND_COLORS.accent;\n const muted = brand.colors.muted ?? DEFAULT_BRAND_COLORS.muted;\n if (theme === \"dark\") {\n const background = brand.theme === \"dark\" ? brand.colors.background : brand.colors.foreground;\n const foreground = brand.theme === \"dark\" ? brand.colors.foreground : brand.colors.background;\n return {\n background,\n foreground,\n muted: brand.theme === \"dark\" ? muted : DEFAULT_BRAND_COLORS.muted,\n primary,\n accent,\n card: mix(background, foreground, 0.08),\n };\n }\n const background = brand.theme === \"light\" ? brand.colors.background : brand.colors.foreground;\n const foreground = brand.theme === \"light\" ? brand.colors.foreground : brand.colors.background;\n return {\n background,\n foreground,\n muted: brand.theme === \"light\" ? muted : \"#52525b\",\n primary,\n accent,\n card: mix(background, foreground, 0.06),\n };\n}\n\nfunction mix(a: string, b: string, amount: number): string {\n const ar = Number.parseInt(a.slice(1, 3), 16);\n const ag = Number.parseInt(a.slice(3, 5), 16);\n const ab = Number.parseInt(a.slice(5, 7), 16);\n const br = Number.parseInt(b.slice(1, 3), 16);\n const bg = Number.parseInt(b.slice(3, 5), 16);\n const bb = Number.parseInt(b.slice(5, 7), 16);\n return `#${toHex(ar + (br - ar) * amount)}${toHex(ag + (bg - ag) * amount)}${toHex(ab + (bb - ab) * amount)}`;\n}\n\nfunction toHex(value: number): string {\n return Math.round(value).toString(16).padStart(2, \"0\");\n}\n","// Local four-line JSX runtime for Takumi templates (no React)\n// Spec: docs/PROJECT_PLAN.md §16.2, §25 (S1)\n\nexport type JsxElement = {\n type: string | symbol | ((props: Record<string, unknown>) => unknown);\n props: Record<string, unknown> | null;\n key: string | null;\n};\n\nexport function jsx(\n type: JsxElement[\"type\"],\n props: Record<string, unknown> | null,\n key?: string | null,\n): JsxElement {\n return { type, props, key: key ?? null };\n}\n\nexport const jsxs = jsx;\nexport const jsxDEV = jsx;\nexport const Fragment = Symbol.for(\"takumi.fragment\");\n\nexport namespace JSX {\n export type Element = JsxElement;\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n export type IntrinsicElements = Record<string, Record<string, unknown>>;\n}\n","// Template: syntax-highlighted snippet\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { CodeLine, Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\n/** Advance width of a monospace glyph as a fraction of the font size. */\nexport const MONO_ADVANCE = 0.6;\n\nconst propsSchema = z.object({\n headline: z.string(),\n headingFamily: z.string(),\n monoFamily: z.string(),\n headingWeight: z.number(),\n monoWeight: z.number(),\n radius: z.number(),\n lines: z.array(z.array(z.object({ text: z.string(), color: z.string() }))),\n});\n\nexport type CodeCardProps = z.infer<typeof propsSchema>;\n\nexport const codeCard: TemplateDefinition = {\n id: \"code-card\",\n events: [\"release\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n headline: { maxLines: 1, maxFontSize: 40, minFontSize: 28, step: 2, box: { width } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return { headline: props.headline };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"headline\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n }\n return { family: props.monoFamily, weight: props.monoWeight, lineHeight: 1.35, whiteSpace: \"pre\" };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n const lines = copy.codeLines ?? [];\n if (lines.length === 0) {\n missing.push({ fact: \"release.codeSnippet\", effect: \"code card uses empty snippet\" });\n }\n return {\n props: {\n headline: copy.codeTitle ?? copy.headline,\n headingFamily: brand.fonts.heading.family,\n monoFamily: brand.fonts.mono.family,\n headingWeight: brand.fonts.heading.weight,\n monoWeight: brand.fonts.mono.weight,\n radius: brand.radius,\n lines,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const headline = ctx.fitted.headline;\n\n // Size the type to the snippet rather than the card. A fixed 22px in a box with flexGrow\n // drew a 14-line frame around a 2-line snippet, leaving most of the card empty with small\n // text on it. Mono glyphs are a constant fraction of the em, so the widest line and the\n // line count give a size directly, with no measurement pass.\n const boxPad = 28;\n const lineHeight = 1.35;\n const lines = props.lines.length === 0 ? 1 : props.lines.length;\n const longest = Math.max(\n 1,\n ...props.lines.map((line) => line.reduce((total, token) => total + token.text.length, 0)),\n );\n const headlineHeight = (headline?.fontSize ?? 36) * 1.25;\n const attributionHeight = ctx.attribution ? 18 * 1.4 + 24 : 0;\n const innerWidth = ctx.format.width - 2 * pad - 2 * boxPad;\n const innerHeight =\n ctx.format.height - 2 * pad - headlineHeight - 24 - attributionHeight - 2 * boxPad;\n const codeSize = Math.max(\n 18,\n Math.min(44, Math.floor(Math.min(innerWidth / (longest * MONO_ADVANCE), innerHeight / (lines * lineHeight)))),\n );\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n gap: 24,\n }}\n >\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: headline?.fontSize ?? 36,\n color: colors.foreground,\n }}\n >\n {headline?.text ?? props.headline}\n </div>\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: \"center\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n padding: boxPad,\n gap: 0,\n }}\n >\n {props.lines.map((line, lineIndex) => (\n <div\n key={String(lineIndex)}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n }}\n >\n {line.map((token, tokenIndex) => (\n <div\n key={`${String(lineIndex)}-${String(tokenIndex)}`}\n style={{\n fontFamily: props.monoFamily,\n fontWeight: props.monoWeight,\n fontSize: codeSize,\n color: token.color,\n whiteSpace: \"pre\",\n lineHeight,\n }}\n >\n {token.text}\n </div>\n ))}\n </div>\n ))}\n </div>\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: 400,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n );\n },\n};\n\nexport function emptyCodeLines(): CodeLine[] {\n return [[{ text: \" \", color: \"#e6edf3\" }]];\n}\n","// Syntax-highlight a snippet into colored spans (shiki tokens)\n// Spec: docs/PROJECT_PLAN.md §14.3, spike S5\n\nimport type { CodeLine } from \"../copy/slots.js\";\n\nconst MAX_LINES = 14;\n\nexport async function highlightCode(\n code: string,\n lang: string,\n theme: \"dark\" | \"light\",\n): Promise<CodeLine[]> {\n const clipped = code.split(\"\\n\").slice(0, MAX_LINES).join(\"\\n\");\n const fallbackColor = theme === \"dark\" ? \"#e6edf3\" : \"#1f2328\";\n try {\n const { codeToTokens } = await import(\"shiki\");\n const result = await codeToTokens(clipped, {\n lang: mapLang(lang),\n theme: theme === \"dark\" ? \"github-dark\" : \"github-light\",\n });\n return result.tokens.map((line) => {\n if (line.length === 0) {\n return [{ text: \" \", color: fallbackColor }];\n }\n return line.map((token) => ({\n text: token.content,\n color: token.color ?? fallbackColor,\n }));\n });\n } catch {\n return clipped.split(\"\\n\").map((line) => [{ text: line.length === 0 ? \" \" : line, color: fallbackColor }]);\n }\n}\n\nfunction mapLang(lang: string): \"ts\" | \"js\" | \"tsx\" | \"jsx\" | \"json\" | \"bash\" {\n const key = lang.toLowerCase();\n if (key === \"javascript\" || key === \"js\") {\n return \"js\";\n }\n if (key === \"tsx\") {\n return \"tsx\";\n }\n if (key === \"jsx\") {\n return \"jsx\";\n }\n if (key === \"json\") {\n return \"json\";\n }\n if (key === \"bash\" || key === \"shell\" || key === \"sh\") {\n return \"bash\";\n }\n return \"ts\";\n}\n","// Template: before/after metrics\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport { changePhrase, percentChange } from \"../bench/percent.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst rowSchema = z.object({\n label: z.string(),\n beforeText: z.string(),\n afterText: z.string(),\n changeText: z.string(),\n regression: z.boolean(),\n});\n\nconst propsSchema = z.object({\n title: z.string(),\n note: z.string(),\n rows: z.array(rowSchema),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n});\n\nexport type BenchProps = z.infer<typeof propsSchema>;\n\nexport const bench: TemplateDefinition = {\n id: \"bench\",\n events: [\"bench\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n const slots: Record<string, { maxLines: number; maxFontSize: number; minFontSize: number; step: number; box: { width: number } }> =\n {\n title: { maxLines: 2, maxFontSize: 48, minFontSize: 28, step: 2, box: { width } },\n };\n for (let index = 0; index < 3; index += 1) {\n slots[`change-${String(index)}`] = {\n maxLines: 1,\n maxFontSize: 36,\n minFontSize: 22,\n step: 2,\n box: { width: Math.min(360, width) },\n };\n }\n return slots;\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n const text: Record<string, string> = { title: props.title };\n props.rows.forEach((row, index) => {\n text[`change-${String(index)}`] = row.changeText;\n });\n return text;\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"title\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.15 };\n }\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (facts.bench === undefined) {\n missing.push({ fact: \"bench\", effect: \"metrics hidden\" });\n }\n const rows =\n facts.bench?.metrics.map((metric) => {\n const change = percentChange(metric.before.value, metric.after.value, metric.better.value);\n return {\n label: metric.label.value,\n beforeText: `${formatMetric(metric.before.value)} ${metric.unit.value}`,\n afterText: `${formatMetric(metric.after.value)} ${metric.unit.value}`,\n changeText: changePhrase(metric.unit.value, metric.better.value, change),\n regression: change.regression,\n };\n }) ?? [];\n return {\n props: {\n title: copy.headline,\n note: copy.subheadline,\n rows,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const title = ctx.fitted.title;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n }}\n >\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: title?.fontSize ?? 40,\n color: colors.foreground,\n lineHeight: 1.15,\n }}\n >\n {title?.text ?? props.title}\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 20 }}>\n {props.rows.map((row, index) => {\n const change = ctx.fitted[`change-${String(index)}`];\n return (\n <div\n key={row.label}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n paddingTop: 16,\n paddingBottom: 16,\n paddingLeft: 24,\n paddingRight: 24,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6 }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.muted,\n }}\n >\n {row.label}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 24,\n color: colors.foreground,\n }}\n >\n {`${row.beforeText} to ${row.afterText}`}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"flex-end\", gap: 4 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: change?.fontSize ?? 32,\n color: row.regression ? colors.primary : colors.accent,\n }}\n >\n {change?.text ?? row.changeText}\n </div>\n {row.regression ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.primary,\n }}\n >\n regression\n </div>\n ) : undefined}\n </div>\n </div>\n );\n })}\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 20,\n color: colors.muted,\n }}\n >\n {props.note}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n\nfunction formatMetric(value: number): string {\n return String(value);\n}\n","// Template: milestone big number\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport { formatCount } from \"../copy/deterministic.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n numberText: z.string(),\n metricLabel: z.string(),\n thankYou: z.string(),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n showLogo: z.boolean(),\n});\n\nexport type MilestoneProps = z.infer<typeof propsSchema>;\n\nexport const milestone: TemplateDefinition = {\n id: \"milestone\",\n events: [\"milestone\"],\n formats: [\"og\", \"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n number: { maxLines: 1, maxFontSize: 160, minFontSize: 72, step: 8, box: { width } },\n thankYou: { maxLines: 2, maxFontSize: 36, minFontSize: 24, step: 2, box: { width } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return { number: props.numberText, thankYou: props.thankYou };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"number\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1 };\n }\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n const threshold = facts.milestone?.threshold.value;\n if (threshold === undefined) {\n missing.push({ fact: \"milestone.threshold\", effect: \"number hidden\" });\n }\n const metric = facts.milestone?.metric.value;\n const metricLabel =\n metric === \"downloads\" ? \"weekly downloads\" : metric === \"contributors\" ? \"contributors\" : \"stars\";\n const showLogo = brand.logo !== undefined;\n if (!showLogo) {\n missing.push({ fact: \"brand.logo\", effect: \"logo hidden\" });\n }\n const thankYou = copy.milestoneLine ?? (threshold === undefined ? \"\" : `Thank you for ${formatCount(threshold)} ${metricLabel}`);\n return {\n props: {\n name: brand.name,\n numberText: threshold === undefined ? \"\" : formatCount(threshold),\n metricLabel,\n thankYou,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n showLogo,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const number = ctx.fitted.number;\n const thanks = ctx.fitted.thankYou;\n const compact = ctx.format.height <= 640;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"row\", alignItems: \"center\", gap: 20 }}>\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <img src={ctx.logoSrc} width={compact ? 56 : 72} height={compact ? 56 : 72} />\n ) : undefined}\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 28,\n color: colors.foreground,\n }}\n >\n {props.name}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: number?.fontSize ?? 140,\n color: colors.foreground,\n lineHeight: 1,\n }}\n >\n {number?.text ?? props.numberText}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: 32,\n color: colors.primary,\n }}\n >\n {props.metricLabel}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: thanks?.fontSize ?? 28,\n color: colors.muted,\n lineHeight: 1.25,\n }}\n >\n {thanks?.text ?? props.thankYou}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n","// Seal stamp: the verified-facts mark shared by every template\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport type { Facts } from \"../../facts/schema.js\";\nimport { formatCount } from \"../../copy/deterministic.js\";\n\nexport interface SealStamp {\n segments: string[];\n missing: { fact: string; effect: string }[];\n}\n\n/**\n * The core promise, made visible on the card.\n *\n * \"sealed · 7 commits · 2026-09-11\" turns \"every number has a source\" from a claim on the\n * website into a mark in the feed. Every segment is a fact, so rule 1 holds: a missing fact\n * drops its segment and is reported, it never becomes a placeholder or an estimate.\n */\nexport function sealStamp(facts: Facts): SealStamp {\n const segments = [\"sealed\"];\n const missing: SealStamp[\"missing\"] = [];\n\n const commits = facts.release?.commitCount?.value;\n if (commits === undefined) {\n missing.push({ fact: \"release.commitCount\", effect: \"seal stamp omits the commit count\" });\n } else {\n segments.push(`${formatCount(commits)} ${commits === 1 ? \"commit\" : \"commits\"}`);\n }\n\n const date = facts.release?.date?.value;\n if (date === undefined) {\n missing.push({ fact: \"release.date\", effect: \"seal stamp omits the date\" });\n } else {\n segments.push(date);\n }\n\n return { segments, missing };\n}\n","// Template: release hero\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\nimport { sealStamp } from \"./primitives/seal.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n version: z.string(),\n headline: z.string(),\n subheadline: z.string(),\n cta: z.string(),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n showCta: z.boolean(),\n showLogo: z.boolean(),\n seal: z.array(z.string()),\n});\n\nexport type ReleaseHeroProps = z.infer<typeof propsSchema>;\n\nexport const releaseHero: TemplateDefinition = {\n id: \"release-hero\",\n events: [\"release\"],\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone;\n return {\n headline: { maxLines: 2, maxFontSize: 72, minFontSize: 48, step: 4, box: { width } },\n subheadline: { maxLines: 2, maxFontSize: 32, minFontSize: 24, step: 2, box: { width } },\n cta: { maxLines: 1, maxFontSize: 28, minFontSize: 22, step: 2, box: { width: Math.min(480, width) } },\n };\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return {\n headline: props.headline,\n subheadline: props.subheadline,\n cta: props.cta,\n };\n },\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n if (slot === \"headline\") {\n return { family: props.headingFamily, weight: props.headingWeight, lineHeight: 1.1 };\n }\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (facts.project.npmPackage === undefined && facts.project.url === undefined) {\n missing.push({ fact: \"project.npmPackage\", effect: \"cta uses project name\" });\n }\n const showLogo = brand.logo !== undefined;\n if (!showLogo) {\n missing.push({ fact: \"brand.logo\", effect: \"logo hidden\" });\n }\n const seal = sealStamp(facts);\n missing.push(...seal.missing);\n const version = facts.release?.version.value ?? \"\";\n return {\n props: {\n name: brand.name,\n version,\n headline: copy.headline,\n subheadline: copy.subheadline,\n cta: copy.cta,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n showCta: copy.cta.length > 0,\n seal: seal.segments,\n showLogo,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const headline = ctx.fitted.headline;\n const sub = ctx.fitted.subheadline;\n const cta = ctx.fitted.cta;\n const compact = ctx.format.height <= 640;\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"space-between\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n position: \"relative\",\n }}\n >\n {/* The right half was empty on every hero. A large, faint mark fills it without\n competing with the headline, and reads as the seal rather than as decoration. */}\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <div\n style={{\n display: \"flex\",\n position: \"absolute\",\n right: -Math.round(ctx.format.height * 0.12),\n top: Math.round(ctx.format.height * 0.18),\n opacity: 0.06,\n }}\n >\n <img\n src={ctx.logoSrc}\n width={Math.round(ctx.format.height * 0.72)}\n height={Math.round(ctx.format.height * 0.72)}\n />\n </div>\n ) : undefined}\n <div style={{ display: \"flex\", flexDirection: \"row\", alignItems: \"center\", gap: 20 }}>\n {props.showLogo && ctx.logoSrc !== undefined ? (\n <img src={ctx.logoSrc} width={compact ? 56 : 72} height={compact ? 56 : 72} />\n ) : undefined}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 28,\n color: colors.foreground,\n }}\n >\n {props.name}\n </div>\n {props.version.length > 0 ? (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n backgroundColor: colors.card,\n borderRadius: props.radius,\n paddingTop: 6,\n paddingBottom: 6,\n paddingLeft: 14,\n paddingRight: 14,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.foreground,\n }}\n >\n {`v${props.version}`}\n </div>\n </div>\n ) : undefined}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: headline?.fontSize ?? 64,\n color: colors.foreground,\n lineHeight: 1.1,\n }}\n >\n {headline?.text ?? props.headline}\n </div>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: sub?.fontSize ?? 28,\n color: colors.muted,\n lineHeight: 1.25,\n }}\n >\n {sub?.text ?? props.subheadline}\n </div>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"row\", justifyContent: \"space-between\", alignItems: \"flex-end\" }}>\n {props.showCta ? (\n <div\n style={{\n display: \"flex\",\n backgroundColor: colors.primary,\n borderRadius: props.radius,\n paddingTop: 14,\n paddingBottom: 14,\n paddingLeft: 24,\n paddingRight: 24,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: cta?.fontSize ?? 24,\n color: colors.background,\n }}\n >\n {cta?.text ?? props.cta}\n </div>\n </div>\n ) : (\n <div />\n )}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n gap: 6,\n }}\n >\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.headingWeight,\n fontSize: 20,\n color: colors.primary,\n }}\n >\n {props.seal.join(\" \\u00b7 \")}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n </div>\n </div>\n );\n },\n};\n","// Template: what's new list\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { z } from \"zod\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n name: z.string(),\n version: z.string(),\n highlights: z.array(z.string()),\n headingFamily: z.string(),\n bodyFamily: z.string(),\n headingWeight: z.number(),\n bodyWeight: z.number(),\n radius: z.number(),\n});\n\nexport type ReleaseHighlightsProps = z.infer<typeof propsSchema>;\n\nexport const releaseHighlights: TemplateDefinition = {\n id: \"release-highlights\",\n events: [\"release\"],\n formats: [\"x\", \"linkedin\"],\n propsSchema,\n slots(format: Format) {\n const width = format.width - 2 * format.safeZone - 48;\n const slots: Record<string, { maxLines: number; maxFontSize: number; minFontSize: number; step: number; box: { width: number } }> = {};\n for (let index = 0; index < 4; index += 1) {\n slots[`highlight-${String(index)}`] = {\n maxLines: 2,\n maxFontSize: 32,\n minFontSize: 24,\n step: 2,\n box: { width },\n };\n }\n return slots;\n },\n slotText(raw) {\n const props = propsSchema.parse(raw);\n const text: Record<string, string> = {};\n props.highlights.forEach((line, index) => {\n text[`highlight-${String(index)}`] = line;\n });\n return text;\n },\n slotFont(raw) {\n const props = propsSchema.parse(raw);\n return { family: props.bodyFamily, weight: props.bodyWeight, lineHeight: 1.25 };\n },\n buildProps(facts: Facts, copy: Copy, brand: Brand) {\n const missing = [];\n if (copy.highlights.length === 0) {\n missing.push({ fact: \"release.features\", effect: \"highlights list empty\" });\n }\n return {\n props: {\n name: brand.name,\n version: facts.release?.version.value ?? \"\",\n highlights: copy.highlights,\n headingFamily: brand.fonts.heading.family,\n bodyFamily: brand.fonts.body.family,\n headingWeight: brand.fonts.heading.weight,\n bodyWeight: brand.fonts.body.weight,\n radius: brand.radius,\n },\n missing,\n };\n },\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const pad = ctx.format.safeZone;\n const title = props.version.length > 0 ? `What's new in v${props.version}` : \"What's new\";\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n padding: pad,\n gap: 28,\n }}\n >\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 22,\n color: colors.primary,\n }}\n >\n {props.name}\n </div>\n <div\n style={{\n fontFamily: props.headingFamily,\n fontWeight: props.headingWeight,\n fontSize: 48,\n color: colors.foreground,\n }}\n >\n {title}\n </div>\n </div>\n {/*\n Grow the list to fill the card and centre it. A release with one or two highlights\n used to leave most of the card empty, which reads as a broken render rather than a\n small release.\n */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: props.highlights.length > 2 ? \"flex-start\" : \"center\",\n gap: props.highlights.length > 2 ? 16 : 20,\n }}\n >\n {props.highlights.map((line, index) => {\n const fitted = ctx.fitted[`highlight-${String(index)}`];\n const breaking = line.startsWith(\"Breaking:\");\n return (\n <div\n key={String(index)}\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"flex-start\",\n gap: 16,\n backgroundColor: colors.card,\n borderRadius: props.radius,\n padding: 18,\n }}\n >\n <div\n style={{\n width: 12,\n height: 12,\n borderRadius: 6,\n backgroundColor: breaking ? colors.accent : colors.primary,\n marginTop: 10,\n }}\n />\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: fitted?.fontSize ?? 28,\n color: colors.foreground,\n lineHeight: 1.25,\n }}\n >\n {fitted?.text ?? line}\n </div>\n </div>\n );\n })}\n </div>\n {ctx.attribution ? (\n <div\n style={{\n fontFamily: props.bodyFamily,\n fontWeight: props.bodyWeight,\n fontSize: 18,\n color: colors.muted,\n marginTop: \"auto\",\n }}\n >\n made with shipseal.dev\n </div>\n ) : undefined}\n </div>\n );\n },\n};\n","// zod schemas for Facts, Fact<T>, Provenance\n// Spec: docs/PROJECT_PLAN.md §9\n\nimport { z } from \"zod\";\n\nexport const SOURCE_IDS = [\n \"git\",\n \"package-json\",\n \"readme\",\n \"changelog\",\n \"github-api\",\n \"npm-api\",\n \"bench-file\",\n \"user-config\",\n \"brand\",\n] as const;\n\nexport const sourceIdSchema = z.enum(SOURCE_IDS);\nexport type SourceId = z.infer<typeof sourceIdSchema>;\n\nexport const provenanceSchema = z.object({\n source: sourceIdSchema,\n ref: z.string().min(1),\n fetchedAt: z.iso.datetime(),\n});\nexport type Provenance = z.infer<typeof provenanceSchema>;\n\nexport function factSchema<T extends z.ZodType>(valueSchema: T) {\n return z.object({\n value: valueSchema,\n provenance: provenanceSchema,\n });\n}\n\nexport type Fact<T> = {\n value: T;\n provenance: Provenance;\n};\n\nconst stringFact = factSchema(z.string());\nconst numberFact = factSchema(z.number());\nconst stringListFact = factSchema(z.array(z.string()));\nconst codeSnippetFact = factSchema(\n z.object({\n code: z.string(),\n lang: z.string(),\n }),\n);\nconst betterFact = factSchema(z.enum([\"lower\", \"higher\"]));\n\nexport const storyPageSchema = z.object({\n kind: z.enum([\"cover\", \"change\", \"code\", \"comparison\", \"upgrade\"]),\n title: stringFact,\n body: stringFact,\n before: stringFact.optional(),\n after: stringFact.optional(),\n});\nexport type StoryPage = z.infer<typeof storyPageSchema>;\n\nexport const factsSchema = z.object({\n story: z.array(storyPageSchema).optional(),\n project: z.object({\n name: stringFact,\n tagline: stringFact.optional(),\n url: stringFact.optional(),\n repo: stringFact.optional(),\n npmPackage: stringFact.optional(),\n cli: factSchema(z.boolean()).optional(),\n license: stringFact.optional(),\n }),\n release: z\n .object({\n version: stringFact,\n tag: stringFact,\n kind: factSchema(z.enum([\"major\", \"minor\", \"patch\"])).optional(),\n headline: stringFact.optional(),\n subheadline: stringFact.optional(),\n previousVersion: stringFact.optional(),\n date: stringFact,\n features: z.array(stringFact),\n fixes: z.array(stringFact),\n breaking: z.array(stringFact),\n commitCount: numberFact.optional(),\n contributors: stringListFact.optional(),\n codeSnippet: codeSnippetFact.optional(),\n })\n .optional(),\n metrics: z\n .object({\n stars: numberFact.optional(),\n weeklyDownloads: numberFact.optional(),\n contributorCount: numberFact.optional(),\n })\n .optional(),\n bench: z\n .object({\n title: stringFact,\n metrics: z.array(\n z.object({\n label: stringFact,\n before: numberFact,\n after: numberFact,\n unit: stringFact,\n better: betterFact,\n }),\n ),\n note: stringFact.optional(),\n })\n .optional(),\n milestone: z\n .object({\n metric: stringFact,\n threshold: numberFact,\n })\n .optional(),\n});\n\nexport type Facts = z.infer<typeof factsSchema>;\n","// One page of a release story. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n//\n// The kind on the page decides the body treatment: `code` uses the mono family and preserves\n// whitespace, `comparison` lays out two supplied screenshots, everything else is prose. The\n// brand style decides the chrome: editorial adds rules, terminal adds a framed body.\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { MONO_ADVANCE } from \"./code-card.js\";\nimport { storyPageSchema } from \"../facts/schema.js\";\nimport type { Format } from \"../formats.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { themeColors } from \"./theme.js\";\n\nconst propsSchema = z.object({\n page: storyPageSchema,\n name: z.string(),\n version: z.string(),\n heading: z.string(),\n body: z.string(),\n mono: z.string(),\n weight: z.number(),\n});\n\nconst HEADER_HEIGHT = 36;\nconst BODY_PAD = 24;\nconst CODE_LINE_HEIGHT = 1.35;\nconst CODE_MIN_FONT_SIZE = 14;\nconst FOOTER_ALLOWANCE = 144;\nconst TALL_THRESHOLD = 900;\n\nfunction geometry(format: Format) {\n const tall = format.height > TALL_THRESHOLD;\n const titleHeight = tall ? 220 : 112;\n return {\n tall,\n titleHeight,\n width: format.width - 2 * format.safeZone,\n bodyHeight: format.height - 2 * format.safeZone - titleHeight - FOOTER_ALLOWANCE,\n };\n}\n\nconst NO_BORDER = \"0px solid transparent\";\n\n/**\n * Monospace `pre` text does not wrap, so the generic line-count fitter cannot keep it inside\n * the card: it reports two lines that fit and the long one runs off the right edge. Mono\n * glyphs are a constant fraction of the em, so the widest line gives a size directly. Same\n * approach as code-card, which is why MONO_ADVANCE is shared rather than copied.\n */\nfunction codeFontSize(text: string, box: { width: number; height: number }, max: number): number {\n const lines = text.split(\"\\n\");\n const longest = Math.max(1, ...lines.map((line) => line.length));\n const byWidth = box.width / (longest * MONO_ADVANCE);\n const byHeight = box.height / (lines.length * CODE_LINE_HEIGHT);\n return Math.max(CODE_MIN_FONT_SIZE, Math.min(max, Math.floor(Math.min(byWidth, byHeight))));\n}\n\n/**\n * A body the reader is meant to copy and run: a code snippet, or upgrade instructions the\n * maintainer supplied. Generated upgrade prose (a link to the release notes) is not one, so\n * the provenance decides rather than the page kind alone.\n */\nfunction isCommand(page: z.infer<typeof propsSchema>[\"page\"]): boolean {\n return (\n page.kind === \"code\" ||\n (page.kind === \"upgrade\" && page.body.provenance.source === \"user-config\")\n );\n}\n\nexport const storyPage: TemplateDefinition = {\n id: \"story-page\",\n events: [\"release\"],\n formats: [\"og\", \"github-social\", \"x\", \"linkedin\", \"square\", \"portrait\", \"producthunt\"],\n propsSchema,\n\n slots(format) {\n const { width, titleHeight, bodyHeight, tall } = geometry(format);\n return {\n name: { maxLines: 1, maxFontSize: 24, minFontSize: 18, step: 2, box: { width: width - 300 } },\n version: { maxLines: 1, maxFontSize: 22, minFontSize: 16, step: 2, box: { width: 220 } },\n // The floor sits above the body's ceiling on purpose. Fitted independently, a long title\n // shrank to 28 while the body stayed at 34, so the page read with its hierarchy inverted.\n // Truncating with a manifest warning is the honest outcome, not a title smaller than its\n // own paragraph.\n title: {\n // Four lines on a tall canvas. Change titles truncated on 6 of the 20 repositories\n // surveyed on 2026-09-15, and a portrait page has the room to spare.\n maxLines: tall ? 4 : 2,\n maxFontSize: tall ? 64 : 48,\n minFontSize: tall ? 36 : 30,\n step: 2,\n box: { width: width - 32, height: titleHeight },\n },\n body: {\n maxLines: Math.floor(bodyHeight / 30),\n maxFontSize: tall ? 34 : 28,\n minFontSize: 20,\n step: 2,\n box: { width: width - 48, height: bodyHeight - 48 },\n },\n };\n },\n\n slotText(raw) {\n const props = propsSchema.parse(raw);\n return {\n name: props.name,\n version: props.version,\n title: props.page.title.value,\n body: props.page.body.value,\n };\n },\n\n slotFont(raw, slot) {\n const props = propsSchema.parse(raw);\n const mono = slot === \"body\" && isCommand(props.page);\n return {\n family: mono ? props.mono : slot === \"title\" ? props.heading : props.body,\n weight: slot === \"title\" ? props.weight : 400,\n lineHeight: mono ? 1.35 : 1.2,\n whiteSpace: mono ? \"pre\" : \"normal\",\n };\n },\n\n buildProps(facts, _copy, brand) {\n const page = facts.story?.[0];\n if (page === undefined) {\n // Reachable when release.templates names story-page directly, so this has to be a\n // typed error rather than a schema failure from inside generate().\n throw new ShipsealError(\n \"story-page.no-page\",\n \"The story-page template has no story page to render.\",\n \"Run shipseal story to build a story pack. Do not list story-page in release.templates.\",\n );\n }\n return {\n props: {\n page,\n name: brand.name,\n version: facts.release?.tag.value ?? \"\",\n heading: brand.style === \"terminal\" ? brand.fonts.mono.family : brand.fonts.heading.family,\n body: brand.fonts.body.family,\n mono: brand.fonts.mono.family,\n weight: brand.fonts.heading.weight,\n },\n missing: [],\n };\n },\n\n render(raw, ctx) {\n const props = propsSchema.parse(raw);\n const colors = themeColors(ctx.brand, ctx.theme);\n const { tall, bodyHeight, width } = geometry(ctx.format);\n const editorial = ctx.brand.style === \"editorial\";\n const terminal = ctx.brand.style === \"terminal\";\n const code = isCommand(props.page);\n const comparison = props.page.kind === \"comparison\";\n const title = ctx.fitted.title;\n const body = ctx.fitted.body;\n const hasBody = props.page.body.value.trim().length > 0;\n const bodyText = body?.text ?? props.page.body.value;\n const bodyFontSize = code\n ? codeFontSize(\n bodyText,\n { width: width - 2 * BODY_PAD, height: bodyHeight - 2 * BODY_PAD },\n tall ? 34 : 28,\n )\n : (body?.fontSize ?? 28);\n const paneWidth = tall ? width : (width - 16) / 2;\n const paneHeight = tall ? (bodyHeight - 16) / 2 : bodyHeight;\n\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n width: \"100%\",\n height: \"100%\",\n backgroundColor: colors.background,\n color: colors.foreground,\n padding: ctx.format.safeZone,\n gap: 24,\n borderTop: editorial ? `16px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n height: HEADER_HEIGHT,\n flexShrink: 0,\n borderBottom: terminal ? `1px solid ${colors.muted}` : NO_BORDER,\n paddingBottom: terminal ? 12 : 0,\n }}\n >\n <div style={{ display: \"flex\", gap: 12, alignItems: \"center\" }}>\n {ctx.logoSrc !== undefined ? <img src={ctx.logoSrc} width={32} height={32} /> : undefined}\n <div\n style={{\n fontFamily: terminal ? props.mono : props.body,\n fontWeight: 400,\n fontSize: ctx.fitted.name?.fontSize ?? 24,\n color: colors.primary,\n }}\n >\n {ctx.fitted.name?.text ?? props.name}\n </div>\n </div>\n <div\n style={{\n fontFamily: props.mono,\n fontWeight: 400,\n fontSize: ctx.fitted.version?.fontSize ?? 22,\n color: colors.muted,\n }}\n >\n {ctx.fitted.version?.text ?? props.version}\n </div>\n </div>\n\n {/*\n Title and body are one block, centred in whatever space the header and footer leave.\n They used to sit in two fixed-height boxes, so a short cover or closing page put its\n content in the top third and left the rest of a 1080x1350 canvas empty.\n */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexGrow: 1,\n justifyContent: \"center\",\n gap: 24,\n minHeight: 0,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n flexShrink: 0,\n paddingLeft: editorial ? 24 : 0,\n borderLeft: editorial ? `8px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n fontFamily: props.heading,\n fontWeight: props.weight,\n fontSize: title?.fontSize ?? 48,\n lineHeight: 1.2,\n maxWidth: width - (editorial ? 32 : 0),\n }}\n >\n {title?.text ?? props.page.title.value}\n </div>\n </div>\n\n {comparison ? (\n <div\n style={{\n display: \"flex\",\n flexDirection: tall ? \"column\" : \"row\",\n gap: 16,\n height: bodyHeight,\n }}\n >\n {[\"before\", \"after\"].map((label) => (\n <div\n key={label}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n width: paneWidth,\n height: paneHeight,\n }}\n >\n <div style={{ fontFamily: props.body, fontSize: 20, color: colors.muted }}>\n {label === \"before\" ? \"Before\" : \"After\"}\n </div>\n <img\n src={`story-${label}`}\n width={paneWidth}\n height={paneHeight - HEADER_HEIGHT}\n style={{ objectFit: \"contain\" }}\n />\n </div>\n ))}\n </div>\n ) : hasBody ? (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n // Top-aligned: centring a short paragraph in a full-height box leaves a hole\n // in the middle of the card rather than margin at the bottom.\n justifyContent: \"flex-start\",\n maxHeight: bodyHeight,\n padding: terminal || code ? BODY_PAD : 0,\n backgroundColor: terminal || code ? colors.card : \"transparent\",\n borderRadius: terminal ? 0 : ctx.brand.radius,\n borderLeft: terminal ? `3px solid ${colors.primary}` : NO_BORDER,\n }}\n >\n <div\n style={{\n fontFamily: code ? props.mono : props.body,\n fontWeight: 400,\n fontSize: bodyFontSize,\n lineHeight: code ? CODE_LINE_HEIGHT : 1.2,\n whiteSpace: code ? \"pre\" : \"normal\",\n color: colors.foreground,\n }}\n >\n {bodyText}\n </div>\n </div>\n ) : undefined}\n </div>\n\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n flexShrink: 0,\n fontFamily: props.mono,\n fontWeight: 400,\n fontSize: 16,\n color: colors.muted,\n }}\n >\n <div style={{ fontFamily: props.mono }}>\n {comparison ? \"Supplied screenshots\" : \"Sources in manifest.json\"}\n </div>\n {ctx.attribution ? (\n <div style={{ fontFamily: props.mono }}>made with shipseal.dev</div>\n ) : undefined}\n </div>\n </div>\n );\n },\n};\n","// Template registry\n// Spec: docs/PROJECT_PLAN.md §14.3\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { TemplateDefinition } from \"./contract.js\";\nimport { bench } from \"./bench.js\";\nimport { codeCard } from \"./code-card.js\";\nimport { milestone } from \"./milestone.js\";\nimport { releaseHero } from \"./release-hero.js\";\nimport { releaseHighlights } from \"./release-highlights.js\";\nimport { storyPage } from \"./story-page.js\";\n\nconst templates = [releaseHero, releaseHighlights, codeCard, milestone, bench, storyPage] as const;\n\nexport function getTemplate(id: string): TemplateDefinition {\n const found = templates.find((template) => template.id === id);\n if (found === undefined) {\n throw new ShipsealError(\n \"template.unknown\",\n `Unknown template \"${id}\".`,\n `Use one of: ${templates.map((template) => template.id).join(\", \")}.`,\n );\n }\n return found;\n}\n\nexport function templatesForEvent(kind: \"release\" | \"milestone\" | \"bench\"): TemplateDefinition[] {\n return templates.filter((template) => template.events.includes(kind));\n}\n\nexport const RELEASE_TEMPLATE_IDS = [\"release-hero\", \"release-highlights\", \"code-card\"] as const;\n","// The pure pipeline: facts + copy + brand + templates -> rendered files (no network I/O)\n// Spec: docs/PROJECT_PLAN.md §6.1\n\nimport { percentChange } from \"../bench/percent.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport type { ShipsealEvent } from \"./events.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { fitText, type FittedText } from \"../fit/fit-text.js\";\nimport { FORMATS, type Format, type FormatId } from \"../formats.js\";\nimport type { ImageFormat, RenderOptions, RendererAdapter } from \"../render/adapter.js\";\nimport { emptyCodeLines } from \"../templates/code-card.js\";\nimport type { ManifestMissing, RenderContext, TemplateDefinition } from \"../templates/contract.js\";\nimport { highlightCode } from \"../templates/highlight.js\";\nimport { getTemplate } from \"../templates/registry.js\";\n\n/**\n * Digest via WebCrypto, not `node:crypto`. The browser demo imports `generate()`, so nothing\n * in the pure core may reach for a Node builtin. Do not \"simplify\" this back to createHash.\n */\nasync function sha256Hex(bytes: Uint8Array): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", Uint8Array.from(bytes));\n return Array.from(new Uint8Array(digest))\n .map((value) => value.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nexport interface GenerateInput {\n event: ShipsealEvent;\n facts: Facts;\n brand: Brand;\n config: Config;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n renderer: RendererAdapter;\n themes: Array<\"dark\" | \"light\">;\n generatedAt: string;\n logos?: { light?: Uint8Array; dark?: Uint8Array };\n images?: Array<{ src: string; data: Uint8Array }>;\n}\n\nexport interface GeneratedFile {\n fileName: string;\n template: string;\n format: FormatId;\n theme: \"dark\" | \"light\";\n width: number;\n height: number;\n bytes: Uint8Array;\n sha256: string;\n}\n\nexport interface FitWarning {\n type: \"fit-warning\";\n template: string;\n format: FormatId;\n slot: string;\n action: \"truncated\";\n}\n\nexport interface GenerateResult {\n files: GeneratedFile[];\n warnings: FitWarning[];\n missing: Array<ManifestMissing & { template: string }>;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n generatedAt: string;\n computed: Record<string, { value: unknown; computedFrom: string[] }>;\n}\n\nexport async function generate(input: GenerateInput): Promise<GenerateResult> {\n const templateIds = templateIdsFor(input.event, input.config);\n const formatIds = input.config.formats ?? [\"og\", \"github-social\", \"x\", \"linkedin\"];\n const imageFormat: ImageFormat = input.config.output?.imageFormat ?? \"png\";\n const attribution = input.config.attribution !== false;\n const files: GeneratedFile[] = [];\n const warnings: FitWarning[] = [];\n const missing: Array<ManifestMissing & { template: string }> = [];\n const recordedMissing = new Set<string>();\n const omitThemeSuffix = input.themes.length === 1;\n\n for (const templateId of templateIds) {\n const template = getTemplate(templateId);\n if (!template.events.includes(input.event.kind)) {\n continue;\n }\n for (const formatId of formatIds) {\n if (!template.formats.includes(formatId)) {\n continue;\n }\n const format = FORMATS[formatId];\n for (const theme of input.themes) {\n // Formats and themes render sequentially so fit warnings stay attached to the right file.\n // eslint-disable-next-line no-await-in-loop\n const copy = await copyForTemplate(template.id, input.copy, input.facts, theme);\n const built = template.buildProps(input.facts, copy, input.brand);\n const props = template.propsSchema.parse(built.props);\n if (!recordedMissing.has(template.id)) {\n recordedMissing.add(template.id);\n for (const item of built.missing) {\n missing.push({ template: template.id, fact: item.fact, effect: item.effect });\n }\n }\n // eslint-disable-next-line no-await-in-loop\n const { fitted, truncated } = await fitSlots(input.renderer, template, props, format);\n for (const slot of truncated) {\n warnings.push({\n type: \"fit-warning\",\n template: template.id,\n format: formatId,\n slot,\n action: \"truncated\",\n });\n }\n const logo = logoForTheme(input.logos, theme);\n const ctx: RenderContext = {\n format,\n theme,\n brand: input.brand,\n fitted,\n attribution,\n };\n if (logo !== undefined) {\n ctx.logoSrc = \"shipseal-logo\";\n }\n const jsx = template.render(props, ctx);\n // eslint-disable-next-line no-await-in-loop\n const node = await input.renderer.fromJsx(jsx);\n const renderOpts: RenderOptions = {\n width: format.width,\n height: format.height,\n format: imageFormat,\n };\n if (logo !== undefined) {\n renderOpts.images = [{ src: \"shipseal-logo\", data: logo }];\n }\n if (input.images !== undefined) {\n renderOpts.images = [...(renderOpts.images ?? []), ...input.images];\n }\n // eslint-disable-next-line no-await-in-loop\n const bytes = await input.renderer.render(node, renderOpts);\n const fileName = outputName(template.id, formatId, theme, omitThemeSuffix, imageFormat);\n // eslint-disable-next-line no-await-in-loop -- one digest per rendered file\n const sha256 = await sha256Hex(bytes);\n files.push({\n fileName,\n template: template.id,\n format: formatId,\n theme,\n width: format.width,\n height: format.height,\n bytes,\n sha256,\n });\n }\n }\n }\n\n return {\n files,\n warnings,\n missing,\n facts: input.facts,\n copy: input.copy,\n copyMode: input.copyMode,\n generatedAt: input.generatedAt,\n computed: computedFromFacts(input.facts),\n };\n}\n\nfunction templateIdsFor(event: ShipsealEvent, config: Config): string[] {\n if (event.kind === \"milestone\") {\n return [\"milestone\"];\n }\n if (event.kind === \"bench\") {\n return [\"bench\"];\n }\n return config.release?.templates ?? [\"release-hero\", \"release-highlights\", \"code-card\"];\n}\n\nfunction computedFromFacts(facts: Facts): Record<string, { value: unknown; computedFrom: string[] }> {\n const out: Record<string, { value: unknown; computedFrom: string[] }> = {};\n if (facts.bench === undefined) {\n return out;\n }\n facts.bench.metrics.forEach((metric, index) => {\n const change = percentChange(metric.before.value, metric.after.value, metric.better.value);\n const prefix = `bench.metrics[${String(index)}]`;\n out[`${prefix}.percent`] = {\n value: change.signed,\n computedFrom: [`${prefix}.before`, `${prefix}.after`, `${prefix}.better`],\n };\n });\n return out;\n}\n\nasync function fitSlots(\n renderer: RendererAdapter,\n template: TemplateDefinition,\n props: unknown,\n format: Format,\n): Promise<{ fitted: Record<string, FittedText>; truncated: string[] }> {\n const specs = template.slots(format);\n const texts = template.slotText(props);\n const fitted: Record<string, FittedText> = {};\n const truncated: string[] = [];\n for (const [slot, spec] of Object.entries(specs)) {\n const text = texts[slot];\n if (text === undefined) {\n continue;\n }\n const font = template.slotFont(props, slot);\n const fitFont: { family: string; lineHeight: number; weight: number; whiteSpace?: \"normal\" | \"pre\" } = {\n family: font.family,\n lineHeight: font.lineHeight,\n weight: font.weight,\n };\n if (font.whiteSpace !== undefined) {\n fitFont.whiteSpace = font.whiteSpace;\n }\n // eslint-disable-next-line no-await-in-loop -- sizes are sequential per slot spec\n const result = await fitText(renderer, text, spec, fitFont);\n fitted[slot] = result;\n if (result.truncated) {\n truncated.push(slot);\n }\n }\n return { fitted, truncated };\n}\n\nfunction outputName(\n template: string,\n format: FormatId,\n theme: \"dark\" | \"light\",\n omitTheme: boolean,\n imageFormat: string,\n): string {\n const themePart = omitTheme ? \"\" : `-${theme}`;\n return `${template}-${format}${themePart}.${imageFormat}`;\n}\n\nfunction logoForTheme(\n logos: GenerateInput[\"logos\"],\n theme: \"dark\" | \"light\",\n): Uint8Array | undefined {\n if (logos === undefined) {\n return undefined;\n }\n if (theme === \"dark\") {\n return logos.dark ?? logos.light;\n }\n return logos.light ?? logos.dark;\n}\n\nasync function copyForTemplate(\n templateId: string,\n copy: Copy,\n facts: Facts,\n theme: \"dark\" | \"light\",\n): Promise<Copy> {\n if (templateId !== \"code-card\") {\n return copy;\n }\n const snippet = facts.release?.codeSnippet?.value;\n if (snippet === undefined) {\n return { ...copy, codeLines: emptyCodeLines() };\n }\n return { ...copy, codeLines: await highlightCode(snippet.code, snippet.lang, theme) };\n}\n","// fact() helper that attaches provenance\n// Spec: docs/PROJECT_PLAN.md §9.1\n\nimport type { Fact, SourceId } from \"./schema.js\";\n\nexport function fact<T>(\n value: T,\n provenance: { source: SourceId; ref: string; fetchedAt?: string },\n): Fact<T> {\n const fetchedAt = provenance.fetchedAt ?? new Date().toISOString();\n return {\n value,\n provenance: {\n source: provenance.source,\n ref: provenance.ref,\n fetchedAt,\n },\n };\n}\n","// Merge partial Facts from sources. Later sources fill holes.\n// Changelog feature lists replace git commit lists when present.\n// Spec: docs/PROJECT_PLAN.md §12\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { Facts } from \"./schema.js\";\nimport type { PartialFacts, PartialMetrics, PartialMilestone, PartialProject, PartialRelease } from \"./partial.js\";\n\nexport function mergeFacts(parts: PartialFacts[]): Facts {\n const project: PartialProject = {};\n const release: PartialRelease = {};\n const metrics: PartialMetrics = {};\n const milestone: PartialMilestone = {};\n let bench: Facts[\"bench\"];\n\n for (const part of parts) {\n fillObject(project, part.project);\n mergeRelease(release, part.release);\n fillObject(metrics, part.metrics);\n fillObject(milestone, part.milestone);\n if (part.bench !== undefined) {\n bench = part.bench;\n }\n }\n\n if (project.name === undefined) {\n throw new ShipsealError(\n \"facts.missing-name\",\n \"Could not determine the project name.\",\n \"Add a name field to package.json, or an H1 in README.md.\",\n );\n }\n\n const facts: Facts = {\n project: {\n name: project.name,\n },\n };\n if (project.tagline !== undefined) {\n facts.project.tagline = project.tagline;\n }\n if (project.url !== undefined) {\n facts.project.url = project.url;\n }\n if (project.repo !== undefined) {\n facts.project.repo = project.repo;\n }\n if (project.npmPackage !== undefined) {\n facts.project.npmPackage = project.npmPackage;\n }\n if (project.cli !== undefined) {\n facts.project.cli = project.cli;\n }\n if (project.license !== undefined) {\n facts.project.license = project.license;\n }\n\n // A partial release block is dropped, not fatal. `package.json#version` alone makes\n // `hasRelease` true on every project, so throwing here broke `bench` and `milestone`,\n // which do not need release facts at all (§6.3). The release event still errors, in\n // collectFacts, where the check knows the event kind.\n if (isCompleteRelease(release)) {\n facts.release = {\n version: release.version,\n tag: release.tag,\n date: release.date,\n features: release.features ?? [],\n fixes: release.fixes ?? [],\n breaking: release.breaking ?? [],\n };\n if (release.kind !== undefined) {\n facts.release.kind = release.kind;\n }\n if (release.headline !== undefined) {\n facts.release.headline = release.headline;\n }\n if (release.subheadline !== undefined) {\n facts.release.subheadline = release.subheadline;\n }\n if (release.previousVersion !== undefined) {\n facts.release.previousVersion = release.previousVersion;\n }\n if (release.commitCount !== undefined) {\n facts.release.commitCount = release.commitCount;\n }\n if (release.contributors !== undefined) {\n facts.release.contributors = release.contributors;\n }\n if (release.codeSnippet !== undefined) {\n facts.release.codeSnippet = release.codeSnippet;\n }\n }\n\n if (Object.keys(metrics).length > 0) {\n facts.metrics = metrics;\n }\n if (bench !== undefined) {\n facts.bench = bench;\n }\n if (milestone.metric !== undefined && milestone.threshold !== undefined) {\n facts.milestone = { metric: milestone.metric, threshold: milestone.threshold };\n }\n return facts;\n}\n\nfunction mergeRelease(target: PartialRelease, overlay: PartialRelease | undefined): void {\n if (overlay === undefined) {\n return;\n }\n fillObject(target, overlay, [\"features\", \"fixes\", \"breaking\"]);\n replaceList(target, overlay, \"features\");\n replaceList(target, overlay, \"fixes\");\n replaceList(target, overlay, \"breaking\");\n}\n\nfunction replaceList(\n target: PartialRelease,\n overlay: PartialRelease,\n key: \"features\" | \"fixes\" | \"breaking\",\n): void {\n const next = overlay[key];\n if (next !== undefined) {\n target[key] = next;\n }\n}\n\nfunction fillObject<T extends object>(target: T, overlay: T | undefined, skip: (keyof T)[] = []): void {\n if (overlay === undefined) {\n return;\n }\n const skipped = new Set(skip);\n for (const key of Object.keys(overlay) as (keyof T)[]) {\n if (skipped.has(key)) {\n continue;\n }\n const value = overlay[key];\n if (value !== undefined && target[key] === undefined) {\n target[key] = value;\n }\n }\n}\n\nfunction isCompleteRelease(\n release: PartialRelease,\n): release is PartialRelease &\n Required<Pick<PartialRelease, \"version\" | \"tag\" | \"date\">> {\n return release.version !== undefined && release.tag !== undefined && release.date !== undefined;\n}\n","// Benchmark JSON reader\n// Spec: docs/PROJECT_PLAN.md §12.7\n\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\n\nconst metricSchema = z.object({\n label: z.string().min(1),\n before: z.number().finite(),\n after: z.number().finite(),\n unit: z.string().min(1),\n better: z.enum([\"lower\", \"higher\"]),\n});\n\nconst benchFileSchema = z.object({\n title: z.string().min(1),\n metrics: z.array(metricSchema).min(1).max(3),\n note: z.string().optional(),\n});\n\nexport async function collectBenchFile(cwd: string, filePath = \".shipseal/bench.json\"): Promise<PartialFacts> {\n const resolved = isAbsolute(filePath) ? filePath : join(cwd, filePath);\n let raw: string;\n try {\n raw = await readFile(resolved, \"utf8\");\n } catch (error) {\n throw new ShipsealError(\n \"bench.missing-file\",\n `Benchmark file not found: ${filePath}.`,\n \"Write .shipseal/bench.json (title, metrics with before/after/unit/better), or pass --file <path>.\",\n { cause: error },\n );\n }\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch (error) {\n throw new ShipsealError(\n \"bench.invalid-json\",\n `Benchmark file is not valid JSON: ${filePath}.`,\n \"Fix the JSON syntax, then retry.\",\n { cause: error },\n );\n }\n const parsed = benchFileSchema.safeParse(json);\n if (!parsed.success) {\n throw new ShipsealError(\n \"bench.invalid-shape\",\n `Benchmark file is missing required fields: ${filePath}.`,\n 'Each metric needs label, before, after, unit, and better (\"lower\" or \"higher\"). At most 3 metrics.',\n );\n }\n const fetchedAt = new Date().toISOString();\n const ref = filePath;\n const bench: NonNullable<Facts[\"bench\"]> = {\n title: fact(parsed.data.title, { source: \"bench-file\", ref: `${ref}#title`, fetchedAt }),\n metrics: parsed.data.metrics.map((metric, index) => ({\n label: fact(metric.label, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].label`, fetchedAt }),\n before: fact(metric.before, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].before`, fetchedAt }),\n after: fact(metric.after, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].after`, fetchedAt }),\n unit: fact(metric.unit, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].unit`, fetchedAt }),\n better: fact(metric.better, { source: \"bench-file\", ref: `${ref}#metrics[${String(index)}].better`, fetchedAt }),\n })),\n };\n if (parsed.data.note !== undefined) {\n bench.note = fact(parsed.data.note, { source: \"bench-file\", ref: `${ref}#note`, fetchedAt });\n }\n return { bench };\n}\n","// README source: title, tagline, first fenced code block\n// Spec: docs/PROJECT_PLAN.md §12.3\n\nimport { readFile } from \"node:fs/promises\";\nimport { extname, join } from \"node:path\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nexport async function collectReadme(cwd: string): Promise<PartialFacts> {\n let markdown: string;\n try {\n markdown = await readFile(join(cwd, \"README.md\"), \"utf8\");\n } catch {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const out: PartialFacts = {};\n const h1 = extractH1(markdown);\n const tagline = extractTagline(markdown);\n const snippet = extractFirstCodeFence(markdown);\n\n const project: PartialProject = {};\n if (h1 !== undefined) {\n project.name = fact(h1, { source: \"readme\", ref: \"README.md H1\", fetchedAt });\n }\n if (tagline !== undefined) {\n project.tagline = fact(stripEmoji(tagline), {\n source: \"readme\",\n ref: \"README.md first paragraph\",\n fetchedAt,\n });\n }\n if (project.name !== undefined || project.tagline !== undefined) {\n out.project = project;\n }\n if (snippet !== undefined) {\n out.release = {\n codeSnippet: fact(snippet, {\n source: \"readme\",\n ref: \"README.md first fenced code block\",\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nexport async function collectConfiguredSnippet(\n cwd: string,\n spec: string,\n): Promise<PartialFacts> {\n const parsed = parseSnippetSpec(spec);\n if (parsed === undefined) {\n return {};\n }\n let contents: string;\n try {\n contents = await readFile(join(cwd, parsed.path), \"utf8\");\n } catch {\n return {};\n }\n const lines = contents.split(/\\r?\\n/);\n const slice = lines.slice(parsed.start - 1, parsed.end).join(\"\\n\");\n const fetchedAt = new Date().toISOString();\n return {\n release: {\n codeSnippet: fact(\n { code: slice, lang: langFromPath(parsed.path) },\n { source: \"user-config\", ref: spec, fetchedAt },\n ),\n },\n };\n}\n\n/**\n * Strip fenced code and HTML before reading prose out of a README.\n *\n * Skipping blocks that merely *start* with a fence is not enough. A `#` comment inside a YAML\n * example reads as a markdown H1, and a blank line inside a fence makes its body look like a\n * paragraph. Shipseal's own README hit both: the detected name became\n * \".github/workflows/shipseal.yml\" and the tagline became a chunk of workflow YAML.\n */\nfunction stripNonProse(markdown: string): string {\n return markdown\n .replace(/```[\\s\\S]*?```/g, \"\")\n .replace(/~~~[\\s\\S]*?~~~/g, \"\")\n .replace(/<[^>]+>/g, \"\");\n}\n\nexport function extractH1(markdown: string): string | undefined {\n const match = /^#\\s+(.+)$/m.exec(stripNonProse(markdown));\n const heading = match?.[1];\n if (heading === undefined) {\n return undefined;\n }\n return heading.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\").trim();\n}\n\nexport function extractTagline(markdown: string): string | undefined {\n const prose = stripNonProse(markdown);\n const h1 = /^#\\s+.+$/m.exec(prose);\n const start = h1 === null ? 0 : (h1.index ?? 0) + h1[0].length;\n for (const block of prose.slice(start).split(/\\n\\s*\\n/)) {\n const cleaned = stripBadges(block).trim();\n if (cleaned.length >= 20 && !cleaned.startsWith(\"#\") && !cleaned.startsWith(\"```\")) {\n return cleaned;\n }\n }\n return undefined;\n}\n\nexport function extractFirstCodeFence(markdown: string): { code: string; lang: string } | undefined {\n const match = /```([a-zA-Z0-9+-]+)\\n([\\s\\S]*?)```/.exec(markdown);\n if (match === null || match[1] === undefined || match[2] === undefined) {\n return undefined;\n }\n return { lang: match[1], code: match[2].replace(/\\n$/, \"\") };\n}\n\nfunction parseSnippetSpec(spec: string): { path: string; start: number; end: number } | undefined {\n const match = /^(?<path>.+)#L(?<start>\\d+)(?:-L(?<end>\\d+))?$/.exec(spec);\n if (match === null || match.groups === undefined) {\n return undefined;\n }\n const path = match.groups.path;\n const start = Number.parseInt(match.groups.start ?? \"0\", 10);\n const end = Number.parseInt(match.groups.end ?? match.groups.start ?? \"0\", 10);\n if (path === undefined || start < 1 || end < start) {\n return undefined;\n }\n return { path, start, end };\n}\n\nfunction langFromPath(path: string): string {\n const ext = extname(path).replace(\".\", \"\");\n if (ext === \"ts\") {\n return \"ts\";\n }\n if (ext === \"tsx\") {\n return \"tsx\";\n }\n if (ext === \"js\" || ext === \"mjs\" || ext === \"cjs\") {\n return \"js\";\n }\n if (ext === \"jsx\") {\n return \"jsx\";\n }\n return ext.length > 0 ? ext : \"text\";\n}\n\nfunction stripBadges(text: string): string {\n return text\n .replace(/\\[!\\[[^\\]]*]\\([^)]+\\)]\\([^)]+\\)/g, \"\")\n .replace(/!\\[[^\\]]*]\\([^)]+\\)/g, \"\")\n .replace(/<img[^>]*>/gi, \"\")\n .replace(/<[^>]+>/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n","// One cleaner for every line that becomes card text, whatever source it came from.\n//\n// There used to be two. `cleanChangelogItem` stripped fourteen patterns for the CLI path and\n// `cleanBullet` stripped five for the browser demo, so a GitHub release body kept the things a\n// CHANGELOG entry had removed. oven-sh/bun rendered a card headlined \"@dylan-conway\", a\n// contributor's handle, and astral-sh/ruff kept backslash-escaped brackets. Same input shape,\n// two different answers, because the rules lived in two places.\n\n/** Markdown escapes a maintainer never meant to see rendered: \\[ruff\\] becomes [ruff]. */\nconst MARKDOWN_ESCAPE = /\\\\([[\\]()*_`~#+\\-.!])/g;\n\nexport function cleanReleaseLine(item: string): string {\n return (\n item\n .replace(/^\\s*[-*]\\s*/, \"\")\n // Commit and pull request references: a card is not an audit trail.\n .replace(/\\[`[a-f0-9]{7,40}`]\\([^)]+\\)/gi, \"\")\n .replace(/^[a-f0-9]{7,40}:\\s*/i, \"\")\n .replace(/\\(#\\d+\\)/g, \"\")\n .replace(/\\[#\\d+]\\([^)]+\\)/g, \"\")\n .replace(/#\\d+\\b/g, \"\")\n // Credit lines. These are why a handle became a headline.\n .replace(/Thanks\\s+\\[@[\\w-]+]\\([^)]+\\)!?\\s*-?\\s*/gi, \"\")\n .replace(/\\[@[\\w-]+]\\([^)]+\\)/g, \"\")\n .replace(/\\(@[\\w-]+\\)/g, \"\")\n .replace(/\\s+by\\s+@[\\w-]+/gi, \"\")\n .replace(/@[\\w-]+/g, \"\")\n .replace(/^Thanks\\s*!?\\s*-?\\s*/i, \"\")\n // Markdown: images dropped, links reduced to their text, HTML and emphasis removed.\n .replaceAll(/!\\[[^\\]]*\\]\\([^)]*\\)/g, \"\")\n .replaceAll(/\\[([^\\]]+)\\]\\([^)]*\\)/g, \"$1\")\n .replaceAll(/<[^>]*>/g, \"\")\n .replaceAll(MARKDOWN_ESCAPE, \"$1\")\n .replaceAll(/[*`]/g, \"\")\n // After links are reduced: `([4379bf0](url))` only looks like a bare hash by this point.\n .replaceAll(/\\(\\s*[a-f0-9]{6,40}\\s*\\)/gi, \"\")\n // Leading scope labels, as in \"[/lightbox] Add option to ...\".\n .replace(/^\\[[^\\]]{1,24}\\]\\s*/, \"\")\n .replace(/^\\s*[-*]\\s*/, \"\")\n // Whatever the removals left behind.\n .replace(/\\s*\\(\\s*\\)/g, \"\")\n .replace(/\\s+([,.;:])/g, \"$1\")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/[\\s,;:-]+$/, \"\")\n .replace(/\\.$/, \"\")\n );\n}\n","// Keep a Changelog + Changesets parsing\n// Spec: docs/PROJECT_PLAN.md §12.4\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { extractFirstCodeFence } from \"./readme.js\";\nimport { cleanReleaseLine } from \"./release-line.js\";\n\nexport async function collectChangelog(\n cwd: string,\n version: string | undefined,\n changelogPath = \"CHANGELOG.md\",\n): Promise<PartialFacts> {\n if (version === undefined) {\n return {};\n }\n let markdown: string;\n try {\n markdown = await readFile(join(cwd, changelogPath), \"utf8\");\n } catch {\n return {};\n }\n const section = findVersionSection(markdown, version);\n if (section === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const features: Fact<string>[] = [];\n const fixes: Fact<string>[] = [];\n const breaking: Fact<string>[] = [];\n\n for (const group of parseGroups(section.body)) {\n const bucket = bucketForHeading(group.heading);\n if (bucket === undefined) {\n continue;\n }\n for (const item of group.items) {\n const cleaned = cleanChangelogItem(item);\n if (cleaned.length === 0) {\n continue;\n }\n const entry = fact(cleaned, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading} ${group.heading}: ${item}`,\n fetchedAt,\n });\n if (bucket === \"features\") {\n features.push(entry);\n } else if (bucket === \"fixes\") {\n fixes.push(entry);\n } else {\n breaking.push(entry);\n }\n }\n }\n\n const out: PartialFacts = {\n release: {\n version: fact(version.replace(/^v/, \"\"), {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n tag: fact(version.startsWith(\"v\") ? version : `v${version}`, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n features,\n fixes,\n breaking,\n },\n };\n // An author can title their own release from inside the notes, where the words already live:\n // <!-- shipseal: headline \"Milestone cards are here\" -->\n // Deterministic copy can only reuse a changelog sentence, and those are written for\n // maintainers. This is the cheap way to write for an audience without turning on the LLM.\n for (const slot of [\"headline\", \"subheadline\"] as const) {\n const marker = new RegExp(`<!--\\\\s*shipseal:\\\\s*${slot}\\\\s+\"([^\"]+)\"\\\\s*-->`).exec(section.body);\n const text = marker?.[1]?.trim();\n if (text !== undefined && text.length > 0) {\n out.release = {\n ...out.release,\n [slot]: fact(text, {\n source: \"user-config\",\n ref: `${changelogPath} ${section.heading} shipseal:${slot} marker`,\n fetchedAt,\n }),\n };\n }\n }\n\n // A snippet from the release notes is about this release. The README's first fence is\n // usually the install command, which says nothing about what changed. Sits above the README\n // in the merge order and below an explicit `release.snippet`.\n const snippet = extractFirstCodeFence(section.body);\n if (snippet !== undefined) {\n out.release = {\n ...out.release,\n codeSnippet: fact(snippet, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading} first fenced code block`,\n fetchedAt,\n }),\n };\n }\n if (section.date !== undefined) {\n out.release = {\n ...out.release,\n date: fact(section.date, {\n source: \"changelog\",\n ref: `${changelogPath} ${section.heading}`,\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nexport function findVersionSection(\n markdown: string,\n version: string,\n): { heading: string; body: string; date?: string } | undefined {\n const needle = version.replace(/^v/, \"\");\n const headingRe = /^##\\s+(.+)$/gm;\n const matches = [...markdown.matchAll(headingRe)];\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n if (match === undefined) {\n continue;\n }\n const heading = match[1];\n if (heading === undefined || !headingIncludesVersion(heading, needle)) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].length;\n const next = matches[index + 1];\n const end = next?.index ?? markdown.length;\n const date = extractDate(heading);\n const body = markdown.slice(start, end);\n if (date === undefined) {\n return { heading, body };\n }\n return { heading, body, date };\n }\n return undefined;\n}\n\nexport function cleanChangelogItem(item: string): string {\n return cleanReleaseLine(item);\n}\n\nfunction headingIncludesVersion(heading: string, version: string): boolean {\n const unwrapped = heading.replace(/[[\\]]/g, \" \");\n return new RegExp(`(?:^|\\\\s)v?${escapeRegExp(version)}(?:\\\\s|$)`).test(unwrapped);\n}\n\nfunction extractDate(heading: string): string | undefined {\n const match = /(\\d{4}-\\d{2}-\\d{2})/.exec(heading);\n return match?.[1];\n}\n\nfunction parseGroups(body: string): Array<{ heading: string; items: string[] }> {\n const groups: Array<{ heading: string; items: string[] }> = [];\n const headingRe = /^###\\s+(.+)$/gm;\n const matches = [...body.matchAll(headingRe)];\n if (matches.length === 0) {\n return [{ heading: \"Added\", items: listItems(body) }];\n }\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n if (match === undefined) {\n continue;\n }\n const heading = match[1];\n if (heading === undefined) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].length;\n const next = matches[index + 1];\n const end = next?.index ?? body.length;\n groups.push({ heading, items: listItems(body.slice(start, end)) });\n }\n return groups;\n}\n\nfunction listItems(block: string): string[] {\n const items: string[] = [];\n let current: string | undefined;\n for (const raw of block.split(\"\\n\")) {\n const trimmed = raw.trim();\n // Only an unindented bullet starts a new entry. A nested bullet belongs to the entry\n // above it: Changesets writes sub-lists inside one entry, and treating those as separate\n // highlights put a sentence fragment on a card with no context.\n const indented = /^\\s+/.test(raw);\n if (!indented && (trimmed.startsWith(\"- \") || trimmed.startsWith(\"* \"))) {\n if (current !== undefined) {\n items.push(current);\n }\n current = trimmed;\n continue;\n }\n if (current !== undefined && trimmed.length > 0 && !trimmed.startsWith(\"#\")) {\n current = `${current} ${trimmed}`;\n }\n }\n if (current !== undefined) {\n items.push(current);\n }\n return items;\n}\n\nfunction bucketForHeading(heading: string): \"features\" | \"fixes\" | \"breaking\" | undefined {\n const key = heading.trim().toLowerCase();\n if (\n key === \"added\" ||\n key === \"changed\" ||\n key === \"minor changes\" ||\n key === \"features\"\n ) {\n return \"features\";\n }\n if (key === \"fixed\" || key === \"patch changes\" || key === \"security\" || key === \"fixes\") {\n return \"fixes\";\n }\n if (\n key === \"removed\" ||\n key === \"major changes\" ||\n key === \"breaking\" ||\n key === \"breaking changes\"\n ) {\n return \"breaking\";\n }\n return undefined;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","// git source: tags, commits, contributors\n// Spec: docs/PROJECT_PLAN.md §12.1\n\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { cleanChangelogItem } from \"./changelog.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport async function collectGit(\n cwd: string,\n event: { tag?: string; previousTag?: string },\n): Promise<PartialFacts> {\n const inside = await git(cwd, [\"rev-parse\", \"--is-inside-work-tree\"]);\n if (inside !== \"true\") {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const tag = event.tag ?? (await gitCurrentTag(cwd));\n if (tag === undefined) {\n return {};\n }\n const exists = await git(cwd, [\"rev-parse\", \"--verify\", `${tag}^{commit}`]);\n if (exists === undefined) {\n return {};\n }\n const version = versionFromTag(tag);\n const tags = await gitLines(cwd, [\"tag\", \"--sort=-v:refname\"]);\n const tagIndex = tags.indexOf(tag);\n const previousTag =\n event.previousTag ?? (tagIndex >= 0 ? tags[tagIndex + 1] : tags.find((candidate) => candidate !== tag));\n const range = previousTag === undefined ? tag : `${previousTag}..${tag}`;\n const log = await git(cwd, [\"log\", range, \"--pretty=format:%s\\t%an\\t%ae\\t%h\\t%cI\"]);\n const commits = (log ?? \"\").split(\"\\n\").filter((line) => line.length > 0);\n const features: Fact<string>[] = [];\n const fixes: Fact<string>[] = [];\n const breaking: Fact<string>[] = [];\n const contributors = new Map<string, string>();\n\n for (const line of commits) {\n const [subject, author, email, hash] = line.split(\"\\t\");\n if (subject === undefined || hash === undefined) {\n continue;\n }\n const parsed = parseConventional(subject);\n const display = parsed.display;\n const ref = `git log ${range} ${hash}`;\n const item = fact(display, { source: \"git\", ref, fetchedAt });\n if (parsed.breaking) {\n breaking.push(item);\n } else if (parsed.type === \"feat\") {\n features.push(item);\n } else if (parsed.type === \"fix\" || parsed.type === \"perf\") {\n fixes.push(item);\n }\n if (email !== undefined && author !== undefined && !isBot(author, email)) {\n contributors.set(email, author);\n }\n }\n\n const dateLine = await git(cwd, [\"log\", \"-1\", \"--format=%cI\", tag]);\n const date = (dateLine ?? fetchedAt).slice(0, 10);\n const names = [...contributors.values()];\n\n const release: NonNullable<PartialFacts[\"release\"]> = {\n version: fact(version, { source: \"git\", ref: `git tag ${tag}`, fetchedAt }),\n tag: fact(tag, { source: \"git\", ref: `git tag ${tag}`, fetchedAt }),\n date: fact(date, { source: \"git\", ref: `git log -1 --format=%cI ${tag}`, fetchedAt }),\n features,\n fixes,\n breaking,\n commitCount: fact(commits.length, {\n source: \"git\",\n ref: `git rev-list --count ${range}`,\n fetchedAt,\n }),\n };\n if (previousTag !== undefined) {\n release.previousVersion = fact(versionFromTag(previousTag), {\n source: \"git\",\n ref: `git tag ${previousTag}`,\n fetchedAt,\n });\n const kind = releaseKind(versionFromTag(previousTag), versionFromTag(tag));\n if (kind !== undefined) {\n release.kind = fact(kind, {\n source: \"git\",\n ref: `semver ${previousTag}..${tag}`,\n fetchedAt,\n });\n }\n }\n if (names.length > 0) {\n release.contributors = fact(names, {\n source: \"git\",\n ref: `git log ${range} unique authors`,\n fetchedAt,\n });\n }\n return { release };\n}\n\nexport function parseConventional(subject: string): {\n type: string | undefined;\n display: string;\n breaking: boolean;\n} {\n const match = /^(?<type>\\w+)(?<scope>\\([^)]+\\))?(?<bang>!)?:\\s*(?<rest>.+)$/.exec(subject);\n if (match === null || match.groups === undefined) {\n return { type: undefined, display: displaySubject(subject), breaking: false };\n }\n const type = match.groups.type;\n const rest = match.groups.rest ?? subject;\n const breaking = match.groups.bang === \"!\" || /BREAKING CHANGE:/.test(subject);\n return { type, display: displaySubject(rest), breaking };\n}\n\nexport function versionFromTag(tag: string): string {\n const at = tag.lastIndexOf(\"@\");\n if (at >= 0 && at < tag.length - 1) {\n return tag.slice(at + 1).replace(/^v/, \"\");\n }\n return tag.replace(/^v/, \"\");\n}\n\nexport async function gitCurrentTag(cwd: string): Promise<string | undefined> {\n return git(cwd, [\"describe\", \"--tags\", \"--abbrev=0\"]);\n}\n\nasync function git(cwd: string, args: string[]): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { cwd });\n const trimmed = stdout.trim();\n return trimmed.length === 0 ? undefined : trimmed;\n } catch {\n return undefined;\n }\n}\n\nasync function gitLines(cwd: string, args: string[]): Promise<string[]> {\n const out = await git(cwd, args);\n return out === undefined ? [] : out.split(\"\\n\").filter((line) => line.length > 0);\n}\n\nfunction isBot(author: string, email: string): boolean {\n const haystack = `${author} ${email}`.toLowerCase();\n return (\n author.endsWith(\"[bot]\") ||\n haystack.includes(\"dependabot\") ||\n haystack.includes(\"renovate\") ||\n haystack.includes(\"github-actions\")\n );\n}\n\nfunction displaySubject(text: string): string {\n const cleaned = cleanChangelogItem(text);\n const first = cleaned.at(0);\n if (first === undefined) {\n return cleaned;\n }\n return first.toUpperCase() + cleaned.slice(1);\n}\n\n/**\n * Repository slug and URL from `git remote get-url origin`.\n *\n * Kept separate from `collectGit`, which returns nothing without a tag. A monorepo root\n * often has no `homepage` or `repository` in its private package.json, which left the call\n * to action falling back to the workspace name. The remote is always there.\n */\nexport async function collectGitRemote(cwd: string): Promise<PartialFacts> {\n const remote = await git(cwd, [\"remote\", \"get-url\", \"origin\"]);\n if (remote === undefined) {\n return {};\n }\n const slug = githubSlug(remote.trim());\n if (slug === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const provenance = { source: \"git\" as const, ref: \"git remote get-url origin\", fetchedAt };\n return {\n project: {\n repo: fact(slug, provenance),\n url: fact(`https://github.com/${slug}`, provenance),\n },\n };\n}\n\nfunction githubSlug(url: string): string | undefined {\n const cleaned = url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n return /github\\.com[/:]([^/]+\\/[^/]+)$/.exec(cleaned)?.[1];\n}\n\n/**\n * How significant is this release, by semver alone?\n *\n * Compared against the previous tag rather than read from a changelog heading, so it is a fact\n * with a reference someone can re-run. Returns undefined when either tag is not semver, or when\n * the two are equal: a caller should treat \"unknown\" as \"announce it\", never as \"skip it\".\n */\nexport function releaseKind(\n previous: string,\n current: string,\n): \"major\" | \"minor\" | \"patch\" | undefined {\n const before = parseSemver(previous);\n const after = parseSemver(current);\n if (before === undefined || after === undefined) {\n return undefined;\n }\n if (after[0] !== before[0]) {\n return \"major\";\n }\n if (after[1] !== before[1]) {\n return \"minor\";\n }\n return after[2] === before[2] ? undefined : \"patch\";\n}\n\nfunction parseSemver(value: string): [number, number, number] | undefined {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(value.replace(/^v/, \"\"));\n if (match === null) {\n return undefined;\n }\n return [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n","// GitHub REST via fetch (token optional)\n// Spec: docs/PROJECT_PLAN.md §12.5\n// Docs checked 2026-09-11: https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28\n// GET /repos/{owner}/{repo}\n// GET /repos/{owner}/{repo}/releases/tags/{tag}\n// GET /repos/{owner}/{repo}/contributors\n// Headers: Accept application/vnd.github+json, X-GitHub-Api-Version 2022-11-28\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact } from \"../facts/schema.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nconst API_VERSION = \"2022-11-28\";\nconst API_ROOT = \"https://api.github.com\";\n\nconst repoSchema = z.object({\n stargazers_count: z.number().int().nonnegative(),\n description: z.string().nullable().optional(),\n homepage: z.string().nullable().optional(),\n license: z.object({ spdx_id: z.string().nullable() }).nullable().optional(),\n});\n\nconst releaseSchema = z.object({\n body: z.string().nullable().optional(),\n});\n\nconst contributorsSchema = z.array(z.unknown());\n\nexport interface GithubCacheEntry {\n json: unknown;\n link: string | null;\n}\n\nexport interface GithubCollectOptions {\n repo: string;\n tag?: string;\n token?: string;\n fetchImpl?: typeof fetch;\n cache?: Map<string, GithubCacheEntry>;\n}\n\nexport async function collectGithub(options: GithubCollectOptions): Promise<PartialFacts> {\n const slug = parseRepo(options.repo);\n if (slug === undefined) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n const fetchImpl = options.fetchImpl ?? fetch;\n const cache = options.cache ?? new Map<string, GithubCacheEntry>();\n const repoResponse = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}`,\n options.token,\n fetchImpl,\n cache,\n );\n if (repoResponse === undefined) {\n return {};\n }\n const repo = repoSchema.parse(repoResponse.json);\n const out: PartialFacts = {\n metrics: {\n stars: fact(repo.stargazers_count, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} stargazers_count`,\n fetchedAt,\n }),\n },\n project: {},\n };\n if (repo.description !== undefined && repo.description !== null && repo.description.length > 0) {\n out.project = {\n ...out.project,\n tagline: fact(stripEmoji(repo.description), {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} description`,\n fetchedAt,\n }),\n };\n }\n if (repo.homepage !== undefined && repo.homepage !== null && repo.homepage.length > 0) {\n out.project = {\n ...out.project,\n url: fact(repo.homepage, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} homepage`,\n fetchedAt,\n }),\n };\n }\n const license = repo.license?.spdx_id;\n if (license !== undefined && license !== null && license !== \"NOASSERTION\") {\n out.project = {\n ...out.project,\n license: fact(license, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo} license.spdx_id`,\n fetchedAt,\n }),\n };\n }\n\n if (options.tag !== undefined) {\n const releaseResponse = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}/releases/tags/${encodeURIComponent(options.tag)}`,\n options.token,\n fetchImpl,\n cache,\n { notFoundOk: true },\n );\n if (releaseResponse !== undefined) {\n const release = releaseSchema.parse(releaseResponse.json);\n const features = featuresFromReleaseBody(release.body ?? \"\", options.tag, fetchedAt);\n if (features.length > 0) {\n out.release = { features };\n }\n }\n }\n\n const contributors = await githubGet(\n `${API_ROOT}/repos/${slug.owner}/${slug.repo}/contributors?per_page=1&anon=true`,\n options.token,\n fetchImpl,\n cache,\n { notFoundOk: true },\n );\n if (contributors !== undefined) {\n contributorsSchema.parse(contributors.json);\n const listed = Array.isArray(contributors.json) ? contributors.json.length : 0;\n const fromLink = lastPageFromLink(contributors.link);\n out.metrics = {\n ...out.metrics,\n contributorCount: fact(fromLink ?? listed, {\n source: \"github-api\",\n ref: `GET /repos/${slug.owner}/${slug.repo}/contributors`,\n fetchedAt,\n }),\n };\n }\n\n return out;\n}\n\nexport function parseRepo(value: string): { owner: string; repo: string } | undefined {\n const trimmed = value.trim().replace(/\\.git$/, \"\");\n const match = /^(?:https?:\\/\\/github\\.com\\/)?([A-Za-z0-9_.-]+)\\/([A-Za-z0-9_.-]+)$/.exec(trimmed);\n if (match === null || match[1] === undefined || match[2] === undefined) {\n return undefined;\n }\n return { owner: match[1], repo: match[2] };\n}\n\nfunction featuresFromReleaseBody(body: string, tag: string, fetchedAt: string): Fact<string>[] {\n const lines = body\n .split(\"\\n\")\n .map((line) => line.replace(/^\\s*[-*]\\s*/, \"\").trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n return lines.slice(0, 8).map((line) =>\n fact(line.replace(/\\.$/, \"\"), {\n source: \"github-api\",\n ref: `GET /repos/.../releases/tags/${tag} body`,\n fetchedAt,\n }),\n );\n}\n\nasync function githubGet(\n url: string,\n token: string | undefined,\n fetchImpl: typeof fetch,\n cache: Map<string, GithubCacheEntry>,\n opts: { notFoundOk?: boolean } = {},\n): Promise<GithubCacheEntry | undefined> {\n const cached = cache.get(url);\n if (cached !== undefined) {\n return cached;\n }\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": API_VERSION,\n \"User-Agent\": \"shipseal\",\n };\n if (token !== undefined && token.length > 0) {\n headers.Authorization = `Bearer ${token}`;\n }\n let response: Response;\n try {\n response = await fetchImpl(url, { headers });\n } catch (error) {\n throw new ShipsealError(\n \"github.network\",\n \"Could not reach the GitHub API.\",\n \"Check network access, then retry. Unauthenticated calls are optional; facts still come from git and package.json.\",\n { cause: error },\n );\n }\n if (response.status === 404 && opts.notFoundOk === true) {\n return undefined;\n }\n if (response.status === 403 || response.status === 429) {\n throw new ShipsealError(\n \"github.rate-limit\",\n \"GitHub API rate limit exceeded.\",\n \"Set GITHUB_TOKEN in the environment to raise the limit, then retry.\",\n );\n }\n if (!response.ok) {\n throw new ShipsealError(\n \"github.http\",\n `GitHub API returned HTTP ${String(response.status)} for ${url}.`,\n \"Confirm the repository exists and GITHUB_TOKEN can read it.\",\n );\n }\n const json: unknown = await response.json();\n const entry: GithubCacheEntry = { json, link: response.headers.get(\"link\") };\n cache.set(url, entry);\n return entry;\n}\n\nfunction lastPageFromLink(link: string | null): number | undefined {\n if (link === null) {\n return undefined;\n }\n const match = /[?&]page=(\\d+)>;\\s*rel=\"last\"/.exec(link);\n if (match === null || match[1] === undefined) {\n return undefined;\n }\n return Number.parseInt(match[1], 10);\n}\n","// npm weekly downloads\n// Spec: docs/PROJECT_PLAN.md §12.6\n// Docs checked 2026-09-11: https://github.com/npm/registry/blob/main/docs/download-counts.md\n// GET https://api.npmjs.org/downloads/point/{period}/{package}\n// period last-week. Scoped names are URL-encoded (@scope/pkg -> %40scope%2Fpkg).\n// 404 means the package is unpublished or unknown: return nothing.\n\nimport { z } from \"zod\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts } from \"../facts/partial.js\";\n\nconst API_ROOT = \"https://api.npmjs.org/downloads/point/last-week\";\nconst REGISTRY_ROOT = \"https://registry.npmjs.org\";\n\nconst pointSchema = z.object({\n downloads: z.number().int().nonnegative(),\n start: z.string().optional(),\n end: z.string().optional(),\n package: z.string().optional(),\n});\n\nexport interface NpmCollectOptions {\n npmPackage: string;\n fetchImpl?: typeof fetch;\n cache?: Map<string, unknown>;\n}\n\nexport async function collectNpm(options: NpmCollectOptions): Promise<PartialFacts> {\n const name = options.npmPackage.trim();\n if (name.length === 0) {\n return {};\n }\n const url = `${API_ROOT}/${encodeURIComponent(name)}`;\n const cache = options.cache ?? new Map<string, unknown>();\n const cached = cache.get(url);\n const json = cached ?? (await npmGet(url, options.fetchImpl ?? fetch, cache));\n if (json === undefined) {\n return {};\n }\n const point = pointSchema.parse(json);\n return {\n metrics: {\n weeklyDownloads: fact(point.downloads, {\n source: \"npm-api\",\n ref: `GET /downloads/point/last-week/${name} downloads`,\n fetchedAt: new Date().toISOString(),\n }),\n },\n };\n}\n\nasync function npmGet(\n url: string,\n fetchImpl: typeof fetch,\n cache: Map<string, unknown>,\n): Promise<unknown | undefined> {\n let response: Response;\n try {\n response = await fetchImpl(url, { headers: { Accept: \"application/json\", \"User-Agent\": \"shipseal\" } });\n } catch (error) {\n throw new ShipsealError(\n \"npm.network\",\n \"Could not reach the npm downloads API.\",\n \"Check network access, then retry. Weekly downloads are optional; other facts still render.\",\n { cause: error },\n );\n }\n if (response.status === 404) {\n return undefined;\n }\n if (response.status === 403 || response.status === 429) {\n throw new ShipsealError(\n \"npm.rate-limit\",\n \"npm downloads API rate limit exceeded.\",\n \"Wait and retry. Milestone cards can still use stars and contributors without downloads.\",\n );\n }\n if (!response.ok) {\n throw new ShipsealError(\n \"npm.http\",\n `npm downloads API returned HTTP ${String(response.status)} for ${url}.`,\n \"Confirm the package name in package.json is published on npm.\",\n );\n }\n const json: unknown = await response.json();\n cache.set(url, json);\n return json;\n}\n\n/**\n * Is this name actually published?\n *\n * The downloads endpoint cannot answer this: it 404s for a package published minutes ago that\n * has no download data yet, which is exactly the case a first release is in. The registry\n * document is the authority.\n *\n * Only a definitive 404 counts as \"no\". A network error, a rate limit or anything else returns\n * undefined, so an unreachable registry never removes a call to action that was probably right.\n */\nexport async function npmPackageExists(\n name: string,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean | undefined> {\n const trimmed = name.trim();\n if (trimmed.length === 0) {\n return false;\n }\n let response: Response;\n try {\n response = await fetchImpl(`${REGISTRY_ROOT}/${encodeURIComponent(trimmed)}`, {\n method: \"HEAD\",\n headers: { accept: \"application/json\" },\n });\n } catch {\n return undefined;\n }\n if (response.status === 404) {\n return false;\n }\n return response.ok ? true : undefined;\n}\n","// package.json source\n// Spec: docs/PROJECT_PLAN.md §12.2\n\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { fact } from \"../facts/fact.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { stripEmoji } from \"../copy/deterministic.js\";\n\nconst pkgSchema = z.object({\n private: z.boolean().optional(),\n name: z.string().optional(),\n bin: z.union([z.string(), z.record(z.string(), z.string())]).optional(),\n description: z.string().optional(),\n version: z.string().optional(),\n homepage: z.string().optional(),\n license: z.string().optional(),\n repository: z.union([z.string(), z.object({ url: z.string().optional() })]).optional(),\n});\n\nexport async function collectPackageJson(\n cwd: string,\n packagePath = \"package.json\",\n): Promise<PartialFacts> {\n const path = join(cwd, packagePath);\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return {};\n }\n const pkg = pkgSchema.safeParse(parsed);\n if (!pkg.success) {\n return {};\n }\n const fetchedAt = new Date().toISOString();\n // A private package.json is a workspace root and its name is plumbing, not a brand. Using\n // it put \"shipseal-monorepo 0.0.5\" on a real hero card. Fall back to the directory, and let\n // a README heading or the git remote win if either has something better.\n const rawName = pkg.data.private === true ? undefined : pkg.data.name;\n const project: PartialProject = {\n name: fact(stripScope(rawName ?? basenameFromPath(cwd)), {\n source: \"package-json\",\n ref: rawName === undefined ? `${packagePath} directory name` : `${packagePath}#name`,\n fetchedAt,\n }),\n };\n if (pkg.data.description !== undefined && pkg.data.description.length > 0) {\n project.tagline = fact(stripEmoji(pkg.data.description), {\n source: \"package-json\",\n ref: `${packagePath}#description`,\n fetchedAt,\n });\n }\n const url = pkg.data.homepage ?? repositoryUrl(pkg.data.repository);\n if (url !== undefined) {\n project.url = fact(url, {\n source: \"package-json\",\n ref: pkg.data.homepage !== undefined ? `${packagePath}#homepage` : `${packagePath}#repository`,\n fetchedAt,\n });\n }\n const repo = repoSlug(pkg.data.repository);\n if (repo !== undefined) {\n project.repo = fact(repo, {\n source: \"package-json\",\n ref: `${packagePath}#repository`,\n fetchedAt,\n });\n }\n // A private package is never on npm. Taking its name put \"npm i shipseal-monorepo\" on a\n // real release card, telling people to install a package that does not exist.\n if (pkg.data.name !== undefined && pkg.data.private !== true) {\n project.npmPackage = fact(pkg.data.name, {\n source: \"package-json\",\n ref: `${packagePath}#name`,\n fetchedAt,\n });\n }\n // A package with a bin is run, not imported. \"npm i shipseal\" told people to install a CLI\n // as a dependency, which is not how any of the docs say to use it.\n if (pkg.data.bin !== undefined && pkg.data.private !== true) {\n project.cli = fact(true, {\n source: \"package-json\",\n ref: `${packagePath}#bin`,\n fetchedAt,\n });\n }\n if (pkg.data.license !== undefined) {\n project.license = fact(pkg.data.license, {\n source: \"package-json\",\n ref: `${packagePath}#license`,\n fetchedAt,\n });\n }\n\n const out: PartialFacts = { project };\n if (pkg.data.version !== undefined) {\n out.release = {\n version: fact(pkg.data.version.replace(/^v/, \"\"), {\n source: \"package-json\",\n ref: `${packagePath}#version`,\n fetchedAt,\n }),\n };\n }\n return out;\n}\n\nfunction stripScope(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1] ?? name;\n}\n\nfunction basenameFromPath(cwd: string): string {\n const parts = cwd.split(/[/\\\\]/).filter((part) => part.length > 0);\n return parts[parts.length - 1] ?? \"project\";\n}\n\nfunction repositoryUrl(repository: z.infer<typeof pkgSchema>[\"repository\"]): string | undefined {\n if (typeof repository === \"string\") {\n return normalizeGitUrl(repository);\n }\n if (repository?.url !== undefined) {\n return normalizeGitUrl(repository.url);\n }\n return undefined;\n}\n\nfunction repoSlug(repository: z.infer<typeof pkgSchema>[\"repository\"]): string | undefined {\n const url = repositoryUrl(repository);\n if (url === undefined) {\n return undefined;\n }\n const match = /github\\.com[/:]([^/]+\\/[^/]+)$/.exec(url.replace(/\\.git$/, \"\"));\n return match?.[1];\n}\n\n// npm allows shorthand repository strings: \"owner/repo\", \"github:owner/repo\",\n// and the other hosts' prefixes. Expand the GitHub ones so repoSlug and the\n// GitHub source see a real URL. Without this, `milestone` could not read stars\n// for any project using the shorthand, which is the most common form.\nconst SHORTHAND = /^(?:github:)?([\\w.-]+\\/[\\w.-]+)$/;\n\nfunction normalizeGitUrl(url: string): string {\n const shorthand = SHORTHAND.exec(url);\n if (shorthand?.[1] !== undefined) {\n return `https://github.com/${shorthand[1].replace(/\\.git$/, \"\")}`;\n }\n const ssh = /^git@([^:]+):(.+)$/.exec(url);\n if (ssh !== null && ssh[1] !== undefined && ssh[2] !== undefined) {\n return `https://${ssh[1]}/${ssh[2].replace(/\\.git$/, \"\")}`;\n }\n return url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n}\n","// Orchestrate collectors into one Facts object\n// Spec: docs/PROJECT_PLAN.md §12\n\nimport { readdir } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport { mergeFacts } from \"../facts/merge.js\";\nimport type { Fact, Facts } from \"../facts/schema.js\";\nimport type { PartialFacts, PartialProject } from \"../facts/partial.js\";\nimport { collectBenchFile } from \"./bench-file.js\";\nimport { collectChangelog } from \"./changelog.js\";\nimport { collectGit, collectGitRemote, versionFromTag } from \"./git.js\";\nimport { collectGithub } from \"./github.js\";\nimport { collectNpm, npmPackageExists } from \"./npm.js\";\nimport { collectPackageJson } from \"./package-json.js\";\nimport { collectConfiguredSnippet, collectReadme } from \"./readme.js\";\n\nexport interface CollectOptions {\n cwd: string;\n event: ShipsealEvent;\n packagePath?: string;\n changelogPath?: string;\n snippet?: string | null;\n headline?: string | undefined;\n subheadline?: string | undefined;\n benchFile?: string;\n githubToken?: string;\n fetchImpl?: typeof fetch;\n skipNetwork?: boolean;\n}\n\nexport async function collectFacts(options: CollectOptions): Promise<Facts> {\n const pkg = await collectPackageJson(options.cwd, options.packagePath ?? \"package.json\");\n const tag = options.event.kind === \"release\" ? options.event.tag : undefined;\n const previousTag = options.event.kind === \"release\" ? options.event.previousTag : undefined;\n const gitEvent: { tag?: string; previousTag?: string } = {};\n if (tag !== undefined) {\n gitEvent.tag = tag;\n }\n if (previousTag !== undefined) {\n gitEvent.previousTag = previousTag;\n }\n const git = await collectGit(options.cwd, gitEvent);\n const version =\n git.release?.version?.value ??\n pkg.release?.version?.value ??\n (tag === undefined ? undefined : versionFromTag(tag));\n const remote = await collectGitRemote(options.cwd);\n const changelog = await collectBestChangelog(\n options.cwd,\n version,\n options.changelogPath ?? \"CHANGELOG.md\",\n options.packagePath,\n );\n const readme = await collectReadme(options.cwd);\n const snippet =\n options.snippet !== undefined && options.snippet !== null && options.snippet.length > 0\n ? await collectConfiguredSnippet(options.cwd, options.snippet)\n : {};\n\n // A private workspace root has no npm name, so the CTA fell back to the GitHub URL even\n // when the repo publishes a package one directory down. Sits before `pkg` so an explicit\n // root name, or one from --package, still wins.\n const workspacePkg =\n pkg.project?.npmPackage === undefined\n ? // Verify what was inferred, trust what was declared. A root name, or one from\n // --package, is the user saying so; this one is a guess worth checking.\n await collectWorkspaceNpmPackage(\n options.cwd,\n options.skipNetwork === true\n ? {}\n : { verify: async (name) => npmPackageExists(name, options.fetchImpl ?? fetch) },\n )\n : {};\n\n // A headline passed on the command line or set in config outranks the changelog marker,\n // which outranks anything deterministic copy would compose. Recorded as a fact either way,\n // so the manifest says the words were chosen rather than derived.\n const overrides: PartialFacts = {};\n for (const slot of [\"headline\", \"subheadline\"] as const) {\n const text = options[slot]?.trim();\n if (text !== undefined && text.length > 0) {\n overrides.release = {\n ...overrides.release,\n [slot]: fact(text, {\n source: \"user-config\",\n ref: `--${slot} or release.${slot}`,\n fetchedAt: new Date().toISOString(),\n }),\n };\n }\n }\n\n // mergeFacts fills holes, so the first source to supply a fact wins. Declared beats derived\n // throughout: package.json is the author saying so, the git remote is whatever this clone\n // happens to point at, which may be a fork, a mirror or an SSH alias.\n //\n // `remote` used to sit first, with a comment claiming that let an explicit package.json\n // homepage or repository win. It did the opposite, because first wins rather than last.\n //\n // Snippet order is explicit, then release notes, then README: a configured `release.snippet`\n // is the user saying so, a fence in the release notes is about this release, and the README's\n // first fence is usually just the install command. `snippet` used to sit last, which meant a\n // configured snippet was silently ignored whenever the README had any code block at all.\n const parts: PartialFacts[] = [overrides, pkg, workspacePkg, remote, git, snippet, changelog, readme];\n\n if (options.event.kind === \"bench\") {\n parts.push(await collectBenchFile(options.cwd, options.benchFile ?? \".shipseal/bench.json\"));\n }\n\n if (options.skipNetwork !== true) {\n const repo = pkg.project?.repo?.value ?? gitRepoFromParts(pkg, readme);\n if (repo !== undefined) {\n const githubOpts: Parameters<typeof collectGithub>[0] = { repo };\n const githubTag = git.release?.tag?.value ?? tag;\n if (githubTag !== undefined) {\n githubOpts.tag = githubTag;\n }\n if (options.githubToken !== undefined) {\n githubOpts.token = options.githubToken;\n }\n if (options.fetchImpl !== undefined) {\n githubOpts.fetchImpl = options.fetchImpl;\n }\n const github = await collectGithub(githubOpts);\n const githubWithoutFeatures: PartialFacts = {};\n if (github.project !== undefined) {\n githubWithoutFeatures.project = github.project;\n }\n if (github.metrics !== undefined) {\n githubWithoutFeatures.metrics = github.metrics;\n }\n parts.push(githubWithoutFeatures);\n const mergedPreview = mergeFacts(parts);\n if (\n options.event.kind === \"release\" &&\n (mergedPreview.release?.features.length ?? 0) === 0 &&\n github.release?.features !== undefined &&\n github.release.features.length > 0\n ) {\n parts.push({ release: { features: github.release.features } });\n }\n }\n const npmPackage = pkg.project?.npmPackage?.value;\n if (npmPackage !== undefined) {\n const npmOpts: Parameters<typeof collectNpm>[0] = { npmPackage };\n if (options.fetchImpl !== undefined) {\n npmOpts.fetchImpl = options.fetchImpl;\n }\n parts.push(await collectNpm(npmOpts));\n }\n }\n\n const facts = mergeFacts(parts);\n if (options.event.kind === \"release\" && facts.release === undefined) {\n throw new ShipsealError(\n \"facts.missing-release\",\n \"Could not collect release facts.\",\n \"Create a git tag, pass --tag, or add a matching version section to CHANGELOG.md.\",\n );\n }\n return facts;\n}\n\nasync function collectBestChangelog(\n cwd: string,\n version: string | undefined,\n changelogPath: string,\n packagePath: string | undefined,\n): Promise<PartialFacts> {\n const paths = [changelogPath];\n if (packagePath !== undefined) {\n const sibling = join(dirname(packagePath), \"CHANGELOG.md\");\n if (!paths.includes(sibling)) {\n paths.push(sibling);\n }\n }\n const collected = await Promise.all(paths.map((path) => collectChangelog(cwd, version, path)));\n const found = collected.find((facts) => changelogHasNotes(facts));\n if (found !== undefined) {\n return found;\n }\n\n // Monorepos keep the changelog beside the package, not at the repo root, and Changesets\n // writes it there. Without this, `release` on a workspace root silently fell back to raw\n // commit subjects even though a perfectly good changelog existed one directory down.\n const candidates = await workspaceChangelogs(cwd);\n const fromWorkspace = await Promise.all(\n candidates.map((candidate) => collectChangelog(cwd, version, candidate)),\n );\n return fromWorkspace.find((facts) => changelogHasNotes(facts)) ?? {};\n}\n\n/**\n * Find the one publishable package in a workspace.\n *\n * Only when there is exactly one candidate: two publishable packages make the CTA a guess, and\n * guessing which one to tell people to install is worse than falling back to the repository\n * URL. `--package` resolves the ambiguity explicitly.\n */\nasync function collectWorkspaceNpmPackage(\n cwd: string,\n options: { verify?: (name: string) => Promise<boolean | undefined> } = {},\n): Promise<PartialFacts> {\n const paths = await workspaceManifests(cwd);\n const manifests = await Promise.all(paths.map((path) => collectPackageJson(cwd, path)));\n const found = manifests\n .map((facts, index) => ({\n name: facts.project?.npmPackage?.value,\n cli: facts.project?.cli,\n path: paths[index] ?? \"\",\n }))\n .filter(\n (entry): entry is { name: string; cli: Fact<boolean> | undefined; path: string } =>\n entry.name !== undefined,\n );\n const only = found.length === 1 ? found[0] : undefined;\n if (only === undefined) {\n return {};\n }\n if (options.verify !== undefined && (await options.verify(only.name)) === false) {\n // Declared public but never published. \"npm i <name>\" would fail for every reader, so\n // leave npmPackage unset and let the call to action fall back to the repository URL.\n return {};\n }\n const project: PartialProject = {\n npmPackage: fact(only.name, {\n source: \"package-json\",\n ref: `${only.path}#name`,\n fetchedAt: new Date().toISOString(),\n }),\n };\n if (only.cli !== undefined) {\n project.cli = only.cli;\n }\n return { project };\n}\n\nasync function workspaceManifests(cwd: string): Promise<string[]> {\n return (await workspaceChangelogs(cwd)).map((path) =>\n path.replace(/CHANGELOG\\.md$/, \"package.json\"),\n );\n}\n\nasync function workspaceChangelogs(cwd: string): Promise<string[]> {\n const roots = [\"packages\", \"apps\"];\n const listings = await Promise.all(\n roots.map(async (root) => {\n let entries: Dirent[];\n try {\n entries = await readdir(join(cwd, root), { withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => join(root, entry.name, \"CHANGELOG.md\"));\n }),\n );\n return listings.flat().toSorted();\n}\n\nfunction changelogHasNotes(facts: PartialFacts): boolean {\n const release = facts.release;\n if (release === undefined) {\n return false;\n }\n return (\n (release.features?.length ?? 0) > 0 ||\n (release.fixes?.length ?? 0) > 0 ||\n (release.breaking?.length ?? 0) > 0\n );\n}\n\nfunction gitRepoFromParts(pkg: PartialFacts, readme: PartialFacts): string | undefined {\n return pkg.project?.repo?.value ?? pkg.project?.url?.value ?? readme.project?.url?.value;\n}\n","// ONLY file allowed to import Takumi (Rule R4). Verify API first (spike S1)\n// Spec: docs/PROJECT_PLAN.md §16\n// Docs checked 2026-09-11: https://takumi.kane.tw/docs , /docs/measure-api, /docs/typography-and-fonts, /docs/helpers\n//\n// This file must stay free of `node:` imports. The browser demo (/try) imports the renderer\n// through here, and one top-level Node builtin is enough for Vite to externalize the module,\n// throw on load, and leave the page blank. Disk access lives in `takumi-node.ts`.\n\nimport { Renderer, type Node } from \"takumi-js/node\";\nimport { container, text as textNode } from \"takumi-js/helpers\";\nimport { fromJsx as takumiFromJsx } from \"takumi-js/helpers/jsx\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type {\n LayoutNode,\n MeasureOptions,\n MeasureResult,\n MeasureTextOptions,\n RenderOptions,\n RendererAdapter,\n} from \"./adapter.js\";\n\nexport const GEIST_MONO_FAMILY = \"Geist Mono\";\n\n/** Path of the vendored font, relative to the package root. Resolved in `takumi-node.ts`. */\nexport const FONT_REL = \"assets/fonts/GeistMono[wght].ttf\";\n\n/** Both runtimes end here: one adapter, one registered font, whoever supplied the bytes. */\nexport async function createRendererWithFont(font: Uint8Array): Promise<RendererAdapter> {\n const renderer = new Renderer();\n await renderer.registerFont({\n name: GEIST_MONO_FAMILY,\n data: font,\n generic: \"monospace\",\n });\n return new TakumiRenderer(renderer);\n}\n\n/** The docs build aliases takumi-js/node to the WASM binding, keeping one adapter. */\nexport async function createBrowserTakumiRenderer(font: Uint8Array): Promise<RendererAdapter> {\n const { init } = await import(\"takumi-js/wasm/no-init\");\n const { default: wasmUrl } = await import(\"takumi-js/wasm-url\");\n await init({ module_or_path: wasmUrl });\n return createRendererWithFont(font);\n}\n\nexport interface LineCountNode {\n runs: ReadonlyArray<{ y: number }>;\n children: readonly LineCountNode[];\n}\n\nexport function countLines(node: LineCountNode): number {\n const ys = new Set<number>();\n const walk = (current: LineCountNode): void => {\n for (const run of current.runs) {\n ys.add(Math.round(run.y));\n }\n for (const child of current.children) {\n walk(child);\n }\n };\n walk(node);\n return ys.size;\n}\n\nexport function testCardNode(): LayoutNode {\n return container({\n style: {\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n padding: 64,\n backgroundColor: \"#0b0b0c\",\n },\n children: [\n textNode(\"Shipseal\", {\n fontFamily: \"Geist\",\n fontSize: 72,\n fontWeight: 700,\n color: \"#fafafa\",\n }),\n textNode(\"Every release, sealed and ready to share\", {\n fontFamily: GEIST_MONO_FAMILY,\n fontSize: 28,\n fontWeight: 400,\n color: \"#a1a1aa\",\n }),\n ],\n });\n}\n\nclass TakumiRenderer implements RendererAdapter {\n constructor(private readonly renderer: Renderer) {}\n\n async fromJsx(element: unknown): Promise<LayoutNode> {\n const result = await takumiFromJsx(asReactElementLike(element));\n return pack(result.node, result.css);\n }\n\n async render(node: LayoutNode, opts: RenderOptions): Promise<Uint8Array> {\n const packed = unpack(node);\n const extras: { css: string[]; images?: RenderOptions[\"images\"] } = {\n css: opts.css ?? packed.css,\n };\n if (opts.images !== undefined) {\n extras.images = opts.images;\n }\n const buffer = await renderWithFormat(this.renderer, packed.node, opts, extras);\n return Uint8Array.from(buffer);\n }\n\n async measure(node: LayoutNode, opts?: MeasureOptions): Promise<MeasureResult> {\n const packed = unpack(node);\n const measured = await this.renderer.measure(packed.node, measureOpts(opts));\n return {\n lines: countLines(measured),\n width: measured.width,\n height: measured.height,\n };\n }\n\n async measureText(value: string, opts: MeasureTextOptions): Promise<MeasureResult> {\n const measured = await this.renderer.measure(asNode(textMeasureNode(value, opts)));\n return {\n lines: countLines(measured),\n width: measured.width,\n height: measured.height,\n };\n }\n}\n\nfunction renderWithFormat(\n renderer: Renderer,\n node: Node,\n opts: RenderOptions,\n extras: { css: string[]; images?: RenderOptions[\"images\"] },\n): Promise<Buffer> {\n const width = opts.width;\n const height = opts.height;\n const css = extras.css;\n const images = extras.images;\n if (opts.format === \"webp\") {\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"webp\", css, images });\n }\n return renderer.render(node, { width, height, format: \"webp\", css });\n }\n if (opts.format === \"jpeg\") {\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"jpeg\", css, images });\n }\n return renderer.render(node, { width, height, format: \"jpeg\", css });\n }\n if (images !== undefined) {\n return renderer.render(node, { width, height, format: \"png\", css, images });\n }\n return renderer.render(node, { width, height, format: \"png\", css });\n}\n\nfunction measureOpts(opts?: MeasureOptions): { width?: number; height?: number } {\n const out: { width?: number; height?: number } = {};\n if (opts?.width !== undefined) {\n out.width = opts.width;\n }\n if (opts?.height !== undefined) {\n out.height = opts.height;\n }\n return out;\n}\n\nfunction textMeasureNode(value: string, opts: MeasureTextOptions): LayoutNode {\n const style: {\n fontFamily: string;\n fontSize: number;\n lineHeight: number;\n whiteSpace: \"normal\" | \"pre\";\n maxWidth: number;\n fontWeight?: number;\n } = {\n fontFamily: opts.fontFamily,\n fontSize: opts.fontSize,\n lineHeight: opts.lineHeight,\n whiteSpace: opts.whiteSpace ?? \"normal\",\n maxWidth: opts.maxWidth,\n };\n if (opts.fontWeight !== undefined) {\n style.fontWeight = opts.fontWeight;\n }\n return textNode(value, style);\n}\n\nfunction asNode(node: LayoutNode): Node {\n return unpack(node).node;\n}\n\ntype PackedLayout = { readonly __shipseal: true; node: Node; css: string[] };\n\nfunction pack(node: Node, css: string[] = []): LayoutNode {\n const packed: PackedLayout = { __shipseal: true, node, css };\n return packed;\n}\n\nfunction unpack(node: LayoutNode): PackedLayout {\n if (isPacked(node)) {\n return node;\n }\n if (isTakumiNode(node)) {\n return { __shipseal: true, node, css: [] };\n }\n throw new ShipsealError(\n \"render.invalid-node\",\n \"render/measure received a value that is not a Takumi node tree.\",\n \"Pass a node built by the renderer adapter (fromJsx, measureText, or testCardNode).\",\n );\n}\n\nfunction isPacked(node: LayoutNode): node is PackedLayout {\n return typeof node === \"object\" && node !== null && \"__shipseal\" in node;\n}\n\nfunction isTakumiNode(node: LayoutNode): node is Node {\n return typeof node === \"object\" && node !== null && \"type\" in node;\n}\n\nfunction asReactElementLike(element: unknown): { type: unknown; props: unknown; key: string | null } {\n if (typeof element !== \"object\" || element === null || !(\"type\" in element)) {\n throw new ShipsealError(\n \"render.invalid-jsx\",\n \"fromJsx received a value that is not a JSX element.\",\n \"Return JSX from a template render function.\",\n );\n }\n const record = element;\n const type = \"type\" in record ? record.type : undefined;\n const props = \"props\" in record ? record.props : null;\n const key = \"key\" in record && typeof record.key === \"string\" ? record.key : null;\n return { type, props, key };\n}\n","// The Node half of the renderer: finding the vendored font on disk and loading it.\n// Spec: docs/PROJECT_PLAN.md §16\n//\n// This file exists so that `takumi.ts` holds no `node:` import. The browser demo imports the\n// renderer through `takumi.ts`, and a single top-level `node:fs` there is enough for Vite to\n// externalize the module, throw on load, and leave the page blank with no error shown.\n//\n// Rule 3 still holds: `takumi.ts` remains the only file that imports Takumi. This one imports\n// `takumi.ts`, never `takumi-js`.\n\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { RendererAdapter } from \"./adapter.js\";\nimport { FONT_REL, createRendererWithFont } from \"./takumi.js\";\n\nlet shared: Promise<RendererAdapter> | undefined;\n\nexport function getTakumiRenderer(): Promise<RendererAdapter> {\n shared ??= createTakumiRenderer();\n return shared;\n}\n\nexport async function createTakumiRenderer(): Promise<RendererAdapter> {\n const fontPath = join(resolvePackageRoot(), FONT_REL);\n const data = await readFile(fontPath);\n return createRendererWithFont(data);\n}\n\nexport function resolvePackageRoot(from = import.meta.url): string {\n let dir = dirname(fileURLToPath(from));\n for (;;) {\n if (existsSync(join(dir, \"package.json\")) && existsSync(join(dir, FONT_REL))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n throw new ShipsealError(\n \"render.font-missing\",\n `Could not find vendored font ${FONT_REL}.`,\n \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present next to package.json.\",\n );\n }\n dir = parent;\n }\n}\n","// Rule R1: reject any digits not from facts\n// Spec: docs/PROJECT_PLAN.md §13.3\n\nimport type { Facts } from \"../facts/schema.js\";\nimport type { Copy } from \"./slots.js\";\n\nexport function allowedNumbers(facts: Facts): Set<string> {\n const allowed = new Set<string>();\n const visit = (value: unknown): void => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n addNumber(allowed, value);\n return;\n }\n if (typeof value === \"string\") {\n for (const match of value.match(/\\d+(?:\\.\\d+)*/g) ?? []) {\n allowed.add(match);\n }\n return;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n visit(item);\n }\n return;\n }\n if (typeof value === \"object\" && value !== null) {\n if (\"value\" in value && \"provenance\" in value) {\n visit(value.value);\n return;\n }\n for (const nested of Object.values(value)) {\n visit(nested);\n }\n }\n };\n visit(facts);\n return allowed;\n}\n\nexport function unsourcedDigits(text: string, allowed: Set<string>): string[] {\n const found: string[] = [];\n const withoutGrouped = text.replace(/\\d{1,3}(?:,\\d{3})+/g, (match) => {\n const compact = match.replaceAll(\",\", \"\");\n if (!allowed.has(match) && !allowed.has(compact)) {\n found.push(match);\n }\n return \" \";\n });\n for (const match of withoutGrouped.match(/\\d+(?:\\.\\d+)*/g) ?? []) {\n if (!allowed.has(match)) {\n found.push(match);\n }\n }\n return found;\n}\n\nexport function guardCopy(copy: Copy, facts: Facts): { ok: true } | { ok: false; slot: string; digits: string[] } {\n const allowed = allowedNumbers(facts);\n const slots: Array<[string, string]> = [\n [\"headline\", copy.headline],\n [\"subheadline\", copy.subheadline],\n [\"cta\", copy.cta],\n ];\n if (copy.milestoneLine !== undefined) {\n slots.push([\"milestoneLine\", copy.milestoneLine]);\n }\n copy.highlights.forEach((line, index) => {\n slots.push([`highlights[${String(index)}]`, line]);\n });\n for (const [slot, text] of slots) {\n const digits = unsourcedDigits(text, allowed);\n if (digits.length > 0) {\n return { ok: false, slot, digits };\n }\n }\n return { ok: true };\n}\n\nfunction addNumber(allowed: Set<string>, value: number): void {\n allowed.add(String(value));\n if (Number.isInteger(value)) {\n allowed.add(value.toLocaleString(\"en-US\"));\n }\n}\n","// Optional LLM copy via OpenAI-compatible fetch (BYOK, no extra SDK)\n// Spec: docs/PROJECT_PLAN.md §13.3\n\nimport { z } from \"zod\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { COPY_LIMITS, MAX_HIGHLIGHTS, type Copy } from \"./slots.js\";\nimport { deterministicCopy } from \"./deterministic.js\";\nimport { guardCopy } from \"./number-guard.js\";\n\nconst llmCopySchema = z.object({\n headline: z.string(),\n subheadline: z.string(),\n highlights: z.array(z.string()).max(MAX_HIGHLIGHTS),\n cta: z.string(),\n});\n\nexport interface LlmCopyOptions {\n apiKey: string;\n model: string;\n maxRetries: number;\n baseUrl?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport async function llmCopy(\n facts: Facts,\n options: LlmCopyOptions,\n fallback = deterministicCopy(facts),\n): Promise<{ copy: Copy; mode: \"llm\" | \"deterministic\"; warning?: string }> {\n const payload = factsForLlm(facts);\n let lastError: string | undefined;\n const retries = Math.max(0, options.maxRetries);\n for (let attempt = 0; attempt <= retries; attempt += 1) {\n let parsed: z.infer<typeof llmCopySchema>;\n try {\n // Sequential retries are required: each attempt depends on the previous rejection.\n // eslint-disable-next-line no-await-in-loop\n const raw = await requestCopy(payload, options);\n parsed = llmCopySchema.parse(JSON.parse(raw));\n } catch (error) {\n lastError = error instanceof Error ? error.message : \"LLM request failed\";\n continue;\n }\n const expanded = expandPlaceholders(parsed, facts);\n const styled: Copy = {\n headline: stripStyle(expanded.headline).slice(0, COPY_LIMITS.headline),\n subheadline: stripStyle(expanded.subheadline).slice(0, COPY_LIMITS.subheadline),\n highlights: expanded.highlights.map((line) => stripStyle(line).slice(0, COPY_LIMITS.highlight)),\n cta: stripStyle(expanded.cta).slice(0, COPY_LIMITS.cta),\n };\n const guarded = guardCopy(styled, facts);\n if (!guarded.ok) {\n lastError = `Number guard rejected ${guarded.slot}: ${guarded.digits.join(\", \")}`;\n continue;\n }\n return { copy: styled, mode: \"llm\" };\n }\n return {\n copy: fallback,\n mode: \"deterministic\",\n warning: lastError ?? \"LLM copy failed; using deterministic copy\",\n };\n}\n\nfunction factsForLlm(facts: Facts): Record<string, unknown> {\n return {\n project: {\n name: facts.project.name.value,\n tagline: facts.project.tagline?.value,\n npmPackage: facts.project.npmPackage?.value,\n url: facts.project.url?.value,\n },\n release: facts.release === undefined\n ? undefined\n : {\n version: \"{version}\",\n features: facts.release.features.map((item) => item.value),\n fixes: facts.release.fixes.map((item) => item.value),\n breaking: facts.release.breaking.map((item) => item.value),\n },\n metrics: {\n stars: facts.metrics?.stars === undefined ? undefined : \"{stars}\",\n weeklyDownloads: facts.metrics?.weeklyDownloads === undefined ? undefined : \"{weeklyDownloads}\",\n contributorCount: facts.metrics?.contributorCount === undefined ? undefined : \"{contributorCount}\",\n },\n };\n}\n\nfunction expandPlaceholders(copy: z.infer<typeof llmCopySchema>, facts: Facts): z.infer<typeof llmCopySchema> {\n const map: Record<string, string> = {\n \"{version}\": facts.release?.version.value ?? \"\",\n \"{stars}\": facts.metrics?.stars === undefined ? \"\" : formatCount(facts.metrics.stars.value),\n \"{weeklyDownloads}\":\n facts.metrics?.weeklyDownloads === undefined ? \"\" : formatCount(facts.metrics.weeklyDownloads.value),\n \"{contributorCount}\":\n facts.metrics?.contributorCount === undefined ? \"\" : formatCount(facts.metrics.contributorCount.value),\n };\n const expand = (text: string): string => {\n let out = text;\n for (const [token, value] of Object.entries(map)) {\n out = out.replaceAll(token, value);\n }\n return out;\n };\n return {\n headline: expand(copy.headline),\n subheadline: expand(copy.subheadline),\n highlights: copy.highlights.map(expand),\n cta: expand(copy.cta),\n };\n}\n\nfunction stripStyle(text: string): string {\n return text.replaceAll(\"\\u2014\", \":\").replaceAll(\"\\u2013\", \"-\").replaceAll(\"!\", \".\");\n}\n\nfunction formatCount(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nasync function requestCopy(facts: Record<string, unknown>, options: LlmCopyOptions): Promise<string> {\n const base = (options.baseUrl ?? \"https://api.openai.com/v1\").replace(/\\/$/, \"\");\n const fetchImpl = options.fetchImpl ?? fetch;\n const response = await fetchImpl(`${base}/chat/completions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: options.model,\n response_format: { type: \"json_object\" },\n messages: [\n {\n role: \"system\",\n content:\n \"Write short release-card copy as JSON with keys headline, subheadline, highlights, cta. No em dashes, no exclamation marks. Use placeholders like {version} for numbers. Never invent numbers.\",\n },\n { role: \"user\", content: JSON.stringify(facts) },\n ],\n }),\n });\n if (!response.ok) {\n throw new ShipsealError(\n \"copy.llm-http\",\n `LLM provider returned HTTP ${String(response.status)}.`,\n \"Check SHIPSEAL_LLM_API_KEY, copy.model, and SHIPSEAL_LLM_BASE_URL.\",\n );\n }\n const json: unknown = await response.json();\n const message = z\n .object({\n choices: z.array(z.object({ message: z.object({ content: z.string() }) })).min(1),\n })\n .parse(json);\n const first = message.choices[0];\n if (first === undefined) {\n throw new ShipsealError(\"copy.llm-empty\", \"LLM returned no choices.\", \"Retry, or run with --no-copy.\");\n }\n return first.message.content;\n}\n","// Build manifest.json with facts, computed values, warnings\n// Spec: docs/PROJECT_PLAN.md §17.2\n\nimport type { Brand } from \"../brand/schema.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport type { GenerateResult } from \"../core/generate.js\";\n\nexport interface ManifestFile {\n path: string;\n template: string;\n format: string;\n width: number;\n height: number;\n bytes: number;\n sha256: string;\n}\n\nexport interface Manifest {\n shipseal: string;\n event: ShipsealEvent;\n generatedAt: string;\n brand: { name: string; theme: Brand[\"theme\"]; source: string };\n copy: { mode: \"deterministic\" | \"llm\" };\n files: ManifestFile[];\n facts: Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }>;\n computed: Record<string, { value: unknown; computedFrom: string[] }>;\n warnings: GenerateResult[\"warnings\"];\n missing: GenerateResult[\"missing\"];\n}\n\nexport function buildManifest(input: {\n result: GenerateResult;\n event: ShipsealEvent;\n brand: Brand;\n shipsealVersion: string;\n}): Manifest {\n return {\n shipseal: input.shipsealVersion,\n event: input.event,\n generatedAt: input.result.generatedAt,\n brand: {\n name: input.brand.name,\n theme: input.brand.theme,\n source: \".shipseal/brand.json\",\n },\n copy: { mode: input.result.copyMode },\n files: input.result.files.map((file) => ({\n path: file.fileName,\n template: file.template,\n format: file.format,\n width: file.width,\n height: file.height,\n bytes: file.bytes.byteLength,\n sha256: file.sha256,\n })),\n facts: flattenFacts(input.result.facts),\n computed: input.result.computed,\n warnings: input.result.warnings,\n missing: input.result.missing,\n };\n}\n\nexport function flattenFacts(\n facts: Facts,\n): Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }> {\n const out: Record<string, { value: unknown; source: string; ref: string; fetchedAt: string }> = {};\n const walk = (prefix: string, value: unknown): void => {\n if (isFact(value)) {\n out[prefix] = {\n value: value.value,\n source: value.provenance.source,\n ref: value.provenance.ref,\n fetchedAt: value.provenance.fetchedAt,\n };\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n walk(`${prefix}[${String(index)}]`, item);\n });\n return;\n }\n if (typeof value === \"object\" && value !== null) {\n for (const [key, nested] of Object.entries(value)) {\n walk(prefix.length === 0 ? key : `${prefix}.${key}`, nested);\n }\n }\n };\n walk(\"project\", facts.project);\n if (facts.story !== undefined) {\n walk(\"story\", facts.story);\n }\n if (facts.release !== undefined) {\n walk(\"release\", facts.release);\n }\n if (facts.metrics !== undefined) {\n walk(\"metrics\", facts.metrics);\n }\n if (facts.bench !== undefined) {\n walk(\"bench\", facts.bench);\n }\n if (facts.milestone !== undefined) {\n walk(\"milestone\", facts.milestone);\n }\n return out;\n}\n\nfunction isFact(\n value: unknown,\n): value is { value: unknown; provenance: { source: string; ref: string; fetchedAt: string } } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n if (!(\"value\" in value) || !(\"provenance\" in value)) {\n return false;\n }\n const provenance = value.provenance;\n return (\n typeof provenance === \"object\" &&\n provenance !== null &&\n \"source\" in provenance &&\n \"ref\" in provenance &&\n \"fetchedAt\" in provenance\n );\n}\n","// Write pack files to disk\n// Spec: docs/PROJECT_PLAN.md §17.1\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { GenerateResult } from \"../core/generate.js\";\nimport { buildManifest, type Manifest } from \"./manifest.js\";\nimport type { Brand } from \"../brand/schema.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\n\nexport async function writePack(input: {\n outDir: string;\n eventId: string;\n result: GenerateResult;\n event: ShipsealEvent;\n brand: Brand;\n shipsealVersion: string;\n}): Promise<{ dir: string; manifest: Manifest }> {\n const dir = join(input.outDir, input.eventId);\n await mkdir(dir, { recursive: true });\n await Promise.all(input.result.files.map((file) => writeFile(join(dir, file.fileName), file.bytes)));\n const manifest = buildManifest({\n result: input.result,\n event: input.event,\n brand: input.brand,\n shipsealVersion: input.shipsealVersion,\n });\n await writeFile(join(dir, \"manifest.json\"), `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n return { dir, manifest };\n}\n\nexport function resolveOutputDir(cwd: string, configured: string): string {\n return isAbsolute(configured) ? configured : join(cwd, configured);\n}\n\nexport function eventId(event: ShipsealEvent, generatedAt = \"\"): string {\n if (event.kind === \"release\") {\n return event.tag;\n }\n if (event.kind === \"milestone\") {\n return `milestone-${event.metric}-${String(event.threshold)}`;\n }\n const day = generatedAt.slice(0, 10);\n return /^\\d{4}-\\d{2}-\\d{2}$/.test(day) ? `bench-${day}` : \"bench\";\n}\n","// Upload assets to a GitHub release and write the Actions job summary\n// Spec: docs/PROJECT_PLAN.md §19.4\n// Docs checked 2026-09-11: `gh release upload <tag> <files>... --clobber`\n// gh is preinstalled on GitHub-hosted runners.\n\nimport { execFile } from \"node:child_process\";\nimport { appendFile } from \"node:fs/promises\";\nimport { promisify } from \"node:util\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { Manifest } from \"./manifest.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GhExec = (\n file: string,\n args: string[],\n options: { env: NodeJS.ProcessEnv },\n) => Promise<{ stdout: string; stderr: string }>;\n\nexport async function uploadReleaseAssets(options: {\n tag: string;\n files: string[];\n repo?: string;\n token?: string;\n exec?: GhExec;\n}): Promise<void> {\n if (options.files.length === 0) {\n return;\n }\n const exec = options.exec ?? execFileAsync;\n const args = [\"release\", \"upload\", options.tag, ...options.files, \"--clobber\"];\n if (options.repo !== undefined) {\n args.push(\"--repo\", options.repo);\n }\n const env = { ...process.env };\n if (options.token !== undefined) {\n env.GH_TOKEN = options.token;\n env.GITHUB_TOKEN = options.token;\n }\n try {\n await exec(\"gh\", args, { env });\n } catch (error) {\n throw new ShipsealError(\n \"github.upload\",\n `Could not upload assets to GitHub release ${options.tag}.`,\n \"Confirm gh is installed, GITHUB_TOKEN can write contents, and the release exists.\",\n { cause: error },\n );\n }\n}\n\nexport async function appendJobSummary(path: string, manifest: Manifest, dir: string): Promise<void> {\n await appendFile(path, `${jobSummaryMarkdown(manifest, dir)}\\n`, \"utf8\");\n}\n\nexport function jobSummaryMarkdown(manifest: Manifest, dir: string): string {\n const lines = [\n \"## Shipseal\",\n \"\",\n `Generated **${String(manifest.files.length)}** files in \\`${dir}\\`.`,\n \"\",\n ];\n const repo = process.env.GITHUB_REPOSITORY;\n const tag = manifest.event.kind === \"release\" ? manifest.event.tag : undefined;\n if (repo !== undefined && tag !== undefined) {\n for (const file of manifest.files) {\n const url = `https://github.com/${repo}/releases/download/${tag}/${file.path}`;\n lines.push(``, \"\");\n }\n } else {\n lines.push(\"| File | Template | Format |\", \"|---|---|---|\");\n for (const file of manifest.files) {\n lines.push(`| ${file.path} | ${file.template} | ${file.format} |`);\n }\n lines.push(\"\");\n }\n lines.push(\"### Facts\", \"\");\n for (const [key, entry] of Object.entries(manifest.facts)) {\n lines.push(`- \\`${key}\\`: ${JSON.stringify(entry.value)} (${entry.source})`);\n }\n if (Object.keys(manifest.computed).length > 0) {\n lines.push(\"\", \"### Computed\", \"\");\n for (const [key, entry] of Object.entries(manifest.computed)) {\n lines.push(`- \\`${key}\\`: ${JSON.stringify(entry.value)}`);\n }\n }\n if (manifest.warnings.length > 0) {\n lines.push(\"\", \"### Warnings\", \"\");\n for (const warning of manifest.warnings) {\n lines.push(`- ${warning.template} ${warning.format} ${warning.slot}: ${warning.action}`);\n }\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n","// Shared helpers for release, milestone, and bench commands\n\nimport { readFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { Brand } from \"../brand/schema.js\";\nimport { mergeConfig } from \"../config/load.js\";\nimport { DEFAULT_CONFIG, type Config } from \"../config/schema.js\";\nimport { llmCopy } from \"../copy/llm.js\";\nimport type { Copy } from \"../copy/slots.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport type { GenerateResult } from \"../core/generate.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { FORMAT_IDS, type FormatId } from \"../formats.js\";\nimport { eventId, resolveOutputDir, writePack } from \"../outputs/files.js\";\nimport { appendJobSummary, uploadReleaseAssets } from \"../outputs/github-release.js\";\nimport type { Manifest } from \"../outputs/manifest.js\";\nimport { resolvePackageRoot } from \"../render/takumi-node.js\";\n\nexport interface SharedFlags {\n cwd: string;\n formats?: string;\n themes?: string;\n copy?: boolean;\n out?: string;\n strict?: boolean;\n dryRun?: boolean;\n package?: string;\n upload?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport function overlayFormats(config: Config, flags: SharedFlags): Config {\n const overlay: Config = { ...config };\n if (flags.formats !== undefined) {\n overlay.formats = parseFormats(flags.formats);\n }\n if (flags.out !== undefined) {\n overlay.outputDir = flags.out;\n }\n return mergeConfig(DEFAULT_CONFIG, overlay);\n}\n\nexport function parseFormats(list: string): FormatId[] {\n const formats: FormatId[] = [];\n for (const part of list.split(\",\")) {\n const id = part.trim();\n if (id.length === 0) {\n continue;\n }\n const match = FORMAT_IDS.find((format) => format === id);\n if (match === undefined) {\n throw new ShipsealError(\n \"release.bad-format\",\n `Unknown format \"${id}\".`,\n `Use a comma-separated list from: ${FORMAT_IDS.join(\", \")}.`,\n );\n }\n formats.push(match);\n }\n return formats;\n}\n\nexport function resolveThemes(flag: string | undefined, brandTheme: Brand[\"theme\"]): Array<\"dark\" | \"light\"> {\n if (flag === \"both\") {\n return [\"dark\", \"light\"];\n }\n if (flag === \"dark\" || flag === \"light\") {\n return [flag];\n }\n return [brandTheme];\n}\n\nexport async function resolveCopy(\n facts: Facts,\n config: Config,\n noCopy: boolean,\n fallback: Copy,\n): Promise<{ copy: Copy; copyMode: \"deterministic\" | \"llm\"; warning?: string }> {\n if (noCopy || config.copy?.llm !== true) {\n return { copy: fallback, copyMode: \"deterministic\" };\n }\n const apiKey = process.env.SHIPSEAL_LLM_API_KEY;\n if (apiKey === undefined || apiKey.length === 0) {\n throw new ShipsealError(\n \"copy.missing-key\",\n \"copy.llm is enabled but SHIPSEAL_LLM_API_KEY is not set.\",\n \"Set SHIPSEAL_LLM_API_KEY, or pass --no-copy for deterministic copy.\",\n );\n }\n const llmOpts: Parameters<typeof llmCopy>[1] = {\n apiKey,\n model: config.copy.model ?? \"gpt-4o-mini\",\n maxRetries: config.copy.maxRetries ?? 2,\n };\n if (process.env.SHIPSEAL_LLM_BASE_URL !== undefined) {\n llmOpts.baseUrl = process.env.SHIPSEAL_LLM_BASE_URL;\n }\n const result = await llmCopy(facts, llmOpts, fallback);\n const out: { copy: Copy; copyMode: \"deterministic\" | \"llm\"; warning?: string } = {\n copy: result.copy,\n copyMode: result.mode,\n };\n if (result.warning !== undefined) {\n out.warning = result.warning;\n }\n return out;\n}\n\nexport async function loadLogos(cwd: string, brand: Brand): Promise<{ light?: Uint8Array; dark?: Uint8Array } | undefined> {\n if (brand.logo === undefined) {\n return undefined;\n }\n const logos: { light?: Uint8Array; dark?: Uint8Array } = {\n light: await readLogo(cwd, brand.logo.light),\n };\n if (brand.logo.dark !== undefined) {\n logos.dark = await readLogo(cwd, brand.logo.dark);\n }\n return logos;\n}\n\nasync function readLogo(cwd: string, path: string): Promise<Uint8Array> {\n const resolved = isAbsolute(path) ? path : join(cwd, path);\n return new Uint8Array(await readFile(resolved));\n}\n\nexport function readShipsealVersion(): string {\n const raw: unknown = JSON.parse(readFileSync(join(resolvePackageRoot(), \"package.json\"), \"utf8\"));\n if (typeof raw === \"object\" && raw !== null && \"version\" in raw && typeof raw.version === \"string\") {\n return raw.version;\n }\n return \"0.0.0\";\n}\n\nexport function collectEnv(flags: SharedFlags): {\n skipNetwork: boolean;\n githubToken?: string;\n packagePath?: string;\n fetchImpl?: typeof fetch;\n} {\n const skipNetwork = flags.dryRun === true && process.env.GITHUB_TOKEN === undefined;\n const out: ReturnType<typeof collectEnv> = { skipNetwork };\n if (process.env.GITHUB_TOKEN !== undefined) {\n out.githubToken = process.env.GITHUB_TOKEN;\n }\n if (flags.package !== undefined) {\n out.packagePath = flags.package;\n }\n if (flags.fetchImpl !== undefined) {\n out.fetchImpl = flags.fetchImpl;\n }\n return out;\n}\n\nexport async function finishPack(input: {\n flags: SharedFlags;\n config: Config;\n event: ShipsealEvent;\n result: GenerateResult;\n brand: Brand;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n facts: Facts;\n}): Promise<{\n dryRun: false;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir: string;\n manifest: Manifest;\n warnings: GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}> {\n const generatedAt = input.result.generatedAt;\n const written = await writePack({\n outDir: resolveOutputDir(\n input.flags.cwd,\n input.flags.out ?? input.config.outputDir ?? \".shipseal/output\",\n ),\n eventId: eventId(input.event, generatedAt),\n result: input.result,\n event: input.event,\n brand: input.brand,\n shipsealVersion: readShipsealVersion(),\n });\n if (input.flags.upload === true && input.event.kind === \"release\") {\n const files = input.result.files.map((file) => join(written.dir, file.fileName));\n const uploadOpts: Parameters<typeof uploadReleaseAssets>[0] = { tag: input.event.tag, files };\n if (process.env.GITHUB_REPOSITORY !== undefined) {\n uploadOpts.repo = process.env.GITHUB_REPOSITORY;\n }\n if (process.env.GITHUB_TOKEN !== undefined) {\n uploadOpts.token = process.env.GITHUB_TOKEN;\n }\n await uploadReleaseAssets(uploadOpts);\n }\n const summaryPath = process.env.GITHUB_STEP_SUMMARY;\n if (summaryPath !== undefined && summaryPath.length > 0) {\n await appendJobSummary(summaryPath, written.manifest, written.dir);\n }\n const exitCode: 0 | 1 | 2 = input.flags.strict === true && input.result.warnings.length > 0 ? 2 : 0;\n const done: {\n dryRun: false;\n facts: Facts;\n copy: Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir: string;\n manifest: Manifest;\n warnings: GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n } = {\n dryRun: false,\n facts: input.facts,\n copy: input.copy,\n copyMode: input.copyMode,\n dir: written.dir,\n manifest: written.manifest,\n warnings: input.result.warnings,\n exitCode,\n };\n if (input.copyWarning !== undefined) {\n done.copyWarning = input.copyWarning;\n }\n return done;\n}\n","// bench: before/after cards from bench JSON\n// Spec: docs/PROJECT_PLAN.md §18.4\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { benchCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport interface BenchFlags extends SharedFlags {\n file?: string;\n}\n\nexport interface BenchResult {\n dryRun: boolean;\n facts: Awaited<ReturnType<typeof collectFacts>>;\n copy: import(\"../copy/slots.js\").Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runBench(flags: BenchFlags): Promise<BenchResult> {\n const cwd = flags.cwd;\n const config = overlayFormats(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const file = flags.file ?? config.bench?.file ?? \".shipseal/bench.json\";\n const event: ShipsealEvent = { kind: \"bench\", file };\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event,\n skipNetwork: true,\n benchFile: file,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n const facts = await collectFacts(collectOpts);\n const resolved = await resolveCopy(facts, config, flags.copy === false, benchCopy(facts));\n\n if (flags.dryRun === true) {\n const dry: BenchResult = {\n dryRun: true,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n return finishPack(packInput);\n}\n","// doctor: environment and config checks\n// Spec: docs/PROJECT_PLAN.md §18.5\n\nimport { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { brandSchema } from \"../brand/schema.js\";\nimport { FORMATS } from \"../formats.js\";\nimport { createTakumiRenderer, resolvePackageRoot } from \"../render/takumi-node.js\";\nimport { testCardNode } from \"../render/takumi.js\";\n\nconst execFileAsync = promisify(execFile);\nconst MIN_NODE_MAJOR = 22;\n\nexport type CheckStatus = \"pass\" | \"fail\" | \"info\";\n\nexport interface DoctorCheck {\n name: string;\n status: CheckStatus;\n message: string;\n fix?: string;\n}\n\nexport interface DoctorResult {\n ok: boolean;\n checks: DoctorCheck[];\n}\n\nexport async function runDoctor(cwd: string): Promise<DoctorResult> {\n const checks: DoctorCheck[] = [];\n checks.push(checkNode());\n checks.push(await checkGit(cwd));\n checks.push(await checkShallow(cwd));\n checks.push(await checkBrand(cwd));\n checks.push(await checkFont());\n checks.push(await checkLogo(cwd));\n checks.push(checkGithubToken());\n checks.push(await checkRender());\n\n return {\n ok: checks.every((check) => check.status !== \"fail\"),\n checks,\n };\n}\n\nfunction checkNode(): DoctorCheck {\n const version = process.versions.node;\n const major = Number.parseInt(version.split(\".\")[0] ?? \"0\", 10);\n if (major >= MIN_NODE_MAJOR) {\n return { name: \"node\", status: \"pass\", message: `Node.js ${version}` };\n }\n return {\n name: \"node\",\n status: \"fail\",\n message: `Node.js ${version} is below the minimum of ${MIN_NODE_MAJOR}.`,\n fix: `Install Node.js ${MIN_NODE_MAJOR} or newer.`,\n };\n}\n\nasync function checkGit(cwd: string): Promise<DoctorCheck> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"--version\"], { cwd });\n return { name: \"git\", status: \"pass\", message: stdout.trim() };\n } catch {\n return {\n name: \"git\",\n status: \"fail\",\n message: \"git is not available on PATH.\",\n fix: \"Install git and ensure it is on PATH.\",\n };\n }\n}\n\nasync function checkShallow(cwd: string): Promise<DoctorCheck> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--is-shallow-repository\"], {\n cwd,\n });\n if (stdout.trim() === \"true\") {\n return {\n name: \"clone-depth\",\n status: \"fail\",\n message: \"This git clone is shallow, so release facts will be incomplete.\",\n fix: \"Re-clone with a full history, or in GitHub Actions set fetch-depth: 0.\",\n };\n }\n return { name: \"clone-depth\", status: \"pass\", message: \"Full git history is available.\" };\n } catch {\n return {\n name: \"clone-depth\",\n status: \"info\",\n message: \"Could not determine whether the clone is shallow.\",\n };\n }\n}\n\nasync function checkBrand(cwd: string): Promise<DoctorCheck> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n if (!existsSync(path)) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \".shipseal/brand.json is missing.\",\n fix: \"Run shipseal init to detect a brand kit.\",\n };\n }\n try {\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = brandSchema.safeParse(raw);\n if (!parsed.success) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \"brand.json did not match the v1 schema.\",\n fix: parsed.error.issues.map((issue) => issue.message).join(\"; \"),\n };\n }\n return { name: \"brand.json\", status: \"pass\", message: `Brand ${parsed.data.name} is valid.` };\n } catch (error) {\n if (error instanceof SyntaxError) {\n return {\n name: \"brand.json\",\n status: \"fail\",\n message: \"brand.json is not valid JSON.\",\n fix: \"Fix the JSON syntax, or re-run shipseal init --force.\",\n };\n }\n throw error;\n }\n}\n\nasync function checkFont(): Promise<DoctorCheck> {\n try {\n const root = resolvePackageRoot();\n const fontPath = join(root, \"assets\", \"fonts\", \"GeistMono[wght].ttf\");\n if (!existsSync(fontPath)) {\n return {\n name: \"fonts\",\n status: \"fail\",\n message: \"Vendored Geist Mono file is missing.\",\n fix: \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present.\",\n };\n }\n return { name: \"fonts\", status: \"pass\", message: `Geist Mono found at ${fontPath}` };\n } catch {\n return {\n name: \"fonts\",\n status: \"fail\",\n message: \"Could not resolve the vendored Geist Mono font.\",\n fix: \"Reinstall shipseal so assets/fonts/GeistMono[wght].ttf is present.\",\n };\n }\n}\n\nasync function checkLogo(cwd: string): Promise<DoctorCheck> {\n const path = join(cwd, \".shipseal\", \"brand.json\");\n if (!existsSync(path)) {\n return {\n name: \"logo\",\n status: \"info\",\n message: \"Skipped; brand.json is missing.\",\n };\n }\n const raw: unknown = JSON.parse(await readFile(path, \"utf8\"));\n const parsed = brandSchema.safeParse(raw);\n if (!parsed.success || parsed.data.logo === undefined) {\n return { name: \"logo\", status: \"info\", message: \"No logo path in brand.json.\" };\n }\n const light = join(cwd, parsed.data.logo.light);\n if (!existsSync(light)) {\n return {\n name: \"logo\",\n status: \"fail\",\n message: `Logo file ${parsed.data.logo.light} is not readable.`,\n fix: \"Point brand.json logo.light at an existing SVG or PNG, or re-run init.\",\n };\n }\n return { name: \"logo\", status: \"pass\", message: `Logo readable at ${parsed.data.logo.light}` };\n}\n\nfunction checkGithubToken(): DoctorCheck {\n if (process.env.GITHUB_TOKEN !== undefined && process.env.GITHUB_TOKEN.length > 0) {\n return { name: \"GITHUB_TOKEN\", status: \"info\", message: \"GITHUB_TOKEN is set.\" };\n }\n return {\n name: \"GITHUB_TOKEN\",\n status: \"info\",\n message: \"GITHUB_TOKEN is not set. Unauthenticated GitHub API calls have a low rate limit.\",\n };\n}\n\nasync function checkRender(): Promise<DoctorCheck> {\n try {\n const renderer = await createTakumiRenderer();\n const png = await renderer.render(testCardNode(), {\n width: FORMATS.og.width,\n height: FORMATS.og.height,\n format: \"png\",\n });\n if (png.length < 8 || png[0] !== 0x89 || png[1] !== 0x50) {\n return {\n name: \"takumi\",\n status: \"fail\",\n message: \"Takumi rendered bytes that are not a PNG.\",\n fix: \"File an issue with the doctor output and your OS/arch.\",\n };\n }\n return {\n name: \"takumi\",\n status: \"pass\",\n message: `Rendered a ${FORMATS.og.width}x${FORMATS.og.height} test card (${png.length} bytes).`,\n };\n } catch (error) {\n return {\n name: \"takumi\",\n status: \"fail\",\n message: error instanceof Error ? error.message : \"Takumi failed to render a test card.\",\n fix: \"Check that the native Takumi binary installed for this platform.\",\n };\n }\n}\n","// CSS color parsing, oklch to sRGB hex, and contrast (no dependency)\n// Spec: docs/PROJECT_PLAN.md §10.3 and §25 (S7 oklch converter)\n\nconst HEX = /^#([\\da-f]{3}|[\\da-f]{6}|[\\da-f]{8})$/i;\n\nexport function parseCssColor(value: string): string | undefined {\n const trimmed = value.trim();\n const hex = normalizeHex(trimmed);\n if (hex !== undefined) {\n return hex;\n }\n const oklch = parseOklch(trimmed);\n if (oklch !== undefined) {\n return oklchToHex(oklch.l, oklch.c, oklch.h);\n }\n const rgb = parseRgb(trimmed);\n if (rgb !== undefined) {\n return rgbToHex(rgb[0], rgb[1], rgb[2]);\n }\n const hsl = parseHsl(trimmed);\n if (hsl !== undefined) {\n return rgbToHex(...hslToRgb(hsl[0], hsl[1], hsl[2]));\n }\n return undefined;\n}\n\nexport function normalizeHex(value: string): string | undefined {\n const match = HEX.exec(value.trim());\n if (match === null) {\n return undefined;\n }\n const raw = match[1];\n if (raw === undefined) {\n return undefined;\n }\n if (raw.length === 3) {\n return `#${raw[0]}${raw[0]}${raw[1]}${raw[1]}${raw[2]}${raw[2]}`.toLowerCase();\n }\n return `#${raw.slice(0, 6).toLowerCase()}`;\n}\n\nexport function oklchToHex(l: number, c: number, h: number): string {\n const hr = (h * Math.PI) / 180;\n const a = c * Math.cos(hr);\n const b = c * Math.sin(hr);\n const coneL = l + 0.3963377774 * a + 0.2158037573 * b;\n const coneM = l - 0.1055613458 * a - 0.0638541728 * b;\n const coneS = l - 0.0894841775 * a - 1.291485548 * b;\n const l3 = coneL * coneL * coneL;\n const m3 = coneM * coneM * coneM;\n const s3 = coneS * coneS * coneS;\n const r = 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3;\n const g = -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3;\n const bLin = -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3;\n return rgbToHex(srgbEncode(r) * 255, srgbEncode(g) * 255, srgbEncode(bLin) * 255);\n}\n\nexport function contrastRatio(hexA: string, hexB: string): number {\n const a = relativeLuminance(hexA);\n const b = relativeLuminance(hexB);\n const [hi, lo] = a > b ? [a, b] : [b, a];\n return (hi + 0.05) / (lo + 0.05);\n}\n\nexport const LARGE_TEXT_CONTRAST = 3;\n\nexport function ensureForegroundContrast(\n background: string,\n foreground: string,\n): { foreground: string; adjusted: boolean } {\n if (contrastRatio(background, foreground) >= LARGE_TEXT_CONTRAST) {\n return { foreground, adjusted: false };\n }\n const light = \"#fafafa\";\n const dark = \"#0b0b0c\";\n const lightRatio = contrastRatio(background, light);\n const darkRatio = contrastRatio(background, dark);\n return { foreground: lightRatio >= darkRatio ? light : dark, adjusted: true };\n}\n\nexport function readableOnBackground(background: string, candidate: string): boolean {\n return contrastRatio(background, candidate) >= LARGE_TEXT_CONTRAST;\n}\n\nfunction srgbEncode(channel: number): number {\n const abs = Math.abs(channel);\n const encoded = abs <= 0.0031308 ? 12.92 * abs : 1.055 * abs ** (1 / 2.4) - 0.055;\n return Math.sign(channel) * encoded;\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return `#${toByte(r)}${toByte(g)}${toByte(b)}`;\n}\n\nfunction toByte(n: number): string {\n return Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, \"0\");\n}\n\nfunction relativeLuminance(hex: string): number {\n const rgb = hexToRgb(hex);\n if (rgb === undefined) {\n return 0;\n }\n const lin = rgb.map((channel) => {\n const s = channel / 255;\n return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * (lin[0] ?? 0) + 0.7152 * (lin[1] ?? 0) + 0.0722 * (lin[2] ?? 0);\n}\n\nexport function isNeutralHex(hex: string): boolean {\n const rgb = hexToRgb(hex);\n if (rgb === undefined) {\n return true;\n }\n const max = Math.max(rgb[0], rgb[1], rgb[2]);\n const min = Math.min(rgb[0], rgb[1], rgb[2]);\n return max - min < 16;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] | undefined {\n const normalized = normalizeHex(hex);\n if (normalized === undefined) {\n return undefined;\n }\n const r = Number.parseInt(normalized.slice(1, 3), 16);\n const g = Number.parseInt(normalized.slice(3, 5), 16);\n const b = Number.parseInt(normalized.slice(5, 7), 16);\n return [r, g, b];\n}\n\nfunction parseOklch(value: string): { l: number; c: number; h: number } | undefined {\n const match = /^oklch\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const body = match[1];\n if (body === undefined) {\n return undefined;\n }\n const parts = splitCssArgs(body);\n if (parts.length < 3) {\n return undefined;\n }\n const l = parseLightness(parts[0] ?? \"\");\n const c = parseNumber(parts[1] ?? \"\");\n const h = parseHue(parts[2] ?? \"\");\n if (l === undefined || c === undefined || h === undefined) {\n return undefined;\n }\n return { l, c, h };\n}\n\nfunction parseRgb(value: string): [number, number, number] | undefined {\n const match = /^rgba?\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const parts = splitCssArgs(match[1] ?? \"\");\n if (parts.length < 3) {\n return undefined;\n }\n const r = parseRgbChannel(parts[0] ?? \"\");\n const g = parseRgbChannel(parts[1] ?? \"\");\n const b = parseRgbChannel(parts[2] ?? \"\");\n if (r === undefined || g === undefined || b === undefined) {\n return undefined;\n }\n return [r, g, b];\n}\n\nfunction parseHsl(value: string): [number, number, number] | undefined {\n const match = /^hsla?\\(\\s*([^/)]+?)(?:\\s*\\/\\s*[^)]+)?\\s*\\)$/i.exec(value);\n if (match === null) {\n return undefined;\n }\n const parts = splitCssArgs(match[1] ?? \"\");\n if (parts.length < 3) {\n return undefined;\n }\n const h = parseHue(parts[0] ?? \"\");\n const s = parsePercent(parts[1] ?? \"\");\n const l = parsePercent(parts[2] ?? \"\");\n if (h === undefined || s === undefined || l === undefined) {\n return undefined;\n }\n return [h, s, l];\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n const sat = s / 100;\n const light = l / 100;\n const c = (1 - Math.abs(2 * light - 1)) * sat;\n const hp = (((h % 360) + 360) % 360) / 60;\n const x = c * (1 - Math.abs((hp % 2) - 1));\n let r = 0;\n let g = 0;\n let b = 0;\n if (hp < 1) {\n r = c;\n g = x;\n } else if (hp < 2) {\n r = x;\n g = c;\n } else if (hp < 3) {\n g = c;\n b = x;\n } else if (hp < 4) {\n g = x;\n b = c;\n } else if (hp < 5) {\n r = x;\n b = c;\n } else {\n r = c;\n b = x;\n }\n const m = light - c / 2;\n return [(r + m) * 255, (g + m) * 255, (b + m) * 255];\n}\n\nfunction splitCssArgs(body: string): string[] {\n return body\n .split(/[\\s,]+/)\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n}\n\nfunction parseLightness(token: string): number | undefined {\n if (token.endsWith(\"%\")) {\n const n = Number.parseFloat(token.slice(0, -1));\n return Number.isFinite(n) ? n / 100 : undefined;\n }\n return parseNumber(token);\n}\n\nfunction parseHue(token: string): number | undefined {\n if (token === \"none\") {\n return 0;\n }\n if (token.endsWith(\"deg\")) {\n return parseNumber(token.slice(0, -3));\n }\n if (token.endsWith(\"rad\")) {\n const n = parseNumber(token.slice(0, -3));\n return n === undefined ? undefined : (n * 180) / Math.PI;\n }\n if (token.endsWith(\"turn\")) {\n const n = parseNumber(token.slice(0, -4));\n return n === undefined ? undefined : n * 360;\n }\n if (token.endsWith(\"grad\")) {\n const n = parseNumber(token.slice(0, -4));\n return n === undefined ? undefined : n * 0.9;\n }\n return parseNumber(token);\n}\n\nfunction parsePercent(token: string): number | undefined {\n if (!token.endsWith(\"%\")) {\n return parseNumber(token);\n }\n return parseNumber(token.slice(0, -1));\n}\n\nfunction parseRgbChannel(token: string): number | undefined {\n if (token.endsWith(\"%\")) {\n const n = parseNumber(token.slice(0, -1));\n return n === undefined ? undefined : (n / 100) * 255;\n }\n return parseNumber(token);\n}\n\nfunction parseNumber(token: string): number | undefined {\n if (token === \"none\") {\n return 0;\n }\n const n = Number.parseFloat(token);\n return Number.isFinite(n) ? n : undefined;\n}\n","// CSS :root variable extraction\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { parseCssColor } from \"./color.js\";\nimport type { ExtractedColors } from \"./tailwind.js\";\n\n// The trailing semicolon is optional: the last declaration before `}` usually has none,\n// which silently dropped one color from almost every real stylesheet.\nconst PROP =\n /--(primary|brand|accent|background|foreground|muted-foreground|muted)\\s*:\\s*([^;}]+)[;}]?/g;\n\n/** Any declaration, used to resolve `var(--brand-500)` style indirection. */\nconst ANY_PROP = /(--[\\w-]+)\\s*:\\s*([^;}]+)[;}]?/g;\n\n/**\n * Selectors that carry theme tokens in real projects. `:root` alone missed shadcn's\n * `[data-theme]` blocks, plain `html {}`, and `.light`.\n */\nconst SELECTORS = [\n /:root\\s*\\{/g,\n /(?:^|[\\s,}])html\\s*\\{/g,\n /\\.light\\b[^{]*\\{/g,\n /\\[data-theme=[\"']?light[\"']?\\][^{]*\\{/g,\n /\\.dark\\b[^{]*\\{/g,\n /\\[data-theme=[\"']?dark[\"']?\\][^{]*\\{/g,\n];\n\nexport function extractCssRootColors(css: string): ExtractedColors {\n const vars = allVariables(css);\n const found: Record<string, string> = {};\n // Later selectors win, so a dark block overrides a light one, as it does in a browser.\n for (const selector of SELECTORS) {\n Object.assign(found, extractBlockColors(css, selector, vars));\n }\n return mapFoundColors(found);\n}\n\nfunction allVariables(css: string): Record<string, string> {\n const vars: Record<string, string> = {};\n ANY_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = ANY_PROP.exec(css)) !== null) {\n const name = match[1];\n const value = match[2];\n if (name !== undefined && value !== undefined) {\n vars[name] = value.trim();\n }\n }\n return vars;\n}\n\n/**\n * Resolve a declaration to a hex color.\n *\n * Handles two things a plain color parser does not. First, `var(--brand-500)` indirection,\n * up to three hops within the same file. Second, bare channel lists: shadcn writes\n * `--background: 0 0% 100%` and applies it as `hsl(var(--background))`, so the value is only\n * a color once wrapped. Percent signs on the last two channels mean HSL, three plain\n * numbers mean RGB.\n */\nfunction resolveColor(raw: string, vars: Record<string, string>, depth = 0): string | undefined {\n const value = raw.trim();\n if (depth < 3) {\n const ref = /^var\\(\\s*(--[\\w-]+)\\s*(?:,[^)]*)?\\)$/.exec(value);\n const target = ref?.[1] === undefined ? undefined : vars[ref[1]];\n if (target !== undefined) {\n return resolveColor(target, vars, depth + 1);\n }\n }\n const direct = parseCssColor(value);\n if (direct !== undefined) {\n return direct;\n }\n const parts = value.split(/[\\s/]+/).filter((p) => p.length > 0);\n if (parts.length === 3) {\n if (parts[1]?.endsWith(\"%\") === true && parts[2]?.endsWith(\"%\") === true) {\n return parseCssColor(`hsl(${parts[0]} ${parts[1]} ${parts[2]})`);\n }\n if (parts.every((p) => /^\\d+(\\.\\d+)?$/.test(p))) {\n return parseCssColor(`rgb(${parts[0]} ${parts[1]} ${parts[2]})`);\n }\n }\n return undefined;\n}\n\nfunction extractBlockColors(\n css: string,\n blockRe: RegExp,\n vars: Record<string, string>,\n): Record<string, string> {\n const found: Record<string, string> = {};\n blockRe.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = blockRe.exec(css)) !== null) {\n const open = css.indexOf(\"{\", match.index);\n if (open === -1) {\n break;\n }\n const close = matchingBrace(css, open);\n if (close === -1) {\n break;\n }\n const body = css.slice(open + 1, close);\n PROP.lastIndex = 0;\n let prop: RegExpExecArray | null;\n while ((prop = PROP.exec(body)) !== null) {\n const name = prop[1];\n const raw = prop[2];\n if (name === undefined || raw === undefined) {\n continue;\n }\n const hex = resolveColor(raw, vars);\n if (hex !== undefined) {\n found[name] = hex;\n }\n }\n }\n return found;\n}\n\nfunction mapFoundColors(found: Record<string, string>): ExtractedColors {\n const out: ExtractedColors = {};\n const background = found.background;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n const muted = found[\"muted-foreground\"] ?? found.muted;\n if (muted !== undefined) {\n out.muted = muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n if (found.accent !== undefined) {\n out.accent = found.accent;\n }\n return out;\n}\n\nfunction matchingBrace(source: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < source.length; i += 1) {\n const ch = source[i];\n if (ch === \"{\") {\n depth += 1;\n } else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return i;\n }\n }\n }\n return -1;\n}\n","// W3C Design Tokens reader\n// Spec: docs/PROJECT_PLAN.md §10.1\n\nimport { parseCssColor } from \"./color.js\";\nimport type { ExtractedColors } from \"./tailwind.js\";\n\nexport function extractDtcgColors(tokens: unknown): ExtractedColors {\n const found: Record<string, string> = {};\n walk(tokens, [], found);\n const out: ExtractedColors = {};\n const background = found.background ?? found.bg;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground ?? found.fg;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n if (found.muted !== undefined) {\n out.muted = found.muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n const accent = found.accent ?? found.secondary;\n if (accent !== undefined) {\n out.accent = accent;\n }\n return out;\n}\n\nfunction walk(node: unknown, path: string[], found: Record<string, string>): void {\n if (!isRecord(node)) {\n return;\n }\n if (node.$type === \"color\") {\n const hex = colorValue(node.$value);\n const leaf = path[path.length - 1];\n if (hex !== undefined && leaf !== undefined && found[leaf] === undefined) {\n found[leaf] = hex;\n }\n return;\n }\n for (const [key, value] of Object.entries(node)) {\n if (key.startsWith(\"$\")) {\n continue;\n }\n walk(value, [...path, key], found);\n }\n}\n\nfunction colorValue(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n return parseCssColor(value);\n }\n if (isRecord(value) && typeof value.hex === \"string\") {\n return parseCssColor(value.hex);\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","// Static Tailwind v3 config + v4 @theme color extraction\n// Spec: docs/PROJECT_PLAN.md §10.3, spike S7\n\nimport { parseCssColor } from \"./color.js\";\n\nexport interface ExtractedColors {\n background?: string;\n foreground?: string;\n muted?: string;\n primary?: string;\n accent?: string;\n}\n\nconst COLOR_PROP = /--color-([a-zA-Z0-9-]+)\\s*:\\s*([^;]+);/g;\nconst CUSTOM_PROP = /--([a-zA-Z0-9-]+)\\s*:\\s*([^;]+);/g;\nconst SKIP_PREFIXES = new Set([\"chart\", \"sidebar\", \"ring\", \"border\", \"input\", \"destructive\"]);\n\nexport function extractTailwindV4Colors(css: string): ExtractedColors {\n const blocks = themeBlocks(css);\n const custom = collectCustomProperties(css);\n const fromTheme: Record<string, string> = {};\n for (const block of blocks) {\n COLOR_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = COLOR_PROP.exec(block)) !== null) {\n const name = match[1];\n const raw = match[2];\n if (name === undefined || raw === undefined || shouldSkip(name)) {\n continue;\n }\n fromTheme[name] = raw.trim();\n }\n }\n const resolved: Record<string, string> = {};\n for (const [name, raw] of Object.entries(fromTheme)) {\n const hex = resolveToHex(raw, custom, 0);\n if (hex !== undefined) {\n resolved[name] = hex;\n }\n }\n return mapBrandColors(resolved);\n}\n\nexport function extractTailwindV3Colors(source: string): ExtractedColors {\n const found: Record<string, string> = {};\n const re =\n /\\b(primary|brand|accent|background|foreground|muted|secondary)\\b\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(source)) !== null) {\n const name = match[1];\n const raw = match[2];\n if (name === undefined || raw === undefined) {\n continue;\n }\n const hex = parseCssColor(raw);\n if (hex !== undefined) {\n found[name] = hex;\n }\n }\n return mapBrandColors(found);\n}\n\nfunction themeBlocks(css: string): string[] {\n const blocks: string[] = [];\n const re = /@theme(?:\\s+inline)?\\s*\\{/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(css)) !== null) {\n const open = css.indexOf(\"{\", match.index);\n if (open === -1) {\n break;\n }\n const close = matchingBrace(css, open);\n if (close === -1) {\n break;\n }\n blocks.push(css.slice(open + 1, close));\n }\n return blocks;\n}\n\nfunction matchingBrace(source: string, openIndex: number): number {\n let depth = 0;\n for (let i = openIndex; i < source.length; i += 1) {\n const ch = source[i];\n if (ch === \"{\") {\n depth += 1;\n } else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return i;\n }\n }\n }\n return -1;\n}\n\nfunction collectCustomProperties(css: string): Map<string, string> {\n const props = new Map<string, string>();\n CUSTOM_PROP.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = CUSTOM_PROP.exec(css)) !== null) {\n const name = match[1];\n const value = match[2];\n if (name !== undefined && value !== undefined) {\n props.set(`--${name}`, value.trim());\n }\n }\n return props;\n}\n\nfunction resolveToHex(\n raw: string,\n custom: Map<string, string>,\n depth: number,\n): string | undefined {\n if (depth > 3) {\n return undefined;\n }\n const direct = parseCssColor(raw);\n if (direct !== undefined) {\n return direct;\n }\n const varMatch = /^var\\(\\s*(--[a-zA-Z0-9-]+)\\s*(?:,[^)]+)?\\)$/.exec(raw);\n if (varMatch === null) {\n return undefined;\n }\n const ref = varMatch[1];\n if (ref === undefined) {\n return undefined;\n }\n const next = custom.get(ref);\n if (next === undefined) {\n return undefined;\n }\n return resolveToHex(next, custom, depth + 1);\n}\n\nfunction shouldSkip(name: string): boolean {\n const root = name.split(\"-\")[0];\n return root !== undefined && SKIP_PREFIXES.has(root);\n}\n\nfunction mapBrandColors(found: Record<string, string>): ExtractedColors {\n const out: ExtractedColors = {};\n const background = found.background ?? found.bg;\n if (background !== undefined) {\n out.background = background;\n }\n const foreground = found.foreground ?? found.fg;\n if (foreground !== undefined) {\n out.foreground = foreground;\n }\n const muted = found[\"muted-foreground\"] ?? found.muted;\n if (muted !== undefined) {\n out.muted = muted;\n }\n const primary = found.primary ?? found.brand;\n if (primary !== undefined) {\n out.primary = primary;\n }\n const accent = found.accent ?? found.secondary;\n if (accent !== undefined) {\n out.accent = accent;\n }\n return out;\n}\n","// Colour detection, free of every `node:` import so the browser demo runs the same code the CLI\n// does. Spec: docs/REVIEW_2026-09-15.md R0.\n//\n// Splitting this out is what makes /try show a visitor's own colors. `detect.ts` keeps the parts\n// that need disk or zlib (logo files, PNG sampling, README parsing); the colour work is pure\n// text and reaches both surfaces.\n\nimport type { Brand } from \"./schema.js\";\nimport { isNeutralHex, parseCssColor, readableOnBackground } from \"./color.js\";\nimport { extractCssRootColors } from \"./css-vars.js\";\nimport { extractDtcgColors } from \"./dtcg.js\";\nimport type { ProjectFiles } from \"./files.js\";\nimport { extractTailwindV3Colors, extractTailwindV4Colors, type ExtractedColors } from \"./tailwind.js\";\nimport { DEFAULT_BRAND_COLORS } from \"./schema.js\";\n\nexport interface FieldSource {\n field: string;\n source: string;\n}\n\n/** Sampling a PNG logo needs zlib, so the caller supplies it when it can. */\nexport type LogoColor = (files: ProjectFiles, path: string) => Promise<string | undefined>;\n\n/** Path helpers, kept local so this module never imports `node:path`. */\nfunction basename(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\nfunction relative(from: string, path: string): string {\n const prefix = from.endsWith(\"/\") ? from : `${from}/`;\n return path.startsWith(prefix) ? path.slice(prefix.length) : path;\n}\n\nexport async function detectColorsFrom(\n files: ProjectFiles,\n cwd: string,\n logoPath: string | undefined,\n sources: FieldSource[],\n notes: string[],\n logoColor: LogoColor = () => Promise.resolve(undefined),\n): Promise<Brand[\"colors\"]> {\n const merged: ExtractedColors = {};\n const paths = await files.list();\n\n const cssFiles = paths.filter((file) => file.endsWith(\".css\"));\n const cssContents = await Promise.all(\n cssFiles.map(async (file) => ({ file, css: await files.read(file) })),\n );\n for (const { file, css } of cssContents) {\n if (css === undefined) {\n continue;\n }\n const fromTheme = extractTailwindV4Colors(css);\n const fromRoot = extractCssRootColors(css);\n const rel = relative(cwd, file);\n applyColors(merged, fromTheme, sources, `Tailwind v4 @theme in ${rel}`);\n applyColors(merged, fromRoot, sources, `:root variables in ${rel}`);\n }\n\n const configFiles = paths.filter((file) => basename(file).startsWith(\"tailwind.config.\"));\n const configContents = await Promise.all(\n configFiles.map(async (file) => ({ file, source: await files.read(file) })),\n );\n for (const { file, source } of configContents) {\n if (source === undefined) {\n continue;\n }\n applyColors(\n merged,\n extractTailwindV3Colors(source),\n sources,\n `Tailwind config ${relative(cwd, file)}`,\n );\n }\n\n const tokenFile = paths.find((file) => file.endsWith(\".tokens.json\"));\n if (tokenFile !== undefined) {\n const raw = await files.read(tokenFile);\n if (raw !== undefined) {\n try {\n const parsed: unknown = JSON.parse(raw);\n applyColors(merged, extractDtcgColors(parsed), sources, relative(cwd, tokenFile));\n } catch (error) {\n if (error instanceof SyntaxError) {\n notes.push(`Could not parse design tokens file ${relative(cwd, tokenFile)}.`);\n } else {\n throw error;\n }\n }\n }\n }\n\n if (merged.primary === undefined && logoPath !== undefined) {\n const fromPng = logoPath.endsWith(\".png\") ? await logoColor(files, logoPath) : undefined;\n if (fromPng !== undefined) {\n merged.primary = fromPng;\n sources.push({ field: \"colors.primary\", source: `dominant color in ${logoPath}` });\n }\n const svg = logoPath.endsWith(\".svg\") ? await files.read(logoPath) : undefined;\n if (svg !== undefined) {\n const fromLogo = firstNonNeutralSvgColor(svg);\n if (fromLogo !== undefined) {\n merged.primary = fromLogo;\n sources.push({ field: \"colors.primary\", source: `SVG fill in ${logoPath}` });\n }\n }\n }\n\n // Say which colors are built-in defaults rather than anything found in this project.\n // Every other detected field prints its source, so staying silent here would let a user\n // read Shipseal's own red as their brand color.\n const fellBack = ([\"background\", \"foreground\", \"muted\", \"primary\", \"accent\"] as const).filter(\n (field) => merged[field] === undefined,\n );\n if (fellBack.length > 0) {\n notes.push(\n `Using built-in defaults for ${fellBack.map((f) => `colors.${f}`).join(\", \")}. ` +\n \"Nothing in this project set them. Edit .shipseal/brand.json to use your own.\",\n );\n }\n\n return {\n background: merged.background ?? DEFAULT_BRAND_COLORS.background,\n foreground: merged.foreground ?? DEFAULT_BRAND_COLORS.foreground,\n muted: merged.muted ?? DEFAULT_BRAND_COLORS.muted,\n primary: merged.primary ?? DEFAULT_BRAND_COLORS.primary,\n accent: merged.accent ?? DEFAULT_BRAND_COLORS.accent,\n };\n}\n\nfunction applyColors(\n target: ExtractedColors,\n incoming: ExtractedColors,\n sources: FieldSource[],\n source: string,\n): void {\n const keys = [\"background\", \"foreground\", \"muted\", \"primary\", \"accent\"] as const;\n for (const key of keys) {\n const value = incoming[key];\n if (value !== undefined && target[key] === undefined) {\n target[key] = value;\n sources.push({ field: `colors.${key}`, source });\n }\n }\n}\n\nexport function applyReadableMuted(\n colors: Brand[\"colors\"],\n sources: FieldSource[],\n notes: string[],\n): void {\n if (colors.muted === undefined || readableOnBackground(colors.background, colors.muted)) {\n return;\n }\n colors.muted = DEFAULT_BRAND_COLORS.muted;\n notes.push(\n `Muted text color failed WCAG AA large-text contrast (3:1) against background, so it was set to ${DEFAULT_BRAND_COLORS.muted}.`,\n );\n upsertSource(sources, \"colors.muted\", \"contrast adjustment\");\n}\n\nexport function applyReadableAccent(\n colors: Brand[\"colors\"],\n sources: FieldSource[],\n notes: string[],\n): void {\n if (colors.accent === undefined || readableOnBackground(colors.background, colors.accent)) {\n return;\n }\n colors.accent = colors.primary ?? DEFAULT_BRAND_COLORS.primary;\n notes.push(\"Accent failed contrast against background, so it uses the primary color.\");\n upsertSource(sources, \"colors.accent\", \"contrast adjustment\");\n}\n\nexport function upsertSource(sources: FieldSource[], field: string, source: string): void {\n const existing = sources.find((entry) => entry.field === field);\n if (existing !== undefined) {\n existing.source = source;\n return;\n }\n sources.push({ field, source });\n}\n\nfunction firstNonNeutralSvgColor(svg: string): string | undefined {\n const re = /(?:fill|stroke)=\"([^\"]+)\"/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(svg)) !== null) {\n const raw = match[1];\n if (raw === undefined || raw === \"none\" || raw === \"currentColor\") {\n continue;\n }\n const hex = parseCssColor(raw);\n if (hex !== undefined && !isNeutralHex(hex)) {\n return hex;\n }\n }\n return undefined;\n}\n","// Logo discovery\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst DIRECTORIES = [\"\", \"assets\", \"assets/brand\", \"public\", \"public/brand\", \".github\", \"docs\", \"static\", \"branding\"];\nconst ICON_NAMES = [\"icon.svg\", \"icon.png\"];\nconst NAMES = [\"logo.svg\", \"logo.png\", \"logo-light.svg\", \"logo-light.png\"];\nconst FALLBACKS = [...ICON_NAMES, \"favicon.svg\"];\n\nexport function findLogo(cwd: string): string | undefined {\n for (const dir of DIRECTORIES) {\n for (const name of NAMES) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return relative;\n }\n }\n }\n for (const dir of DIRECTORIES) {\n for (const name of FALLBACKS) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return relative;\n }\n }\n }\n return undefined;\n}\n\nexport function findLogoPair(cwd: string): { light: string; dark?: string } | undefined {\n const light = findLogo(cwd);\n if (light === undefined) {\n return undefined;\n }\n const darkNames = [\"logo-dark.svg\", \"logo-dark.png\"];\n for (const dir of DIRECTORIES) {\n for (const name of darkNames) {\n const relative = dir === \"\" ? name : join(dir, name);\n if (existsSync(join(cwd, relative))) {\n return { light, dark: relative };\n }\n }\n }\n return { light };\n}\n","// Minimal PNG reader for brand color detection.\n// Spec: docs/PROJECT_PLAN.md §10.3 (logo color detection)\n//\n// Logos are the only PNGs this reads, so it covers what logo exporters emit: 8 and 16 bit\n// depths, color types 0, 2, 3, 4 and 6, no interlacing. Anything else returns undefined and\n// the caller reports the color as not found rather than guessing. Decoding is done here\n// instead of with a library because `pngjs` would be a runtime dependency for one small job.\n\nimport { inflateSync } from \"node:zlib\";\n\nconst SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);\n\n/** Channels per pixel for each PNG color type. Index is the color type. */\nconst CHANNELS: Record<number, number> = { 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 };\n\nexport interface DecodedPng {\n width: number;\n height: number;\n /** Row-major RGBA, four bytes per pixel. */\n pixels: Uint8Array;\n}\n\nexport function decodePng(buffer: Buffer): DecodedPng | undefined {\n if (buffer.length < 8 || !buffer.subarray(0, 8).equals(SIGNATURE)) {\n return undefined;\n }\n\n let width = 0;\n let height = 0;\n let bitDepth = 0;\n let colorType = 0;\n let interlace = 0;\n let palette: Buffer | undefined;\n let paletteAlpha: Buffer | undefined;\n const idat: Buffer[] = [];\n\n let offset = 8;\n while (offset + 8 <= buffer.length) {\n const length = buffer.readUInt32BE(offset);\n const type = buffer.toString(\"ascii\", offset + 4, offset + 8);\n const start = offset + 8;\n const end = start + length;\n if (end > buffer.length) {\n return undefined;\n }\n\n if (type === \"IHDR\") {\n width = buffer.readUInt32BE(start);\n height = buffer.readUInt32BE(start + 4);\n bitDepth = buffer[start + 8] ?? 0;\n colorType = buffer[start + 9] ?? 0;\n interlace = buffer[start + 12] ?? 0;\n } else if (type === \"PLTE\") {\n palette = buffer.subarray(start, end);\n } else if (type === \"tRNS\") {\n paletteAlpha = buffer.subarray(start, end);\n } else if (type === \"IDAT\") {\n idat.push(buffer.subarray(start, end));\n } else if (type === \"IEND\") {\n break;\n }\n\n offset = end + 4; // skip the CRC\n }\n\n const channels = CHANNELS[colorType];\n if (\n width === 0 ||\n height === 0 ||\n channels === undefined ||\n interlace !== 0 ||\n (bitDepth !== 8 && bitDepth !== 16) ||\n idat.length === 0 ||\n (colorType === 3 && palette === undefined)\n ) {\n return undefined;\n }\n\n // Guard against a malformed header claiming an enormous image.\n if (width * height > 64_000_000) {\n return undefined;\n }\n\n let raw: Buffer;\n try {\n raw = inflateSync(Buffer.concat(idat));\n } catch {\n return undefined;\n }\n\n const bytesPerSample = bitDepth / 8;\n const bpp = channels * bytesPerSample;\n const stride = width * bpp;\n if (raw.length < height * (stride + 1)) {\n return undefined;\n }\n\n const unfiltered = unfilter(raw, height, stride, bpp);\n if (unfiltered === undefined) {\n return undefined;\n }\n\n return { width, height, pixels: toRgba(unfiltered, width, height, colorType, bytesPerSample, palette, paletteAlpha) };\n}\n\n/** Reverse the per-scanline filters defined in the PNG spec. */\nfunction unfilter(raw: Buffer, height: number, stride: number, bpp: number): Buffer | undefined {\n const out = Buffer.alloc(height * stride);\n let pos = 0;\n for (let y = 0; y < height; y++) {\n const filter = raw[pos];\n pos += 1;\n if (filter === undefined || filter > 4) {\n return undefined;\n }\n const rowStart = y * stride;\n const prevStart = rowStart - stride;\n for (let x = 0; x < stride; x++) {\n const value = raw[pos + x] ?? 0;\n const a = x >= bpp ? (out[rowStart + x - bpp] ?? 0) : 0;\n const b = y > 0 ? (out[prevStart + x] ?? 0) : 0;\n const c = x >= bpp && y > 0 ? (out[prevStart + x - bpp] ?? 0) : 0;\n let restored: number;\n switch (filter) {\n case 1: {\n restored = value + a;\n break;\n }\n case 2: {\n restored = value + b;\n break;\n }\n case 3: {\n restored = value + Math.floor((a + b) / 2);\n break;\n }\n case 4: {\n restored = value + paeth(a, b, c);\n break;\n }\n default: {\n restored = value;\n }\n }\n out[rowStart + x] = restored & 0xff;\n }\n pos += stride;\n }\n return out;\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n if (pa <= pb && pa <= pc) {\n return a;\n }\n return pb <= pc ? b : c;\n}\n\nfunction toRgba(\n data: Buffer,\n width: number,\n height: number,\n colorType: number,\n bytesPerSample: number,\n palette: Buffer | undefined,\n paletteAlpha: Buffer | undefined,\n): Uint8Array {\n const pixels = new Uint8Array(width * height * 4);\n const channels = CHANNELS[colorType] ?? 4;\n const bpp = channels * bytesPerSample;\n\n for (let i = 0; i < width * height; i++) {\n // For 16 bit samples the high byte is a close enough approximation for color picking.\n const at = (channel: number): number => data[i * bpp + channel * bytesPerSample] ?? 0;\n const out = i * 4;\n switch (colorType) {\n case 0: {\n const g = at(0);\n pixels[out] = g;\n pixels[out + 1] = g;\n pixels[out + 2] = g;\n pixels[out + 3] = 255;\n break;\n }\n case 2: {\n pixels[out] = at(0);\n pixels[out + 1] = at(1);\n pixels[out + 2] = at(2);\n pixels[out + 3] = 255;\n break;\n }\n case 3: {\n const index = at(0);\n pixels[out] = palette?.[index * 3] ?? 0;\n pixels[out + 1] = palette?.[index * 3 + 1] ?? 0;\n pixels[out + 2] = palette?.[index * 3 + 2] ?? 0;\n pixels[out + 3] = paletteAlpha?.[index] ?? 255;\n break;\n }\n case 4: {\n const g = at(0);\n pixels[out] = g;\n pixels[out + 1] = g;\n pixels[out + 2] = g;\n pixels[out + 3] = at(1);\n break;\n }\n default: {\n pixels[out] = at(0);\n pixels[out + 1] = at(1);\n pixels[out + 2] = at(2);\n pixels[out + 3] = at(3);\n }\n }\n }\n return pixels;\n}\n\n/**\n * Most common non-neutral color in a logo, as a hex string.\n *\n * Nearly transparent pixels are ignored so a transparent background does not win, and greys\n * are ignored because a logo's black wordmark is not its brand color. Colors are bucketed\n * into 16 levels per channel so anti-aliased edges group with the solid fill they belong to,\n * then the winning bucket reports the average of the real pixels inside it rather than the\n * bucket centre, which would drift the hue.\n */\nexport function dominantNonNeutralColor(png: DecodedPng): string | undefined {\n const buckets = new Map<number, { count: number; r: number; g: number; b: number }>();\n\n for (let i = 0; i < png.pixels.length; i += 4) {\n const a = png.pixels[i + 3] ?? 0;\n if (a < 128) {\n continue;\n }\n const r = png.pixels[i] ?? 0;\n const g = png.pixels[i + 1] ?? 0;\n const b = png.pixels[i + 2] ?? 0;\n if (Math.max(r, g, b) - Math.min(r, g, b) < 16) {\n continue; // grey, including pure black and white\n }\n const key = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);\n const bucket = buckets.get(key);\n if (bucket === undefined) {\n buckets.set(key, { count: 1, r, g, b });\n } else {\n bucket.count += 1;\n bucket.r += r;\n bucket.g += g;\n bucket.b += b;\n }\n }\n\n let best: { count: number; r: number; g: number; b: number } | undefined;\n for (const bucket of buckets.values()) {\n if (best === undefined || bucket.count > best.count) {\n best = bucket;\n }\n }\n if (best === undefined) {\n return undefined;\n }\n\n const channel = (total: number): string =>\n Math.round(total / best.count)\n .toString(16)\n .padStart(2, \"0\");\n return `#${channel(best.r)}${channel(best.g)}${channel(best.b)}`;\n}\n","// Brand detection pipeline\n// Spec: docs/PROJECT_PLAN.md §10.3\n\nimport { z } from \"zod\";\nimport { ensureForegroundContrast } from \"./color.js\";\nimport {\n applyReadableAccent,\n applyReadableMuted,\n detectColorsFrom,\n upsertSource,\n type FieldSource,\n} from \"./detect-colors.js\";\nimport type { ProjectFiles } from \"./files.js\";\nimport { findLogoPair } from \"./logo.js\";\nimport { decodePng, dominantNonNeutralColor } from \"./png.js\";\n// One implementation only. detect.ts previously carried its own copies of these, which\n// drifted from the ones in sources/readme.ts and read a YAML comment as the project name.\nimport { extractH1, extractTagline } from \"../sources/readme.js\";\nimport {\n DEFAULT_BRAND_FONTS,\n type Brand,\n} from \"./schema.js\";\n\n\n\n\n\n/** Path helpers, kept local so this module stays free of `node:path` and reaches the browser. */\nfunction basename(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\n\nexport interface BrandDetection {\n brand: Brand;\n sources: FieldSource[];\n notes: string[];\n}\n\nconst packageSchema = z.object({\n private: z.boolean().optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n homepage: z.string().optional(),\n repository: z.union([z.string(), z.object({ url: z.string().optional() })]).optional(),\n});\n\n\n/**\n * Detection over any source. `root` is only used to make reported paths readable, so the\n * GitHub implementation can pass the repository slug.\n */\nexport async function detectBrandFrom(files: ProjectFiles, cwd = \".\"): Promise<BrandDetection> {\n const sources: FieldSource[] = [];\n const notes: string[] = [];\n const pkg = await readPackage(files);\n const readme = await files.read(\"README.md\");\n\n const name = detectName(pkg, readme, cwd, sources);\n const tagline = detectTagline(pkg, readme, sources);\n const url = await detectUrl(files, pkg, cwd, sources);\n const logo = findLogoPair(cwd);\n if (logo !== undefined) {\n sources.push({ field: \"logo\", source: logo.light });\n }\n\n const colors = await detectColorsFrom(files, cwd, logo?.light, sources, notes, dominantLogoColor);\n const contrast = ensureForegroundContrast(colors.background, colors.foreground);\n if (contrast.adjusted) {\n colors.foreground = contrast.foreground;\n notes.push(\n `Foreground failed WCAG AA large-text contrast (3:1) against background, so it was set to ${contrast.foreground}.`,\n );\n upsertSource(sources, \"colors.foreground\", \"contrast adjustment\");\n }\n applyReadableMuted(colors, sources, notes);\n applyReadableAccent(colors, sources, notes);\n\n const brand: Brand = {\n version: 1,\n name,\n colors,\n fonts: {\n heading: { ...DEFAULT_BRAND_FONTS.heading },\n body: { ...DEFAULT_BRAND_FONTS.body },\n mono: { ...DEFAULT_BRAND_FONTS.mono },\n },\n radius: 16,\n theme: \"dark\",\n style: \"minimal\",\n tokens: null,\n };\n if (tagline !== undefined) {\n brand.tagline = tagline;\n }\n if (url !== undefined) {\n brand.url = url;\n }\n if (logo !== undefined) {\n brand.logo = logo.dark === undefined ? { light: logo.light } : { light: logo.light, dark: logo.dark };\n }\n sources.push({ field: \"fonts\", source: \"built-in Geist / vendored Geist Mono\" });\n return { brand, sources, notes };\n}\n\nfunction detectName(\n pkg: z.infer<typeof packageSchema> | undefined,\n readme: string | undefined,\n cwd: string,\n sources: FieldSource[],\n): string {\n // A private package.json is a workspace root, and its name is plumbing, not a brand.\n // The shipseal repo's own root is \"shipseal-monorepo\", which is not what to put on a card.\n if (pkg?.name !== undefined && pkg.private !== true) {\n const fromPkg = stripScope(pkg.name);\n const h1 = readme === undefined ? undefined : extractH1(readme);\n if (h1 !== undefined && h1.toLowerCase() === fromPkg.toLowerCase() && h1 !== fromPkg) {\n sources.push({ field: \"name\", source: \"README.md H1\" });\n return h1;\n }\n sources.push({ field: \"name\", source: \"package.json#name\" });\n return fromPkg;\n }\n const h1 = readme === undefined ? undefined : extractH1(readme);\n if (h1 !== undefined) {\n sources.push({ field: \"name\", source: \"README.md H1\" });\n return h1;\n }\n sources.push({ field: \"name\", source: \"directory name\" });\n const fromDir = basename(cwd);\n return fromDir.length > 0 ? fromDir : \"project\";\n}\n\nfunction detectTagline(\n pkg: z.infer<typeof packageSchema> | undefined,\n readme: string | undefined,\n sources: FieldSource[],\n): string | undefined {\n if (pkg?.description !== undefined && pkg.description.trim().length > 0) {\n sources.push({ field: \"tagline\", source: \"package.json#description\" });\n return pkg.description.trim();\n }\n if (readme !== undefined) {\n const tagline = extractTagline(readme);\n if (tagline !== undefined) {\n sources.push({ field: \"tagline\", source: \"README.md first paragraph\" });\n return tagline;\n }\n }\n return undefined;\n}\n\nasync function detectUrl(\n files: ProjectFiles,\n pkg: z.infer<typeof packageSchema> | undefined,\n cwd: string,\n sources: FieldSource[],\n): Promise<string | undefined> {\n if (pkg?.homepage !== undefined && pkg.homepage.length > 0) {\n sources.push({ field: \"url\", source: \"package.json#homepage\" });\n return pkg.homepage;\n }\n const repo = repositoryUrl(pkg?.repository);\n if (repo !== undefined) {\n sources.push({ field: \"url\", source: \"package.json#repository\" });\n return repo;\n }\n const remote = await files.gitRemote?.();\n if (remote !== undefined) {\n sources.push({ field: \"url\", source: \"git remote origin\" });\n return remote;\n }\n return undefined;\n}\n\n\n\n\n\n\nasync function readPackage(files: ProjectFiles): Promise<z.infer<typeof packageSchema> | undefined> {\n const raw = await files.read(\"package.json\");\n if (raw === undefined) {\n return undefined;\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n const result = packageSchema.safeParse(parsed);\n return result.success ? result.data : undefined;\n } catch (error) {\n if (error instanceof SyntaxError) {\n return undefined;\n }\n throw error;\n }\n}\n\n\n\n\n\nfunction stripScope(name: string): string {\n const parts = name.split(\"/\");\n return parts[parts.length - 1] ?? name;\n}\n\n\nfunction repositoryUrl(repository: z.infer<typeof packageSchema>[\"repository\"]): string | undefined {\n if (typeof repository === \"string\") {\n return normalizeGitUrl(repository);\n }\n if (repository?.url !== undefined) {\n return normalizeGitUrl(repository.url);\n }\n return undefined;\n}\n\nexport function normalizeGitUrl(url: string): string {\n const ssh = /^git@([^:]+):(.+)$/.exec(url);\n if (ssh !== null && ssh[1] !== undefined && ssh[2] !== undefined) {\n return `https://${ssh[1]}/${ssh[2].replace(/\\.git$/, \"\")}`;\n }\n return url.replace(/^git\\+/, \"\").replace(/\\.git$/, \"\");\n}\n\n/**\n * Dominant non-neutral color of a PNG logo, or undefined when the file cannot be read or\n * carries no color. Detection reports the color as not found rather than falling back to a\n * built-in default that would be presented to the user as \"your brand\".\n */\nasync function dominantLogoColor(files: ProjectFiles, path: string): Promise<string | undefined> {\n const buffer = await files.readBinary(path);\n if (buffer === undefined) {\n return undefined;\n }\n const png = decodePng(Buffer.from(buffer));\n if (png === undefined) {\n return undefined;\n }\n return dominantNonNeutralColor(png);\n}\n\n","// The disk half of brand detection. Split out so `detect.ts` carries no `node:` import and the\n// browser demo can run the same detection over the GitHub API (review R0). The split mirrors\n// `render/takumi.ts` and `render/takumi-node.ts`, for the same reason: one top-level Node\n// builtin is enough for Vite to externalise a module and serve /try a blank page.\n\nimport { execFile } from \"node:child_process\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { isAbsolute, join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { detectBrandFrom, normalizeGitUrl, type BrandDetection } from \"./detect.js\";\nimport type { ProjectFiles } from \"./files.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"coverage\",\n \".next\",\n \".astro\",\n \"out\",\n \"vendor\",\n]);\n\nexport async function detectBrand(cwd: string): Promise<BrandDetection> {\n return detectBrandFrom(diskFiles(cwd), cwd);\n}\n\n/** The disk implementation of the port, used by the CLI. Paths stay absolute here. */\nexport function diskFiles(cwd: string, maxDepth = 4): ProjectFiles {\n return {\n list: () => listFiles(cwd, maxDepth),\n read: async (path) => {\n try {\n return await readFile(isAbsolute(path) ? path : join(cwd, path), \"utf8\");\n } catch {\n return undefined;\n }\n },\n gitRemote: () => gitRemote(cwd),\n readBinary: async (path) => {\n try {\n return await readFile(isAbsolute(path) ? path : join(cwd, path));\n } catch {\n return undefined;\n }\n },\n };\n}\n\nasync function listFiles(root: string, maxDepth: number): Promise<string[]> {\n const out: string[] = [];\n const walk = async (dir: string, depth: number): Promise<void> => {\n if (depth < 0) {\n return;\n }\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n const nested: Promise<void>[] = [];\n for (const entry of entries) {\n if (entry.name.startsWith(\".\") && entry.name !== \".github\") {\n continue;\n }\n const path = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n nested.push(walk(path, depth - 1));\n } else {\n out.push(path);\n }\n }\n await Promise.all(nested);\n };\n await walk(root, maxDepth);\n return out;\n}\n\nasync function gitRemote(cwd: string): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd });\n return normalizeGitUrl(stdout.trim());\n } catch (error) {\n if (error instanceof Error) {\n return undefined;\n }\n throw error;\n }\n}\n","// init: detect brand, write .shipseal/brand.json + config.json, render sample\n// Spec: docs/PROJECT_PLAN.md §18.1\n\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\nimport { join } from \"node:path\";\nimport type { BrandDetection } from \"../brand/detect.js\";\nimport { detectBrand } from \"../brand/detect-node.js\";\nimport { brandSchema } from \"../brand/schema.js\";\nimport { DEFAULT_CONFIG, configSchema } from \"../config/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { generate } from \"../core/generate.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\n\nexport interface InitOptions {\n cwd: string;\n yes: boolean;\n force: boolean;\n}\n\nexport interface InitResult {\n brandPath: string;\n configPath: string;\n samplePath: string;\n detection: BrandDetection;\n}\n\nexport async function runInit(options: InitOptions): Promise<InitResult> {\n const detection = await detectBrand(options.cwd);\n const brandDir = join(options.cwd, \".shipseal\");\n const brandPath = join(brandDir, \"brand.json\");\n const configPath = join(brandDir, \"config.json\");\n\n if (!options.force && (existsSync(brandPath) || existsSync(configPath))) {\n throw new ShipsealError(\n \"init.exists\",\n \".shipseal/brand.json or config.json already exists.\",\n \"Re-run with --force to overwrite, or edit the files by hand.\",\n );\n }\n\n if (!options.yes) {\n const accepted = await confirmInit(detection);\n if (!accepted) {\n throw new ShipsealError(\n \"init.cancelled\",\n \"Init cancelled; no files were written.\",\n \"Re-run shipseal init and confirm, or pass --yes to accept detections.\",\n );\n }\n }\n\n const brand = brandSchema.parse(detection.brand);\n const config = configSchema.parse(DEFAULT_CONFIG);\n await mkdir(brandDir, { recursive: true });\n await writeFile(brandPath, `${JSON.stringify(brand, null, 2)}\\n`, \"utf8\");\n await writeFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf8\");\n await ensureGitignore(options.cwd);\n\n const sampleDir = join(brandDir, \"output\", \"sample\");\n await mkdir(sampleDir, { recursive: true });\n const samplePath = join(sampleDir, \"release-hero-og.png\");\n const renderer = await createTakumiRenderer();\n // Render the real release-hero template with the brand just detected. This used to be a\n // hard-coded card that said \"Shipseal\" for every user, which made the tool look like it had\n // ignored their project. The point of the sample is to show them their own brand.\n const fetchedAt = new Date().toISOString();\n const provenance = { source: \"brand\" as const, ref: \".shipseal/brand.json\", fetchedAt };\n const sampleFacts: Facts = {\n project: { name: fact(brand.name, provenance) },\n };\n if (brand.tagline !== undefined) {\n sampleFacts.project.tagline = fact(brand.tagline, provenance);\n }\n if (brand.url !== undefined) {\n sampleFacts.project.url = fact(brand.url, provenance);\n }\n const sample = await generate({\n event: { kind: \"release\", tag: \"v1.0.0\" },\n facts: sampleFacts,\n brand,\n config: { ...config, formats: [\"og\"], release: { ...config.release, templates: [\"release-hero\"] } },\n copy: deterministicCopy(sampleFacts),\n copyMode: \"deterministic\",\n renderer,\n themes: [brand.theme],\n generatedAt: fetchedAt,\n });\n const first = sample.files[0];\n if (first === undefined) {\n throw new ShipsealError(\n \"init.sample-failed\",\n \"Could not render the sample card.\",\n \"Run shipseal doctor to check fonts and the renderer.\",\n );\n }\n await writeFile(samplePath, first.bytes);\n\n return { brandPath, configPath, samplePath, detection };\n}\n\nasync function confirmInit(detection: BrandDetection): Promise<boolean> {\n if (!input.isTTY) {\n throw new ShipsealError(\n \"init.unattended\",\n \"stdin is not a TTY, so init cannot ask for confirmation.\",\n \"Re-run with --yes to accept the detected brand and write files.\",\n );\n }\n output.write(\"Detected brand:\\n\");\n for (const field of detection.sources) {\n output.write(` ${field.field}: from ${field.source}\\n`);\n }\n for (const note of detection.notes) {\n output.write(` note: ${note}\\n`);\n }\n const rl = createInterface({ input, output });\n try {\n const answer = await rl.question(\"Write .shipseal/brand.json and config.json? [y/N] \");\n return answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\";\n } finally {\n rl.close();\n }\n}\n\nasync function ensureGitignore(cwd: string): Promise<void> {\n const path = join(cwd, \".gitignore\");\n const entry = \".shipseal/output/\";\n if (!existsSync(path)) {\n await writeFile(path, `${entry}\\n`, \"utf8\");\n return;\n }\n const current = await readFile(path, \"utf8\");\n if (current.split(/\\r?\\n/).some((line) => line.trim() === entry || line.trim() === \".shipseal/output\")) {\n return;\n }\n const prefix = current.endsWith(\"\\n\") || current.length === 0 ? \"\" : \"\\n\";\n await writeFile(path, `${current}${prefix}${entry}\\n`, \"utf8\");\n}\n","// milestone: card for highest crossed threshold\n// Spec: docs/PROJECT_PLAN.md §18.3\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { milestoneCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport type MilestoneMetric = \"stars\" | \"downloads\" | \"contributors\";\n\nexport interface MilestoneFlags extends SharedFlags {\n metric?: string;\n threshold?: string;\n}\n\nexport interface MilestoneResult {\n dryRun: boolean;\n skipped: boolean;\n message?: string;\n facts: Facts;\n copy?: import(\"../copy/slots.js\").Copy;\n copyMode?: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runMilestone(flags: MilestoneFlags): Promise<MilestoneResult> {\n const cwd = flags.cwd;\n const config = overlayFormats(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const placeholder: ShipsealEvent = { kind: \"milestone\", metric: \"stars\", threshold: 0 };\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event: placeholder,\n skipNetwork: env.skipNetwork,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n if (env.githubToken !== undefined) {\n collectOpts.githubToken = env.githubToken;\n }\n if (env.fetchImpl !== undefined) {\n collectOpts.fetchImpl = env.fetchImpl;\n }\n const collected = await collectFacts(collectOpts);\n const selected = selectMilestone(collected, config, parseMetric(flags.metric), parseThreshold(flags.threshold));\n if (selected === undefined) {\n return {\n dryRun: flags.dryRun === true,\n skipped: true,\n message: \"No milestone threshold crossed. Nothing to generate.\",\n facts: collected,\n warnings: [],\n exitCode: 0,\n };\n }\n\n const fetchedAt = new Date().toISOString();\n const metricKey = selected.metric === \"downloads\" ? \"downloads\" : selected.metric;\n const facts: Facts = {\n ...collected,\n milestone: {\n metric: fact(selected.metric, { source: \"user-config\", ref: \"shipseal milestone --metric\", fetchedAt }),\n threshold: fact(selected.threshold, {\n source: \"user-config\",\n ref: `config.json milestones.${metricKey}`,\n fetchedAt,\n }),\n },\n };\n const event: ShipsealEvent = { kind: \"milestone\", metric: selected.metric, threshold: selected.threshold };\n const fallback = milestoneCopy(facts, selected.metric, selected.threshold);\n const resolved = await resolveCopy(facts, config, flags.copy === false, fallback);\n\n if (flags.dryRun === true) {\n const dry: MilestoneResult = {\n dryRun: true,\n skipped: false,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n const packed = await finishPack(packInput);\n return { ...packed, skipped: false };\n}\n\nexport function highestCrossed(thresholds: number[], current: number): number | undefined {\n const crossed = thresholds.filter((item) => current >= item).toSorted((a, b) => b - a);\n return crossed[0];\n}\n\nexport function selectMilestone(\n facts: Facts,\n config: Config,\n metric: MilestoneMetric | undefined,\n threshold: number | undefined,\n): { metric: MilestoneMetric; threshold: number } | undefined {\n const metrics: MilestoneMetric[] = metric === undefined ? [\"stars\", \"downloads\", \"contributors\"] : [metric];\n const candidates: Array<{ metric: MilestoneMetric; threshold: number }> = [];\n for (const item of metrics) {\n const current = currentValue(facts, item);\n if (current === undefined) {\n if (metric !== undefined) {\n throw missingMetric(item);\n }\n continue;\n }\n const list = thresholdsFor(config, item);\n if (threshold !== undefined) {\n if (metric !== undefined || list.includes(threshold)) {\n return { metric: item, threshold };\n }\n continue;\n }\n const crossed = highestCrossed(list, current);\n if (crossed !== undefined) {\n candidates.push({ metric: item, threshold: crossed });\n }\n }\n return candidates.toSorted(\n (a, b) => b.threshold - a.threshold || metrics.indexOf(a.metric) - metrics.indexOf(b.metric),\n )[0];\n}\n\nfunction currentValue(facts: Facts, metric: MilestoneMetric): number | undefined {\n if (metric === \"stars\") {\n return facts.metrics?.stars?.value;\n }\n if (metric === \"downloads\") {\n return facts.metrics?.weeklyDownloads?.value;\n }\n return facts.metrics?.contributorCount?.value;\n}\n\nfunction thresholdsFor(config: Config, metric: MilestoneMetric): number[] {\n if (metric === \"stars\") {\n return config.milestones?.stars ?? [];\n }\n if (metric === \"downloads\") {\n return config.milestones?.downloads ?? [];\n }\n return config.milestones?.contributors ?? [];\n}\n\nfunction parseMetric(value: string | undefined): MilestoneMetric | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (value === \"stars\" || value === \"downloads\" || value === \"contributors\") {\n return value;\n }\n throw new ShipsealError(\n \"milestone.bad-metric\",\n `Unknown metric \"${value}\".`,\n \"Use --metric stars, --metric downloads, or --metric contributors.\",\n );\n}\n\nfunction parseThreshold(value: string | undefined): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n const parsed = Number.parseInt(value, 10);\n if (!Number.isInteger(parsed) || parsed <= 0) {\n throw new ShipsealError(\n \"milestone.bad-threshold\",\n `Invalid threshold \"${value}\".`,\n \"Pass a positive integer, for example --threshold 1000.\",\n );\n }\n return parsed;\n}\n\nfunction missingMetric(metric: MilestoneMetric): ShipsealError {\n if (metric === \"stars\") {\n return new ShipsealError(\n \"milestone.missing-stars\",\n \"Could not read GitHub stars for this repo.\",\n \"Set GITHUB_TOKEN, or confirm package.json repository points at a public GitHub repo.\",\n );\n }\n if (metric === \"downloads\") {\n return new ShipsealError(\n \"milestone.missing-downloads\",\n \"Could not read npm weekly downloads for this package.\",\n \"Confirm package.json name is published on npm, then retry without --dry-run.\",\n );\n }\n return new ShipsealError(\n \"milestone.missing-contributors\",\n \"Could not read the GitHub contributor count for this repo.\",\n \"Set GITHUB_TOKEN, or confirm package.json repository points at a public GitHub repo.\",\n );\n}\n","// release: generate the release pack\n// Spec: docs/PROJECT_PLAN.md §18.2\n\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig, mergeConfig } from \"../config/load.js\";\nimport { DEFAULT_CONFIG, type Config } from \"../config/schema.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { generate } from \"../core/generate.js\";\nimport type { ShipsealEvent } from \"../core/events.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport {\n collectEnv,\n finishPack,\n loadLogos,\n overlayFormats,\n resolveCopy,\n resolveThemes,\n type SharedFlags,\n} from \"./shared.js\";\n\nexport interface ReleaseFlags extends SharedFlags {\n tag?: string;\n from?: string;\n templates?: string;\n headline?: string;\n subheadline?: string;\n}\n\n/** Lowest kind worth announcing, most significant first. */\nconst ANNOUNCE_ORDER = [\"major\", \"minor\", \"patch\"] as const;\n\nexport interface ReleaseResult {\n dryRun: boolean;\n skipped?: boolean;\n message?: string;\n facts: Awaited<ReturnType<typeof collectFacts>>;\n copy: import(\"../copy/slots.js\").Copy;\n copyMode: \"deterministic\" | \"llm\";\n copyWarning?: string;\n dir?: string;\n manifest?: import(\"../outputs/manifest.js\").Manifest;\n warnings: import(\"../core/generate.js\").GenerateResult[\"warnings\"];\n exitCode: 0 | 1 | 2;\n}\n\nexport async function runRelease(flags: ReleaseFlags): Promise<ReleaseResult> {\n const cwd = flags.cwd;\n const config = overlayReleaseConfig(await loadConfig(cwd), flags);\n const brand = await loadBrand(cwd);\n const tag = flags.tag ?? (await gitCurrentTag(cwd));\n if (tag === undefined) {\n throw new ShipsealError(\n \"release.no-tag\",\n \"No git tag found for this release.\",\n \"Create a git tag, or pass --tag vX.Y.Z.\",\n );\n }\n const event: ShipsealEvent =\n flags.from === undefined\n ? { kind: \"release\", tag }\n : { kind: \"release\", tag, previousTag: flags.from };\n\n const env = collectEnv(flags);\n const collectOpts: Parameters<typeof collectFacts>[0] = {\n cwd,\n event,\n skipNetwork: env.skipNetwork,\n };\n if (env.packagePath !== undefined) {\n collectOpts.packagePath = env.packagePath;\n }\n if (config.release?.changelogPath !== undefined) {\n collectOpts.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collectOpts.snippet = config.release.snippet;\n }\n if (env.githubToken !== undefined) {\n collectOpts.githubToken = env.githubToken;\n }\n if (env.fetchImpl !== undefined) {\n collectOpts.fetchImpl = env.fetchImpl;\n }\n const headline = flags.headline ?? config.release?.headline ?? undefined;\n if (headline !== undefined) {\n collectOpts.headline = headline;\n }\n const subheadline = flags.subheadline ?? config.release?.subheadline ?? undefined;\n if (subheadline !== undefined) {\n collectOpts.subheadline = subheadline;\n }\n const facts = await collectFacts(collectOpts);\n\n // Below the configured threshold there is nothing worth posting. Reported the same way\n // `milestone` reports an uncrossed threshold: exit 0, `skipped` true, and say why.\n const announce = config.release?.announce ?? \"patch\";\n const kind = facts.release?.kind?.value;\n if (kind !== undefined && ANNOUNCE_ORDER.indexOf(kind) > ANNOUNCE_ORDER.indexOf(announce)) {\n return {\n dryRun: flags.dryRun === true,\n skipped: true,\n message: `This is a ${kind} release and release.announce is \"${announce}\". Nothing to generate.`,\n facts,\n copy: deterministicCopy(facts, config.release?.maxHighlights, brand.name),\n copyMode: \"deterministic\",\n warnings: [],\n exitCode: 0,\n };\n }\n\n const noCopy = flags.copy === false;\n const resolved = await resolveCopy(facts, config, noCopy, deterministicCopy(facts, config.release?.maxHighlights, brand.name));\n\n if (flags.dryRun === true) {\n const dry: ReleaseResult = {\n dryRun: true,\n facts,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n warnings: [],\n exitCode: 0,\n };\n if (resolved.warning !== undefined) {\n dry.copyWarning = resolved.warning;\n }\n return dry;\n }\n\n const renderer = await createTakumiRenderer();\n const generateInput: Parameters<typeof generate>[0] = {\n event,\n facts,\n brand,\n config,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n renderer,\n themes: resolveThemes(flags.themes, brand.theme),\n generatedAt: new Date().toISOString(),\n };\n const logos = await loadLogos(cwd, brand);\n if (logos !== undefined) {\n generateInput.logos = logos;\n }\n const result = await generate(generateInput);\n const packInput: Parameters<typeof finishPack>[0] = {\n flags,\n config,\n event,\n result,\n brand,\n copy: resolved.copy,\n copyMode: resolved.copyMode,\n facts,\n };\n if (resolved.warning !== undefined) {\n packInput.copyWarning = resolved.warning;\n }\n return finishPack(packInput);\n}\n\nfunction overlayReleaseConfig(config: Config, flags: ReleaseFlags): Config {\n const overlay = overlayFormats(config, flags);\n if (flags.templates === undefined) {\n return overlay;\n }\n return mergeConfig(DEFAULT_CONFIG, {\n ...overlay,\n release: {\n ...overlay.release,\n templates: flags.templates\n .split(\",\")\n .map((item) => item.trim())\n .filter((item) => item.length > 0),\n },\n });\n}\n","// Release stories: an ordered set of pages built from release facts, each rendered by the\n// `story-page` template. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n//\n// Page order is fixed: cover, one page per change, an optional code page, an optional\n// comparison of supplied screenshots, then the upgrade page.\n\nimport type { Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { cleanLine, deterministicCopy, firstSentence } from \"../copy/deterministic.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Fact, Facts, StoryPage } from \"../facts/schema.js\";\nimport { ShipsealError } from \"./errors.js\";\nimport { generate, type GenerateInput, type GenerateResult } from \"./generate.js\";\n\nconst DEFAULT_CHANGE_PAGES = 4;\nconst STORY_FORMATS = \"portrait, square, og, github-social, x, linkedin, or producthunt\";\n\nexport function storyFacts(\n facts: Facts,\n config: Config,\n brand: Pick<Brand, \"name\" | \"tagline\">,\n generatedAt: string,\n): Facts {\n const release = facts.release;\n if (release === undefined) {\n throw new ShipsealError(\n \"story.no-release\",\n \"No release facts are available for a story.\",\n \"Choose a published release or pass --tag to a local repository.\",\n );\n }\n const copy = deterministicCopy(facts, config.release?.maxHighlights, brand.name);\n const configured = (value: string, ref: string): Fact<string> =>\n fact(value, { source: \"user-config\", ref, fetchedAt: generatedAt });\n\n const changes = [...release.breaking, ...release.features, ...release.fixes];\n // The cover headline carries the provenance of the change it was taken from, so a card\n // number or claim is always traceable back to the release notes.\n const headlineSource =\n release.headline ??\n changes.find((item) => cleanLine(firstSentence(item.value)) === copy.headline) ??\n release.version;\n const pages: StoryPage[] = [\n {\n kind: \"cover\",\n title: fact(copy.headline, headlineSource.provenance),\n // The brand file is a declared source like any other, so prefer its tagline over the\n // \"Release notes\" placeholder. Only fall back when nothing describes the project.\n body:\n release.subheadline ??\n facts.project.tagline ??\n (brand.tagline === undefined\n ? fact(\"Release notes\", release.tag.provenance)\n : fact(brand.tagline, {\n source: \"user-config\",\n ref: \"brand.json#tagline\",\n fetchedAt: generatedAt,\n })),\n },\n ];\n\n for (const item of changes.slice(0, config.release?.maxHighlights ?? DEFAULT_CHANGE_PAGES)) {\n // The title is the entry's first sentence, so the body is what follows it. Passing the\n // whole entry would print that sentence twice on the same page.\n const collapsed = item.value.replaceAll(/\\s+/g, \" \").trim();\n const sentence = firstSentence(collapsed);\n const remainder = collapsed.slice(sentence.length).trim();\n pages.push({\n kind: \"change\",\n title: fact(cleanLine(sentence), item.provenance),\n body: fact(remainder.length > 0 ? cleanLine(remainder) : \"\", item.provenance),\n });\n }\n\n if (release.codeSnippet !== undefined) {\n pages.push({\n kind: \"code\",\n title: fact(\"Code example\", release.codeSnippet.provenance),\n body: fact(release.codeSnippet.value.code, release.codeSnippet.provenance),\n });\n }\n\n const options = config.release?.story;\n if (options?.before !== undefined && options.after !== undefined) {\n pages.push({\n kind: \"comparison\",\n title: configured(\"Before and after\", \"release.story.before + release.story.after\"),\n body: configured(\"Supplied screenshots\", \"release.story\"),\n before: configured(options.before, \"release.story.before\"),\n after: configured(options.after, \"release.story.after\"),\n });\n }\n\n const hasUpgrade = options?.upgrade !== undefined && options.upgrade.trim().length > 0;\n let upgrade: Fact<string>;\n if (hasUpgrade && options?.upgrade !== undefined) {\n // Trimmed, not cleaned: this is a command the maintainer expects to be copied and run.\n // cleanLine capitalises the first letter and collapses newlines, which breaks both a\n // `pnpm add ...` line and a multi-line block.\n upgrade = configured(options.upgrade.trim(), \"release.story.upgrade\");\n } else {\n // Never infer an upgrade command from a package name: the release may be breaking, and\n // an invented command is a number-shaped claim the manifest cannot back.\n const repo = facts.project.repo;\n upgrade =\n repo === undefined\n ? fact(copy.cta, facts.project.url?.provenance ?? facts.project.name.provenance)\n : fact(\n `Read the release notes at github.com/${repo.value}/releases/tag/${encodeURIComponent(release.tag.value)}`,\n repo.provenance,\n );\n }\n pages.push({\n kind: \"upgrade\",\n title: fact(hasUpgrade ? \"How to upgrade\" : \"Get the release\", upgrade.provenance),\n body: upgrade,\n });\n\n return { ...facts, story: pages };\n}\n\nexport async function generateStory(input: GenerateInput): Promise<GenerateResult> {\n const facts = storyFacts(input.facts, input.config, input.brand, input.generatedAt);\n const pages = facts.story ?? [];\n const result: GenerateResult = {\n files: [],\n warnings: [],\n missing: [],\n facts,\n copy: input.copy,\n copyMode: \"deterministic\",\n generatedAt: input.generatedAt,\n computed: {},\n };\n const formats = input.config.formats ?? [\"portrait\"];\n if (formats.length === 0 || formats.includes(\"readme-banner\")) {\n throw new ShipsealError(\n \"story.bad-format\",\n \"The story format selection contains no supported output or includes readme-banner.\",\n `Use ${STORY_FORMATS}.`,\n );\n }\n\n for (const [index, page] of pages.entries()) {\n // One renderer instance is shared across pages, so renders are sequential by design.\n // eslint-disable-next-line no-await-in-loop\n const rendered = await generate({\n ...input,\n facts: { ...facts, story: [page] },\n config: {\n ...input.config,\n formats,\n release: { ...input.config.release, templates: [\"story-page\"] },\n },\n });\n const id = `story-${String(index + 1).padStart(2, \"0\")}-${page.kind}`;\n result.files.push(\n ...rendered.files.map((file) => ({\n ...file,\n fileName: file.fileName.replace(\"story-page\", id),\n })),\n );\n result.warnings.push(\n ...rendered.warnings.map((warning) => ({\n ...warning,\n slot: `page-${String(index + 1)}.${warning.slot}`,\n })),\n );\n result.missing.push(...rendered.missing);\n result.computed[`story.pages[${String(index)}]`] = {\n value: {\n kind: page.kind,\n files: result.files\n .filter((file) => file.fileName.startsWith(id))\n .map((file) => file.fileName),\n },\n computedFrom: [`story[${String(index)}].title`, `story[${String(index)}].body`],\n };\n }\n\n if (facts.release?.codeSnippet === undefined) {\n result.missing.push({\n template: \"story-page\",\n fact: \"release.codeSnippet\",\n effect: \"code page omitted\",\n });\n }\n if (pages.every((page) => page.kind !== \"change\")) {\n result.missing.push({\n template: \"story-page\",\n fact: \"release.features\",\n effect: \"change pages omitted because release notes have no changes\",\n });\n }\n return result;\n}\n","// Carousel PDF and ZIP writers. Both are hand-rolled rather than pulled in as dependencies:\n// the output is image streams and stored entries, which needs no compression library\n// (AGENTS.md rule 6). Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { GeneratedFile } from \"../core/generate.js\";\n\nconst encode = (value: string): Uint8Array => new TextEncoder().encode(value);\n\nconst isJpeg = (bytes: Uint8Array): boolean => bytes[0] === 255 && bytes[1] === 216;\n\nexport function joinBytes(parts: Uint8Array[]): Uint8Array {\n const result = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n result.set(part, offset);\n offset += part.length;\n }\n return result;\n}\n\n/**\n * Image-only PDF: each JPEG becomes one page as a DCTDecode stream, so the page is the exact\n * rendered layout rather than a reflow of it. Pages are placed at half the pixel size, which\n * puts a 1080x1350 render on a 540x675pt page at 144dpi.\n *\n * Object numbering: 1 is the catalog, 2 the page tree, then each page contributes three\n * objects (page, image, content stream) at 3 + index * 3.\n */\nexport function carouselPdf(\n pages: Pick<GeneratedFile, \"bytes\" | \"width\" | \"height\">[],\n): Uint8Array {\n if (pages.length === 0 || pages.some((page) => !isJpeg(page.bytes))) {\n throw new ShipsealError(\n \"pdf.invalid-pages\",\n \"A carousel requires nonempty JPEG pages.\",\n \"Render the story as JPEG before building the PDF.\",\n );\n }\n const objects: Uint8Array[] = [\n encode(\"<< /Type /Catalog /Pages 2 0 R >>\"),\n encode(\n `<< /Type /Pages /Count ${String(pages.length)} /Kids [${pages\n .map((_, index) => `${String(3 + index * 3)} 0 R`)\n .join(\" \")}] >>`,\n ),\n ];\n for (const [index, page] of pages.entries()) {\n const id = 3 + index * 3;\n const width = page.width / 2;\n const height = page.height / 2;\n objects.push(\n encode(\n `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${String(width)} ${String(height)}] ` +\n `/Resources << /XObject << /Image ${String(id + 1)} 0 R >> >> ` +\n `/Contents ${String(id + 2)} 0 R >>`,\n ),\n );\n // Takumi renders RGB, so DeviceRGB matches every JPEG it produces.\n objects.push(\n joinBytes([\n encode(\n `<< /Type /XObject /Subtype /Image /Width ${String(page.width)} ` +\n `/Height ${String(page.height)} /ColorSpace /DeviceRGB /BitsPerComponent 8 ` +\n `/Filter /DCTDecode /Length ${String(page.bytes.length)} >>\\nstream\\n`,\n ),\n page.bytes,\n encode(\"\\nendstream\"),\n ]),\n );\n const content = `q ${String(width)} 0 0 ${String(height)} 0 0 cm /Image Do Q`;\n objects.push(\n encode(`<< /Length ${String(encode(content).length)} >>\\nstream\\n${content}\\nendstream`),\n );\n }\n\n const header = encode(\"%PDF-1.4\\n%Shipseal\\n\");\n const parts: Uint8Array[] = [header];\n const offsets: number[] = [];\n let position = header.length;\n for (const [index, object] of objects.entries()) {\n offsets.push(position);\n const bytes = joinBytes([encode(`${String(index + 1)} 0 obj\\n`), object, encode(\"\\nendobj\\n\")]);\n parts.push(bytes);\n position += bytes.length;\n }\n const size = objects.length + 1;\n parts.push(\n encode(\n `xref\\n0 ${String(size)}\\n0000000000 65535 f \\n` +\n offsets.map((offset) => `${String(offset).padStart(10, \"0\")} 00000 n \\n`).join(\"\") +\n `trailer\\n<< /Size ${String(size)} /Root 1 0 R >>\\n` +\n `startxref\\n${String(position)}\\n%%EOF\\n`,\n ),\n );\n return joinBytes(parts);\n}\n\nfunction crc32(bytes: Uint8Array): number {\n let value = 0xffffffff;\n for (const byte of bytes) {\n value ^= byte;\n for (let bit = 0; bit < 8; bit += 1) {\n value = (value >>> 1) ^ ((value & 1) === 1 ? 0xedb88320 : 0);\n }\n }\n return (value ^ 0xffffffff) >>> 0;\n}\n\n/**\n * ZIP with STORE and no compression: PNG and JPEG are already compressed, so deflating them\n * costs time and saves nothing. Every timestamp is the fixed DOS date 1980-01-01 (0x0021) so\n * the same inputs always produce the same archive bytes.\n */\nexport function zipFiles(files: Array<{ name: string; bytes: Uint8Array }>): Uint8Array {\n const FIXED_DOS_DATE = 33;\n const names = new Set<string>();\n const local: Uint8Array[] = [];\n const central: Uint8Array[] = [];\n let offset = 0;\n\n for (const file of files) {\n if (!/^[a-zA-Z0-9_.-]+$/.test(file.name) || names.has(file.name)) {\n throw new ShipsealError(\n \"zip.bad-name\",\n \"An archive file name is unsafe or duplicated.\",\n \"Use unique file names without path separators.\",\n );\n }\n names.add(file.name);\n const name = encode(file.name);\n const checksum = crc32(file.bytes);\n\n // Local file header: signature, version needed, flags, method, time, date, crc,\n // compressed size, uncompressed size, name length, extra length.\n const header = new Uint8Array(30);\n const headerView = new DataView(header.buffer);\n headerView.setUint32(0, 0x04034b50, true);\n headerView.setUint16(4, 20, true);\n headerView.setUint16(12, FIXED_DOS_DATE, true);\n headerView.setUint32(14, checksum, true);\n headerView.setUint32(18, file.bytes.length, true);\n headerView.setUint32(22, file.bytes.length, true);\n headerView.setUint16(26, name.length, true);\n local.push(header, name, file.bytes);\n\n // Central directory entry: as above, plus version made by and the local header offset.\n const entry = new Uint8Array(46);\n const entryView = new DataView(entry.buffer);\n entryView.setUint32(0, 0x02014b50, true);\n entryView.setUint16(4, 20, true);\n entryView.setUint16(6, 20, true);\n entryView.setUint16(14, FIXED_DOS_DATE, true);\n entryView.setUint32(16, checksum, true);\n entryView.setUint32(20, file.bytes.length, true);\n entryView.setUint32(24, file.bytes.length, true);\n entryView.setUint16(28, name.length, true);\n entryView.setUint32(42, offset, true);\n central.push(entry, name);\n offset += header.length + name.length + file.bytes.length;\n }\n\n // End of central directory: entry counts, directory size, directory offset.\n const end = new Uint8Array(22);\n const endView = new DataView(end.buffer);\n endView.setUint32(0, 0x06054b50, true);\n endView.setUint16(8, files.length, true);\n endView.setUint16(10, files.length, true);\n endView.setUint32(12, central.reduce((sum, part) => sum + part.length, 0), true);\n endView.setUint32(16, offset, true);\n return joinBytes([...local, ...central, end]);\n}\n","// One pack builder shared by `shipseal preview`, `shipseal story` and the browser demo, so\n// every surface renders the same bytes. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { z } from \"zod\";\nimport { brandSchema, type Brand } from \"../brand/schema.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { deterministicCopy } from \"../copy/deterministic.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport { generate, type GenerateInput } from \"../core/generate.js\";\nimport { generateStory } from \"../core/story.js\";\nimport { fact } from \"../facts/fact.js\";\nimport type { Facts } from \"../facts/schema.js\";\nimport { V1_FORMAT_IDS, type FormatId } from \"../formats.js\";\nimport { carouselPdf, zipFiles } from \"../outputs/downloads.js\";\nimport { buildManifest } from \"../outputs/manifest.js\";\nimport type { RendererAdapter } from \"../render/adapter.js\";\n\n/** Every format the `story-page` template declares, in the order the selector lists them. */\nconst STORY_FORMATS: FormatId[] = [\n \"portrait\",\n \"square\",\n \"og\",\n \"github-social\",\n \"x\",\n \"linkedin\",\n \"producthunt\",\n];\n\nconst encodeJson = (value: unknown): Uint8Array =>\n new TextEncoder().encode(`${JSON.stringify(value, null, 2)}\\n`);\n\nexport const selectionSchema = z\n .object({\n pack: z.enum([\"story\", \"release\"]).default(\"story\"),\n style: brandSchema.shape.style,\n theme: z.enum([\"dark\", \"light\"]),\n accent: brandSchema.shape.colors.shape.primary,\n headline: z.string().max(500).default(\"\"),\n upgrade: z.string().max(4000).default(\"\"),\n format: z\n .enum([...STORY_FORMATS, \"all\"])\n .default(\"portrait\"),\n })\n .strict();\nexport type StudioSelection = z.infer<typeof selectionSchema>;\n\nexport function selectedConfig(config: Config, selection: StudioSelection): Config {\n const formats: FormatId[] =\n selection.format === \"all\"\n ? selection.pack === \"story\"\n ? [...STORY_FORMATS]\n : [...V1_FORMAT_IDS]\n : [selection.format];\n const landscape = new Set<string>(V1_FORMAT_IDS);\n if (selection.pack === \"release\" && formats.some((format) => !landscape.has(format))) {\n throw new ShipsealError(\n \"preview.format\",\n \"The standard release templates do not support this format.\",\n \"Choose a landscape format or switch to a story pack.\",\n );\n }\n return {\n ...config,\n formats,\n release: {\n ...config.release,\n headline: selection.headline || null,\n story: { ...config.release?.story, upgrade: selection.upgrade },\n },\n output: { imageFormat: \"png\" },\n };\n}\n\nexport function selectedBrand(brand: Brand, selection: StudioSelection): Brand {\n // `theme` stays as stored: it is the native polarity of the palette, not the requested\n // render theme, which travels separately in GenerateInput.themes.\n return {\n ...brand,\n style: selection.style,\n colors: { ...brand.colors, primary: selection.accent },\n };\n}\n\nexport async function buildStudioPack(input: {\n facts: Facts;\n brand: Brand;\n config: Config;\n selection: StudioSelection;\n renderer: RendererAdapter;\n version: string;\n generatedAt: string;\n logos?: GenerateInput[\"logos\"];\n images?: GenerateInput[\"images\"];\n brandSource?: string;\n}) {\n const release = input.facts.release;\n if (release === undefined) {\n throw new ShipsealError(\n \"preview.no-release\",\n \"No release is selected.\",\n \"Load a repository release first.\",\n );\n }\n const config = selectedConfig(input.config, input.selection);\n const brand = selectedBrand(input.brand, input.selection);\n const facts: Facts = { ...input.facts, release: { ...release } };\n if (input.selection.headline) {\n facts.release = {\n ...release,\n headline: fact(input.selection.headline, {\n source: \"user-config\",\n ref: \"release.headline\",\n fetchedAt: input.generatedAt,\n }),\n };\n }\n\n const event = { kind: \"release\" as const, tag: release.tag.value };\n const request: GenerateInput = {\n event,\n facts,\n brand,\n config,\n copy: deterministicCopy(facts, config.release?.maxHighlights, brand.name),\n copyMode: \"deterministic\",\n renderer: input.renderer,\n themes: [input.selection.theme],\n generatedAt: input.generatedAt,\n };\n if (input.logos !== undefined) {\n request.logos = input.logos;\n }\n if (input.images !== undefined) {\n request.images = input.images;\n }\n\n const result = await (input.selection.pack === \"story\" ? generateStory : generate)(request);\n const manifest = buildManifest({ result, event, brand, shipsealVersion: input.version });\n manifest.brand.source = input.brandSource ?? \".shipseal/brand.json + preview selections\";\n const downloads = result.files.map((file) => ({ name: file.fileName, bytes: file.bytes }));\n\n if (input.selection.pack === \"story\") {\n // The PDF pages are re-rendered as JPEG: a carousel embeds DCTDecode streams directly,\n // so the same layout is reused rather than reflowed.\n const pdfFormat = config.formats?.[0] ?? \"portrait\";\n const jpeg = await generateStory({\n ...request,\n config: { ...config, formats: [pdfFormat], output: { imageFormat: \"jpeg\" } },\n });\n const pdf = carouselPdf(jpeg.files);\n downloads.push({ name: \"story.pdf\", bytes: pdf });\n manifest.computed[\"story.pdf\"] = {\n value: { format: pdfFormat, pages: jpeg.files.length, bytes: pdf.length },\n computedFrom: [\"story\"],\n };\n }\n\n downloads.push(\n { name: \"brand.json\", bytes: encodeJson(brand) },\n { name: \"config.json\", bytes: encodeJson(config) },\n { name: \"manifest.json\", bytes: encodeJson(manifest) },\n );\n return { result, manifest, downloads, archive: zipFiles(downloads), brand, config };\n}\n","// `shipseal story`: an ordered release story as images, a PDF carousel and a ZIP.\n// Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport type { Config } from \"../config/schema.js\";\nimport { ShipsealError } from \"../core/errors.js\";\nimport type { GenerateInput } from \"../core/generate.js\";\nimport { createTakumiRenderer } from \"../render/takumi-node.js\";\nimport { buildStudioPack, selectionSchema } from \"../studio/pack.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport { loadLogos, readShipsealVersion } from \"./shared.js\";\n\nconst STORY_IMAGE_LABELS = [\"before\", \"after\"] as const;\nconst MAX_STORY_IMAGE_BYTES = 5_000_000;\n\ntype StoryImage = NonNullable<GenerateInput[\"images\"]>[number];\n\n/**\n * Screenshots are supplied by the maintainer, never generated or captured here: no headless\n * browser is a hard rule (AGENTS.md rule 2).\n */\nasync function readStoryImage(cwd: string, label: string, path: string): Promise<StoryImage> {\n let data: Uint8Array;\n try {\n data = await readFile(resolve(cwd, path));\n } catch (error) {\n throw new ShipsealError(\n \"story.image-missing\",\n `Could not read the ${label} screenshot: ${path}.`,\n \"Set release.story.before and release.story.after to existing PNG or JPEG files.\",\n { cause: error },\n );\n }\n const png = data[0] === 137 && data[1] === 80 && data[2] === 78 && data[3] === 71;\n const jpeg = data[0] === 255 && data[1] === 216;\n if ((!png && !jpeg) || data.length > MAX_STORY_IMAGE_BYTES) {\n throw new ShipsealError(\n \"story.image-invalid\",\n `The ${label} screenshot is not a supported image or exceeds the size limit.`,\n \"Use a PNG or JPEG smaller than 5 MB.\",\n );\n }\n return { src: `story-${label}`, data };\n}\n\nexport async function loadStoryImages(cwd: string, config: Config): Promise<StoryImage[]> {\n const configured = STORY_IMAGE_LABELS.flatMap((label) => {\n const path = config.release?.story?.[label];\n return path === undefined ? [] : [{ label, path }];\n });\n return Promise.all(configured.map((image) => readStoryImage(cwd, image.label, image.path)));\n}\n\nexport interface StoryFlags {\n cwd: string;\n tag?: string;\n format?: string;\n style?: string;\n theme?: string;\n headline?: string;\n out?: string;\n strict?: boolean;\n package?: string;\n}\n\nexport async function runStory(flags: StoryFlags) {\n const brand = await loadBrand(flags.cwd);\n const config = await loadConfig(flags.cwd);\n const tag = flags.tag ?? (await gitCurrentTag(flags.cwd));\n if (tag === undefined) {\n throw new ShipsealError(\n \"story.no-tag\",\n \"No release tag was found.\",\n \"Pass --tag with an existing release tag.\",\n );\n }\n // safeParse, not parse: a bad --style or --format is user input at the CLI boundary and\n // has to come back as a typed error, not a raw zod issue dump.\n const parsed = selectionSchema.safeParse({\n pack: \"story\",\n style: flags.style ?? brand.style,\n theme: flags.theme ?? brand.theme,\n accent: brand.colors.primary ?? \"#ff4d4d\",\n headline: flags.headline ?? config.release?.headline ?? \"\",\n upgrade: config.release?.story?.upgrade ?? \"\",\n format: flags.format ?? \"portrait\",\n });\n if (!parsed.success) {\n const fields = [...new Set(parsed.error.issues.map((issue) => issue.path.join(\".\")))];\n throw new ShipsealError(\n \"story.bad-options\",\n `These story options are not valid: ${fields.join(\", \")}.`,\n \"Use --format portrait, square, og, github-social, x, linkedin, producthunt or all; --style minimal, editorial or terminal; --theme dark or light.\",\n { cause: parsed.error },\n );\n }\n const selection = parsed.data;\n\n const collectOptions: Parameters<typeof collectFacts>[0] = {\n cwd: flags.cwd,\n event: { kind: \"release\", tag },\n skipNetwork: true,\n };\n if (flags.package !== undefined) {\n collectOptions.packagePath = flags.package;\n }\n if (config.release?.changelogPath !== undefined) {\n collectOptions.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collectOptions.snippet = config.release.snippet;\n }\n const facts = await collectFacts(collectOptions);\n\n const input: Parameters<typeof buildStudioPack>[0] = {\n facts,\n brand,\n config,\n selection,\n renderer: await createTakumiRenderer(),\n version: readShipsealVersion(),\n generatedAt: new Date().toISOString(),\n images: await loadStoryImages(flags.cwd, config),\n brandSource: \".shipseal/brand.json + story flags\",\n };\n const logos = await loadLogos(flags.cwd, brand);\n if (logos !== undefined) {\n input.logos = logos;\n }\n const pack = await buildStudioPack(input);\n\n const dir = resolve(\n flags.cwd,\n flags.out ?? config.outputDir ?? \".shipseal/output\",\n `story-${tag.replaceAll(/[^a-zA-Z0-9_.-]/g, \"-\")}`,\n );\n await mkdir(dir, { recursive: true });\n await Promise.all(pack.downloads.map((file) => writeFile(join(dir, file.name), file.bytes)));\n await writeFile(join(dir, \"story.zip\"), pack.archive);\n return {\n dir,\n manifest: pack.manifest,\n exitCode: flags.strict === true && pack.manifest.warnings.length > 0 ? 2 : 0,\n };\n}\n","// Local preview server: renders release and story packs on demand and saves the\n// choices back into .shipseal. Spec: docs/PROJECT_PLAN.md 25 (2026-09-13 decisions).\n\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, rename, writeFile } from \"node:fs/promises\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { join } from \"node:path\";\nimport { loadBrand } from \"../brand/load.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { cleanLine, firstSentence } from \"../copy/deterministic.js\";\nimport { ShipsealError, formatError } from \"../core/errors.js\";\nimport { createTakumiRenderer, resolvePackageRoot } from \"../render/takumi-node.js\";\nimport type { StudioOutput, StudioState } from \"../studio/client.js\";\nimport { buildStudioPack, selectedBrand, selectedConfig, selectionSchema } from \"../studio/pack.js\";\nimport { collectFacts } from \"../sources/collect.js\";\nimport { gitCurrentTag } from \"../sources/git.js\";\nimport { loadLogos, readShipsealVersion } from \"./shared.js\";\nimport { loadStoryImages } from \"./story.js\";\n\n/** Localhost only, so the page is served inline rather than from a template file. */\nconst PAGE = `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Shipseal preview</title>\n</head><body style=\"margin:0;background:#0c0c0f\"><main id=\"studio\"></main><script type=\"module\">\nimport { mountStudio } from '/studio-client.js';\nconst token = new URL(location.href).searchParams.get('token');\nasync function api(path, value) {\n const response = await fetch(path, {\n method: value === undefined ? 'GET' : 'POST',\n headers: { 'Content-Type': 'application/json', 'X-Shipseal-Token': token },\n ...(value === undefined ? {} : { body: JSON.stringify(value) }),\n });\n const body = await response.json();\n if (!response.ok) throw new Error(body.error);\n return body;\n}\nmountStudio(document.getElementById('studio'), {\n mode: 'local',\n load: () => api('/api/state'),\n render: (value) => api('/api/render', value),\n save: (value) => api('/api/save', value),\n});\n</script></body></html>`;\n\nconst PAGE_HEADERS = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n \"Referrer-Policy\": \"no-referrer\",\n \"Content-Security-Policy\":\n \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' blob:; connect-src 'self'; frame-ancestors 'none'\",\n};\n\nfunction json(response: ServerResponse, status: number, value: unknown): void {\n response.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n });\n response.end(JSON.stringify(value));\n}\n\nasync function readSelection(request: IncomingMessage) {\n let text = \"\";\n for await (const value of request) {\n if (!Buffer.isBuffer(value)) {\n throw new ShipsealError(\n \"preview.body\",\n \"The request body is not valid bytes.\",\n \"Reload the preview.\",\n );\n }\n text += value.toString(\"utf8\");\n if (text.length > 16_384) {\n throw new ShipsealError(\n \"preview.body-size\",\n \"The preview request is too large.\",\n \"Shorten the headline or upgrade instructions.\",\n );\n }\n }\n try {\n const raw: unknown = JSON.parse(text);\n return selectionSchema.parse(raw);\n } catch (error) {\n throw new ShipsealError(\n \"preview.selection\",\n \"The preview options are invalid.\",\n \"Reload the preview and choose supported options.\",\n { cause: error },\n );\n }\n}\n\n/** Write through a temporary file so an interrupted save never truncates the original. */\nasync function writeAtomic(destination: string, value: unknown): Promise<void> {\n const temporary = `${destination}.${randomUUID()}.tmp`;\n await writeFile(temporary, `${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n await rename(temporary, destination);\n}\n\nexport async function startPreview(options: {\n cwd: string;\n tag?: string;\n port?: number;\n package?: string;\n}) {\n const resolvedTag = options.tag ?? (await gitCurrentTag(options.cwd));\n if (resolvedTag === undefined) {\n throw new ShipsealError(\n \"preview.no-tag\",\n \"No release tag was found.\",\n \"Pass --tag with an existing release tag.\",\n );\n }\n // Declared as string so the request handler below reads it without renarrowing.\n const tag: string = resolvedTag;\n // Startup validates the workspace before printing a URL the user is told to open.\n await loadBrand(options.cwd);\n const token = randomUUID();\n let origin = \"\";\n\n async function handle(request: IncomingMessage, response: ServerResponse): Promise<void> {\n if (request.headers.host !== new URL(origin).host) {\n json(response, 403, {\n error: \"Invalid preview host. Open the localhost URL printed by Shipseal.\",\n });\n return;\n }\n const url = new URL(request.url ?? \"/\", origin);\n if (request.method === \"GET\" && url.pathname === \"/\") {\n response.writeHead(200, PAGE_HEADERS);\n response.end(PAGE);\n return;\n }\n if (request.method === \"GET\" && url.pathname === \"/studio-client.js\") {\n const script = await readFile(join(resolvePackageRoot(), \"dist\", \"studio-client.js\"));\n response.writeHead(200, { \"Content-Type\": \"text/javascript\", \"Cache-Control\": \"no-store\" });\n response.end(script);\n return;\n }\n if (\n request.headers[\"x-shipseal-token\"] !== token ||\n (request.method === \"POST\" && request.headers.origin !== origin)\n ) {\n json(response, 403, {\n error:\n \"This preview request is not authorized. Reload the localhost URL printed by Shipseal.\",\n });\n return;\n }\n\n const brand = await loadBrand(options.cwd);\n const config = await loadConfig(options.cwd);\n const collect: Parameters<typeof collectFacts>[0] = {\n cwd: options.cwd,\n event: { kind: \"release\", tag },\n skipNetwork: true,\n };\n if (options.package !== undefined) {\n collect.packagePath = options.package;\n }\n if (config.release?.changelogPath !== undefined) {\n collect.changelogPath = config.release.changelogPath;\n }\n if (config.release?.snippet !== undefined) {\n collect.snippet = config.release.snippet;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/api/state\") {\n const facts = await collectFacts(collect);\n const state: StudioState = {\n name: brand.name,\n style: brand.style,\n theme: brand.theme,\n accent: brand.colors.primary ?? \"#ff4d4d\",\n headline: config.release?.headline ?? \"\",\n upgrade: config.release?.story?.upgrade ?? \"\",\n headlines: [...(facts.release?.breaking ?? []), ...(facts.release?.features ?? [])].map(\n (item) => cleanLine(firstSentence(item.value)),\n ),\n notes: [\n \"Local facts come from your checkout. Change files and refresh this page to reload them. Screenshots use release.story.before and release.story.after in config.json.\",\n ],\n releases: [{ tag, label: tag }],\n tag,\n };\n json(response, 200, state);\n return;\n }\n if (request.method !== \"POST\") {\n json(response, 404, { error: \"Preview route not found.\" });\n return;\n }\n\n const selection = await readSelection(request);\n if (url.pathname === \"/api/save\") {\n const nextConfig = selectedConfig(config, selection);\n // Pack-specific sizes are preview choices, so ordinary release formats are preserved.\n nextConfig.formats = config.formats;\n await Promise.all([\n writeAtomic(join(options.cwd, \".shipseal\", \"brand.json\"), selectedBrand(brand, selection)),\n writeAtomic(join(options.cwd, \".shipseal\", \"config.json\"), nextConfig),\n ]);\n json(response, 200, { saved: true });\n return;\n }\n if (url.pathname !== \"/api/render\") {\n json(response, 404, { error: \"Preview route not found.\" });\n return;\n }\n\n const facts = await collectFacts(collect);\n const packInput: Parameters<typeof buildStudioPack>[0] = {\n facts,\n brand,\n config,\n selection,\n renderer: await createTakumiRenderer(),\n generatedAt: new Date().toISOString(),\n version: readShipsealVersion(),\n images: await loadStoryImages(options.cwd, config),\n };\n const logos = await loadLogos(options.cwd, brand);\n if (logos !== undefined) {\n packInput.logos = logos;\n }\n const pack = await buildStudioPack(packInput);\n const output: StudioOutput = {\n files: pack.result.files.map((file) => ({\n name: file.fileName,\n data: Buffer.from(file.bytes).toString(\"base64\"),\n width: file.width,\n height: file.height,\n })),\n archive: Buffer.from(pack.archive).toString(\"base64\"),\n manifest: pack.manifest,\n };\n const pdf = pack.downloads.find((file) => file.name === \"story.pdf\");\n if (pdf !== undefined) {\n output.pdf = Buffer.from(pdf.bytes).toString(\"base64\");\n }\n json(response, 200, output);\n }\n\n const server = createServer((request, response) => {\n void handle(request, response).catch((error: unknown) => {\n json(response, 400, {\n error:\n error instanceof ShipsealError\n ? formatError(error)\n : `${error instanceof Error ? error.message : \"Preview failed\"}. Check the files and retry.`,\n });\n });\n });\n await new Promise<void>((accept, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 4175, \"127.0.0.1\", () => {\n server.removeListener(\"error\", reject);\n accept();\n });\n });\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n throw new ShipsealError(\n \"preview.listen\",\n \"The preview server could not start.\",\n \"Choose another --port and retry.\",\n );\n }\n origin = `http://127.0.0.1:${String(address.port)}`;\n return { server, url: `${origin}/?token=${token}`, token };\n}\n\nexport async function runPreview(options: Parameters<typeof startPreview>[0]): Promise<void> {\n let preview: Awaited<ReturnType<typeof startPreview>>;\n try {\n preview = await startPreview(options);\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\") {\n throw new ShipsealError(\n \"preview.port\",\n \"The preview port is already in use.\",\n \"Pass --port with another available port.\",\n { cause: error },\n );\n }\n throw error;\n }\n process.stdout.write(`Preview: ${preview.url}\\nPress Ctrl+C to stop.\\n`);\n await new Promise<void>((accept) => {\n const stop = () => {\n preview.server.close();\n preview.server.closeAllConnections();\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n preview.server.once(\"close\", () => {\n process.removeListener(\"SIGINT\", stop);\n process.removeListener(\"SIGTERM\", stop);\n accept();\n });\n });\n}\n","#!/usr/bin/env node\n// CLI entry: parse args, dispatch to commands/*\n// Spec: docs/PROJECT_PLAN.md §18\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { cac } from \"cac\";\nimport { runBench, type BenchFlags } from \"./commands/bench.js\";\nimport { runDoctor } from \"./commands/doctor.js\";\nimport { runInit } from \"./commands/init.js\";\nimport { runMilestone, type MilestoneFlags } from \"./commands/milestone.js\";\nimport { runRelease, type ReleaseFlags } from \"./commands/release.js\";\nimport { runStory } from \"./commands/story.js\";\nimport { runPreview } from \"./commands/preview.js\";\nimport { ShipsealError, formatError } from \"./core/errors.js\";\nimport { resolvePackageRoot } from \"./render/takumi-node.js\";\n\nexport async function runCli(argv = process.argv): Promise<number> {\n process.exitCode = 0;\n const cli = cac(\"shipseal\");\n cli.option(\"--cwd <path>\", \"Working directory\", { default: process.cwd() });\n cli.option(\"--json\", \"Machine-readable JSON output\");\n cli.option(\"--quiet\", \"Suppress non-error output\");\n cli.option(\"--verbose\", \"Verbose output\");\n\n cli\n .command(\"init\", \"Detect brand and write .shipseal/brand.json + config.json\")\n .option(\"--yes\", \"Accept detections without prompting\")\n .option(\"--force\", \"Overwrite existing brand.json and config.json\")\n .action(async (flags: Record<string, unknown>) => {\n const result = await runInit({\n cwd: stringFlag(flags.cwd, process.cwd()),\n yes: flags.yes === true,\n force: flags.force === true,\n });\n if (flags.json === true) {\n process.stdout.write(`${JSON.stringify(result.detection.brand, null, 2)}\\n`);\n return;\n }\n if (flags.quiet !== true) {\n process.stdout.write(`Wrote ${result.brandPath}\\n`);\n process.stdout.write(`Wrote ${result.configPath}\\n`);\n process.stdout.write(`Sample card: ${result.samplePath}\\n`);\n for (const field of result.detection.sources) {\n process.stdout.write(` ${field.field}: ${field.source}\\n`);\n }\n // Notes carry the \"this is a built-in default, not your brand\" disclosures.\n // The interactive prompt already shows them, and --yes skips that prompt, so\n // without this the user never learns which colors were not detected.\n for (const note of result.detection.notes) {\n process.stdout.write(` note: ${note}\\n`);\n }\n }\n });\n\n cli.command(\"story\", \"Generate an ordered release story, PDF carousel and ZIP\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--format <format>\", \"portrait, square, og, github-social, x, linkedin, producthunt, or all\")\n .option(\"--style <style>\", \"minimal, editorial, or terminal\")\n .option(\"--theme <theme>\", \"dark or light\")\n .option(\"--headline <text>\", \"Override the cover headline\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--no-copy\", \"Use source text only (stories always use deterministic copy)\")\n .action(async (flags: Record<string, unknown>) => {\n const options: Parameters<typeof runStory>[0] = { cwd: stringFlag(flags.cwd, process.cwd()), strict: flags.strict === true };\n for (const key of [\"tag\", \"format\", \"style\", \"theme\", \"headline\", \"out\", \"package\"] as const) {\n const value = optionalString(flags[key]); if (value !== undefined) options[key] = value;\n }\n const result = await runStory(options);\n process.exitCode = result.exitCode;\n if (flags.json === true) writeJson(result);\n else if (flags.quiet !== true) writeHumanResult({ ...result, dryRun: false, facts: result.manifest.facts, warnings: result.manifest.warnings });\n });\n\n cli.command(\"preview\", \"Preview release and story packs locally, then save your choices\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--port <port>\", \"Localhost port (default: 4175)\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const options: Parameters<typeof runPreview>[0] = { cwd: stringFlag(flags.cwd, process.cwd()) };\n for (const key of [\"tag\", \"package\"] as const) { const value = optionalString(flags[key]); if (value !== undefined) options[key] = value; }\n if (flags.port !== undefined) {\n const port = Number(flags.port);\n if (!Number.isInteger(port) || port < 0 || port > 65535) throw new ShipsealError(\"preview.port\", \"The preview port is invalid.\", \"Pass an integer from 0 through 65535.\");\n options.port = port;\n }\n await runPreview(options);\n });\n\n cli.command(\"doctor\", \"Check Node, git, brand, fonts, and Takumi\").action(async (flags: Record<string, unknown>) => {\n const result = await runDoctor(stringFlag(flags.cwd, process.cwd()));\n if (flags.json === true) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else if (flags.quiet !== true) {\n for (const check of result.checks) {\n const mark = check.status === \"pass\" ? \"ok\" : check.status === \"fail\" ? \"FAIL\" : \"info\";\n process.stdout.write(`[${mark}] ${check.name}: ${check.message}\\n`);\n if (check.fix !== undefined && check.status === \"fail\") {\n process.stdout.write(` Fix: ${check.fix}\\n`);\n }\n }\n }\n if (!result.ok) {\n process.exitCode = 1;\n }\n });\n\n cli\n .command(\"release\", \"Generate the release pack\")\n .option(\"--tag <tag>\", \"Release tag\")\n .option(\"--from <tag>\", \"Previous tag\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--templates <list>\", \"Comma-separated templates\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .option(\"--headline <text>\", \"Headline for the cards, overriding the changelog\")\n .option(\"--subheadline <text>\", \"Subheadline for the cards\")\n .option(\"--upload\", \"Upload PNG files to the GitHub release\")\n .action(async (flags: Record<string, unknown>) => {\n const releaseFlags: ReleaseFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(releaseFlags, flags);\n const tag = optionalString(flags.tag);\n if (tag !== undefined) {\n releaseFlags.tag = tag;\n }\n const headline = optionalString(flags.headline);\n if (headline !== undefined) {\n releaseFlags.headline = headline;\n }\n const subheadline = optionalString(flags.subheadline);\n if (subheadline !== undefined) {\n releaseFlags.subheadline = subheadline;\n }\n const from = optionalString(flags.from);\n if (from !== undefined) {\n releaseFlags.from = from;\n }\n const templates = optionalString(flags.templates);\n if (templates !== undefined) {\n releaseFlags.templates = templates;\n }\n const result = await runRelease(releaseFlags);\n process.exitCode = result.exitCode;\n writeCommandOutput(flags, result);\n });\n\n cli\n .command(\"milestone\", \"Generate a milestone card for the highest crossed threshold\")\n .option(\"--metric <stars|downloads|contributors>\", \"Metric to check\")\n .option(\"--threshold <n>\", \"Force a specific threshold\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const milestoneFlags: MilestoneFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(milestoneFlags, flags);\n const metric = optionalString(flags.metric);\n if (metric !== undefined) {\n milestoneFlags.metric = metric;\n }\n const threshold = optionalString(flags.threshold);\n if (threshold !== undefined) {\n milestoneFlags.threshold = threshold;\n }\n const result = await runMilestone(milestoneFlags);\n process.exitCode = result.exitCode;\n if (flags.json === true) {\n writeJson(resultToJson(result));\n return;\n }\n if (flags.quiet === true) {\n return;\n }\n if (result.skipped) {\n process.stdout.write(`${result.message ?? \"No milestone threshold crossed.\"}\\n`);\n return;\n }\n writeHumanResult(result);\n });\n\n cli\n .command(\"bench\", \"Generate benchmark cards from bench JSON\")\n .option(\"--file <path>\", \"Path to bench JSON\")\n .option(\"--formats <list>\", \"Comma-separated formats\")\n .option(\"--themes <dark|light|both>\", \"Themes to render\")\n .option(\"--copy\", \"Allow optional LLM copy (default: on when config.copy.llm is true)\")\n .option(\"--out <dir>\", \"Output directory\")\n .option(\"--strict\", \"Fit warnings exit with code 2\")\n .option(\"--dry-run\", \"Collect facts and print them; render nothing\")\n .option(\"--package <path>\", \"package.json path for monorepos\")\n .action(async (flags: Record<string, unknown>) => {\n const benchFlags: BenchFlags = {\n cwd: stringFlag(flags.cwd, process.cwd()),\n strict: flags.strict === true,\n dryRun: flags.dryRun === true,\n };\n applySharedFlags(benchFlags, flags);\n const file = optionalString(flags.file);\n if (file !== undefined) {\n benchFlags.file = file;\n }\n const result = await runBench(benchFlags);\n process.exitCode = result.exitCode;\n writeCommandOutput(flags, result);\n });\n\n cli.help();\n cli.version(readVersion());\n\n try {\n cli.parse(argv, { run: false });\n await cli.runMatchedCommand();\n return typeof process.exitCode === \"number\" ? process.exitCode : 0;\n } catch (error) {\n if (error instanceof ShipsealError) {\n process.stderr.write(`${formatError(error)}\\n`);\n return 1;\n }\n if (error instanceof Error) {\n process.stderr.write(`${error.message}\\n`);\n return 1;\n }\n throw error;\n }\n}\n\nfunction stringFlag(value: unknown, fallback: string): string {\n return typeof value === \"string\" && value.length > 0 ? value : fallback;\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction applySharedFlags(target: { formats?: string; themes?: string; copy?: boolean; out?: string; package?: string; upload?: boolean }, flags: Record<string, unknown>): void {\n const formats = optionalString(flags.formats);\n if (formats !== undefined) {\n target.formats = formats;\n }\n const themes = optionalString(flags.themes);\n if (themes !== undefined) {\n target.themes = themes;\n }\n if (flags.copy === false) {\n target.copy = false;\n }\n const out = optionalString(flags.out);\n if (out !== undefined) {\n target.out = out;\n }\n const pkg = optionalString(flags.package);\n if (pkg !== undefined) {\n target.package = pkg;\n }\n if (flags.upload === true) {\n target.upload = true;\n }\n}\n\nfunction writeCommandOutput(\n flags: Record<string, unknown>,\n result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n manifest?: unknown;\n copyWarning?: string;\n warnings: Array<{ template: string; format: string; slot: string; action: string }>;\n skipped?: boolean;\n message?: string;\n },\n): void {\n if (flags.json === true) {\n writeJson(resultToJson(result));\n return;\n }\n if (flags.quiet === true) {\n return;\n }\n writeHumanResult(result);\n}\n\nfunction resultToJson(result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n manifest?: unknown;\n skipped?: boolean;\n message?: string;\n}): Record<string, unknown> {\n const payload: Record<string, unknown> = {};\n if (result.skipped === true) {\n payload.skipped = true;\n }\n if (result.message !== undefined) {\n payload.message = result.message;\n }\n if (result.dir !== undefined) {\n payload.dir = result.dir;\n }\n if (result.manifest !== undefined) {\n payload.manifest = result.manifest;\n } else {\n payload.facts = result.facts;\n }\n return payload;\n}\n\nfunction writeHumanResult(result: {\n dryRun: boolean;\n facts: unknown;\n dir?: string;\n copyWarning?: string;\n warnings: Array<{ template: string; format: string; slot: string; action: string }>;\n skipped?: boolean;\n message?: string;\n}): void {\n if (result.skipped === true) {\n process.stdout.write(`${result.message ?? \"Nothing to generate.\"}\\n`);\n return;\n }\n if (result.dryRun) {\n process.stdout.write(`${JSON.stringify(result.facts, null, 2)}\\n`);\n return;\n }\n if (result.dir !== undefined) {\n process.stdout.write(`Wrote ${result.dir}\\n`);\n }\n if (result.copyWarning !== undefined) {\n process.stdout.write(`Copy: ${result.copyWarning}\\n`);\n }\n for (const warning of result.warnings) {\n process.stdout.write(`Warning: ${warning.template} ${warning.format} ${warning.slot} ${warning.action}\\n`);\n }\n}\n\nfunction writeJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction readVersion(): string {\n const raw: unknown = JSON.parse(readFileSync(join(resolvePackageRoot(), \"package.json\"), \"utf8\"));\n if (typeof raw === \"object\" && raw !== null && \"version\" in raw && typeof raw.version === \"string\") {\n return raw.version;\n }\n return \"0.0.0\";\n}\n\nif (shouldRun(process.argv[1])) {\n void runCli().then((code) => {\n process.exit(code);\n });\n}\n\nfunction shouldRun(invoked: string | undefined): boolean {\n if (invoked === undefined) {\n return false;\n }\n const normalized = invoked.replaceAll(\"\\\\\", \"/\");\n return (\n normalized.endsWith(\"/cli.js\") ||\n normalized.endsWith(\"/cli.ts\") ||\n normalized.endsWith(\"/shipseal\")\n );\n}\n"],"mappings":"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"}
|