stunning-md 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -14
- package/dist/chunk-MKH2VK55.mjs +377 -0
- package/dist/chunk-MKH2VK55.mjs.map +1 -0
- package/dist/core.d.mts +178 -6
- package/dist/core.mjs +174 -87
- package/dist/core.mjs.map +1 -1
- package/dist/index.d.mts +206 -7
- package/dist/index.mjs +3449 -2290
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +21 -1
- package/dist/server.mjs +48 -0
- package/dist/server.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +7 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stunning-md/components/stunning-markdown.tsx","../src/lib/utils.ts","../src/stunning-md/analyze/images.ts","../src/stunning-md/analyze/text.ts","../src/stunning-md/analyze/tables.ts","../src/stunning-md/analyze/plan.ts","../src/stunning-md/theme/themes.ts","../src/stunning-md/classifier.ts","../src/stunning-md/parse.ts","../src/stunning-md/theme/chart.ts","../src/stunning-md/theme/color.ts","../src/stunning-md/components/context.tsx","../src/stunning-md/components/flow.tsx","../src/stunning-md/components/code-block.tsx","../src/components/ui/button.tsx","../src/stunning-md/components/media.tsx","../src/components/ui/carousel.tsx","../src/components/ui/dialog.tsx","../src/stunning-md/components/hero.tsx","../src/stunning-md/components/nav.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ui/sheet.tsx","../src/stunning-md/components/plain.tsx","../src/stunning-md/components/section.tsx","../src/stunning-md/components/blocks.tsx","../src/stunning-md/components/data-block.tsx","../src/components/ui/popover.tsx","../src/components/ui/table.tsx"],"sourcesContent":["\"use client\"\n\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { probeImages } from \"../analyze/images\"\nimport { collectImageUrls, planDocument, type ImageMetaMap } from \"../analyze/plan\"\nimport { proseOf, toText } from \"../analyze/text\"\nimport { judgeDocument, type Classify } from \"../classifier\"\nimport { parseMarkdown } from \"../parse\"\nimport { chartThemeFor } from \"../theme/chart\"\nimport { fontPairings, googleFontsUrl, matchTheme, themeChoice, themes, themeVars } from \"../theme/themes\"\nimport type { Appearance, DocumentPlan, Judgements, PaletteId, SectionLayout, ThemeChoice, VizKind } from \"../types\"\nimport { StunningProvider, type StunningContext } from \"./context\"\nimport { HeroView } from \"./hero\"\nimport { Nav, TocSidebar, useReadingPosition, type View } from \"./nav\"\nimport { PlainDocument, SourceView } from \"./plain\"\nimport { SectionView } from \"./section\"\n\nexport type StunningMarkdownProps = {\n markdown: string\n /**\n * Answers the judgement calls structure cannot settle (theme, typography,\n * ambiguous tables, hero image). Without it everything is decided by rules.\n */\n classifier?: Classify\n /** Fixes parts of the theme — palette, typefaces or corner style — overriding everything else. */\n theme?: Partial<ThemeChoice>\n /** `auto` follows the reader's system setting. */\n appearance?: Appearance | \"auto\"\n /** Maps URLs in the markdown (e.g. relative image paths) to loadable ones. */\n resolveUrl?: (url: string) => string\n /** Let the reader edit the text in the markdown view. Edits stay in the page unless you handle `onMarkdownChange`. */\n editable?: boolean\n /** Called with the new text when the reader's edits are applied. */\n onMarkdownChange?: (markdown: string) => void\n /** Show the theme, layout and chart-form pickers. Default `true`. */\n controls?: boolean\n /** Load the theme's typefaces from Google Fonts. Default `true`. */\n loadFonts?: boolean\n /** Longest wait for an image to report its size, in ms. Default 2500. */\n settleMs?: number\n /**\n * Longest the loader stays up waiting for the classifier and fonts, in ms.\n * Normally it lifts much sooner — as soon as the theme is chosen and the first\n * sections have stopped moving. Default 8000.\n */\n maxWaitMs?: number\n className?: string\n /** Called whenever the plan or theme changes — useful for debugging and tooling. */\n onPlan?: (plan: DocumentPlan, theme: ThemeChoice) => void\n}\n\nconst identity = (url: string) => url\n\nfunction useSystemAppearance(): Appearance {\n return useSyncExternalStore(\n (notify) => {\n const query = window.matchMedia(\"(prefers-color-scheme: dark)\")\n query.addEventListener(\"change\", notify)\n return () => query.removeEventListener(\"change\", notify)\n },\n () => (window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"),\n () => \"light\",\n )\n}\n\n/**\n * Loads the theme's typefaces and reports when text set in them has stopped\n * reflowing. Resolves on its own after `capMs`, so a slow font host never holds the page.\n */\nfunction useFonts(href: string, enabled: boolean, capMs = 1800): boolean {\n const [loaded, setLoaded] = useState<string | null>(null)\n useEffect(() => {\n if (!enabled) return\n let live = true\n const done = () => live && setLoaded(href)\n // Fonts are only requested once styled text has been laid out, so give layout two frames first.\n const settle = () => requestAnimationFrame(() => requestAnimationFrame(() => document.fonts.ready.then(done, done)))\n const cap = setTimeout(done, capMs)\n\n let link = document.head.querySelector<HTMLLinkElement>(`link[data-smd-fonts=\"${href}\"]`)\n if (link?.dataset.smdLoaded) settle()\n else {\n if (!link) {\n link = document.createElement(\"link\")\n link.rel = \"stylesheet\"\n link.href = href\n link.dataset.smdFonts = href\n document.head.appendChild(link)\n }\n const target = link\n const onLoad = () => {\n target.dataset.smdLoaded = \"true\"\n settle()\n }\n target.addEventListener(\"load\", onLoad, { once: true })\n target.addEventListener(\"error\", done, { once: true })\n }\n return () => {\n live = false\n clearTimeout(cap)\n }\n }, [href, enabled, capMs])\n return !enabled || loaded === href\n}\n\nconst NONE: string[] = []\n\n/** The component must be at least this wide, in px, before the contents sit beside the document. */\nconst SIDEBAR_MIN_WIDTH = 1400\n\n/** Whether the element is wide enough — measured on the component, not the window, so embedding works. */\nfunction useWide(target: React.RefObject<HTMLElement | null>, minWidth: number): boolean {\n const [wide, setWide] = useState(false)\n useEffect(() => {\n const el = target.current\n if (!el) return\n const observer = new ResizeObserver(([entry]) => setWide(entry.contentRect.width >= minWidth))\n observer.observe(el)\n return () => observer.disconnect()\n }, [target, minWidth])\n return wide\n}\n\n/** How far down the page counts as \"the first sections\", in viewport heights. */\nconst FIRST_SCREENS = 2\n\nfunction Document({\n markdown: initialMarkdown,\n editable = false,\n onMarkdownChange,\n classifier,\n theme: fixedTheme,\n appearance: appearanceProp = \"auto\",\n resolveUrl = identity,\n controls = true,\n loadFonts = true,\n settleMs = 2500,\n maxWaitMs = 8000,\n className,\n onPlan,\n}: StunningMarkdownProps) {\n const root = useRef<HTMLDivElement>(null)\n // The text being rendered, and — while it is being edited — the text in the editor.\n const [markdown, setMarkdown] = useState(initialMarkdown)\n const [draft, setDraft] = useState(initialMarkdown)\n const parsed = useMemo(() => parseMarkdown(markdown), [markdown])\n const bodyText = useMemo(() => toText(parsed.root), [parsed])\n const prose = useMemo(() => proseOf(parsed.root), [parsed])\n // What the document's own vocabulary suggests, before any classifier is asked.\n const keywordTheme = useMemo(() => {\n const stats = { codeBlocks: (markdown.match(/^```/gm) ?? []).length / 2, tables: (markdown.match(/^\\|?\\s*:?-{3,}/gm) ?? []).length }\n return matchTheme(bodyText, stats)\n }, [markdown, bodyText])\n\n const [images, setImages] = useState<ImageMetaMap | null>(null)\n const [judged, setJudged] = useState<Judgements | null>(null)\n // Classifier questions still unanswered; `null` until the first have been asked.\n const [pending, setPending] = useState<string[] | null>(null)\n const [revealed, setRevealed] = useState(false)\n const [layouts, setLayouts] = useState<Record<string, SectionLayout>>({})\n const [vizPicks, setVizPicks] = useState<Record<string, VizKind>>({})\n const [palettePick, setPalettePick] = useState<PaletteId | null>(null)\n const [appearancePick, setAppearancePick] = useState<Appearance | null>(null)\n const [view, setView] = useState<View>(\"designed\")\n // Edits are applied on leaving the editor, not per keystroke: re-planning and\n // re-asking the classifier for every character would be wasteful and jumpy.\n const changeView = useCallback(\n (next: View) => {\n if (draft !== markdown) {\n setMarkdown(draft)\n onMarkdownChange?.(draft)\n }\n setView(next)\n },\n [draft, markdown, onMarkdownChange],\n )\n\n // 1. Measure images — their size decides hero, full-bleed and split layouts.\n useEffect(() => {\n let live = true\n const urls = collectImageUrls(parsed.root)\n const cover = [\"image\", \"cover\", \"banner\"].map((key) => parsed.frontmatter[key]).filter((v): v is string => typeof v === \"string\")\n probeImages([...urls, ...cover], resolveUrl, settleMs).then((result) => live && setImages(result))\n return () => {\n live = false\n }\n }, [parsed, resolveUrl, settleMs])\n\n // 2. Ask the classifier, once sizes are known, about what rules cannot decide.\n // Every question is asked straight away, top of the page first, and each\n // answer is applied as it lands — nothing waits for the reader to scroll.\n useEffect(() => {\n if (!images || !classifier) return\n const abort = new AbortController()\n const structural = planDocument({ root: parsed.root, frontmatter: parsed.frontmatter, images })\n judgeDocument(structural, prose, classifier, {\n signal: abort.signal,\n themeHint: keywordTheme ?? undefined,\n onProgress: (progress) => {\n setJudged(progress.judgements)\n setPending(progress.pending)\n },\n }).catch((error) => {\n if (abort.signal.aborted) return\n console.warn(\"[stunning-md] classifier unavailable; using rules only\", error)\n setPending([])\n })\n return () => abort.abort()\n }, [images, classifier, parsed, prose, keywordTheme])\n\n const plan = useMemo(\n () =>\n planDocument({\n root: parsed.root,\n frontmatter: parsed.frontmatter,\n images: images ?? {},\n judgements: { ...judged, viz: { ...judged?.viz, ...vizPicks }, layouts },\n }),\n [parsed, images, judged, vizPicks, layouts],\n )\n\n const theme = useMemo<ThemeChoice>(() => {\n const fromFrontmatter = parsed.frontmatter.theme\n const picked =\n palettePick ?? (typeof fromFrontmatter === \"string\" && fromFrontmatter in themes ? (fromFrontmatter as PaletteId) : null)\n // A theme is a whole look — colours, typefaces and corner style travel together —\n // whether it was guessed from keywords, chosen by the classifier or picked by hand.\n const merged = picked ? themeChoice(picked) : { ...themeChoice(keywordTheme ?? \"paper\"), ...judged?.theme }\n return { ...merged, ...fixedTheme }\n }, [keywordTheme, parsed, judged, palettePick, fixedTheme])\n\n const system = useSystemAppearance()\n const appearance: Appearance = appearancePick ?? (appearanceProp === \"auto\" ? system : appearanceProp)\n\n const measured = images !== null\n const fontsReady = useFonts(googleFontsUrl(fontPairings[theme.fonts]), loadFonts)\n const outstanding = classifier ? pending : NONE\n\n // 3. Lift the loader once the top of the page has stopped moving: the theme and\n // its fonts are in, and no unanswered question concerns a block near the top.\n // The document is already laid out underneath, so this is measured, not guessed.\n useEffect(() => {\n if (revealed || !measured) return\n const frame = requestAnimationFrame(() => {\n const el = root.current\n if (!el || !outstanding || !fontsReady) return\n if (outstanding.includes(\"theme\") || outstanding.includes(\"hero\")) return\n const top = el.getBoundingClientRect().top\n const limit = window.innerHeight * FIRST_SCREENS\n const shifting = outstanding.some((id) => {\n const block = el.querySelector(`[data-block-id=\"${CSS.escape(id)}\"]`)\n return !!block && block.getBoundingClientRect().top - top < limit\n })\n if (!shifting) setRevealed(true)\n })\n return () => cancelAnimationFrame(frame)\n }, [revealed, measured, outstanding, fontsReady, plan, theme])\n\n // A slow classifier or font host must not hold the page back indefinitely.\n useEffect(() => {\n if (!measured) return\n const timer = setTimeout(() => setRevealed(true), maxWaitMs)\n return () => clearTimeout(timer)\n }, [measured, maxWaitMs])\n\n useEffect(() => {\n if (revealed) onPlan?.(plan, theme)\n }, [plan, theme, revealed, onPlan])\n\n\n const style = useMemo(() => themeVars(theme, appearance), [theme, appearance])\n const chartTheme = useMemo(() => chartThemeFor(theme), [theme])\n const setLayout = useCallback((id: string, layout: SectionLayout) => setLayouts((prev) => ({ ...prev, [id]: layout })), [])\n const setViz = useCallback((id: string, kind: VizKind) => setVizPicks((prev) => ({ ...prev, [id]: kind })), [])\n\n // Contents: beside the document when there is room for both, in a sheet otherwise.\n const tocIds = useMemo(() => plan.toc.map((entry) => entry.id), [plan])\n const position = useReadingPosition(tocIds, root)\n const wide = useWide(root, SIDEBAR_MIN_WIDTH)\n const [sidebarWanted, setSidebarWanted] = useState(true)\n const sidebarId = useId()\n const sidebar = useMemo(\n () => ({\n available: wide && plan.showToc && view !== \"source\",\n open: sidebarWanted,\n toggle: () => setSidebarWanted((open) => !open),\n id: sidebarId,\n }),\n [wide, plan.showToc, view, sidebarWanted, sidebarId],\n )\n const showSidebar = sidebar.available && sidebar.open\n\n const context = useMemo<StunningContext>(\n () => ({\n resolveUrl,\n appearance,\n theme,\n chartTheme,\n portal: { className: cn(\"smd-portal\", appearance === \"dark\" && \"dark\"), style },\n controls,\n setLayout,\n setViz,\n }),\n [resolveUrl, appearance, theme, chartTheme, style, controls, setLayout, setViz],\n )\n\n return (\n <StunningProvider value={context}>\n <div\n ref={root}\n className={cn(\"smd\", appearance === \"dark\" && \"dark\", className)}\n style={style}\n data-theme={theme.palette}\n data-ready={revealed}\n aria-busy={!revealed}\n >\n {!revealed && (\n <div className=\"smd-loader\" role=\"status\" aria-live=\"polite\">\n <div>\n <span className=\"smd-loader-mark\" aria-hidden />\n <p>Stunnifying ...</p>\n </div>\n </div>\n )}\n {/* Laid out beneath the loader so its final shape can be measured before it is shown. */}\n {measured && (\n <div className=\"smd-document\" inert={!revealed}>\n <a href={`#${plan.sections[0]?.id ?? \"top\"}`} className=\"smd-skip\">\n Skip to content\n </a>\n <Nav\n plan={plan}\n root={root}\n position={position}\n sidebar={sidebar}\n view={view}\n onView={changeView}\n onPalette={setPalettePick}\n onAppearance={setAppearancePick}\n />\n <div className=\"smd-body\" data-sidebar={showSidebar || undefined}>\n <div className=\"smd-content\">\n {view === \"source\" ? (\n <SourceView value={draft} onChange={editable ? setDraft : undefined} />\n ) : view === \"plain\" ? (\n <PlainDocument root={parsed.root} toc={plan.toc} />\n ) : (\n <>\n <HeroView plan={plan} />\n <main>\n {plan.sections.map((section) => (\n <SectionView key={section.id} section={section} />\n ))}\n </main>\n </>\n )}\n </div>\n {showSidebar && <TocSidebar plan={plan} active={position.active} id={sidebarId} />}\n </div>\n </div>\n )}\n </div>\n </StunningProvider>\n )\n}\n\n/**\n * Renders a markdown string as a designed, responsive page: a hero, sections\n * laid out by the shape of their content, charts for tabular data, a contents\n * menu, and a theme chosen to suit the text.\n */\nexport function StunningMarkdown(props: StunningMarkdownProps) {\n const { markdown, onMarkdownChange } = props\n // A different document starts from a clean slate — no stale sizes, judgements\n // or picks. The reader's own edit coming back through the `markdown` prop is\n // the same document, and must not reset anything.\n const [identity, setIdentity] = useState<{ markdown: string; key: number; echo: string | null }>({ markdown, key: 0, echo: null })\n let current = identity\n if (markdown !== identity.markdown) {\n current = { markdown, key: markdown === identity.echo ? identity.key : identity.key + 1, echo: identity.echo }\n setIdentity(current)\n }\n const handleChange = useCallback(\n (text: string) => {\n setIdentity((previous) => ({ ...previous, echo: text }))\n onMarkdownChange?.(text)\n },\n [onMarkdownChange],\n )\n return <Document key={current.key} {...props} onMarkdownChange={handleChange} />\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import type { ImageMeta } from \"../types\"\nimport type { ImageMetaMap } from \"./plan\"\n\nconst cache = new Map<string, Promise<ImageMeta | null>>()\n\nfunction probe(url: string, timeoutMs: number): Promise<ImageMeta | null> {\n const hit = cache.get(url)\n if (hit) return hit\n const pending = new Promise<ImageMeta | null>((resolve) => {\n const image = new Image()\n const timer = setTimeout(() => resolve(null), timeoutMs)\n image.onload = () => {\n clearTimeout(timer)\n // SVGs without intrinsic size report 0; treat them as unmeasured.\n resolve(image.naturalWidth > 0 ? { width: image.naturalWidth, height: image.naturalHeight } : null)\n }\n image.onerror = () => {\n clearTimeout(timer)\n resolve(null)\n }\n image.src = url\n })\n cache.set(url, pending)\n return pending\n}\n\n/**\n * Loads each image far enough to learn its natural size. Images that fail or\n * take longer than the timeout come back as `null` and are laid out conservatively.\n */\nexport async function probeImages(urls: string[], resolveUrl: (url: string) => string, timeoutMs = 2500): Promise<ImageMetaMap> {\n const entries = await Promise.all(urls.map(async (url) => [url, await probe(resolveUrl(url), timeoutMs)] as const))\n return Object.fromEntries(entries)\n}\n","import type { Image, Nodes, PhrasingContent } from \"mdast\"\n\n/** Plain text of any markdown node. Image alt text is not counted as prose. */\nexport function toText(node: Nodes | Nodes[] | undefined): string {\n if (!node) return \"\"\n if (Array.isArray(node)) return node.map(toText).join(\"\")\n if (node.type === \"text\" || node.type === \"inlineCode\" || node.type === \"code\") return node.value\n if (node.type === \"break\") return \" \"\n if (node.type === \"image\") return \"\"\n if (\"children\" in node) {\n const separator = node.type === \"paragraph\" || node.type === \"heading\" || node.type === \"listItem\" ? \" \" : \"\"\n return (node.children as Nodes[]).map(toText).join(separator)\n }\n return \"\"\n}\n\n/** Running prose only — no headings, code, tables or maths. This is what a reader would call \"the text\". */\nexport function proseOf(node: Nodes): string {\n if (node.type === \"heading\" || node.type === \"code\" || node.type === \"table\" || node.type === \"math\" || node.type === \"yaml\") return \"\"\n if (node.type === \"paragraph\") return toText(node)\n if (\"children\" in node) return (node.children as Nodes[]).map(proseOf).filter(Boolean).join(\" \")\n return \"\"\n}\n\nexport function countWords(text: string): number {\n const trimmed = text.trim()\n return trimmed ? trimmed.split(/\\s+/).length : 0\n}\n\nexport function wordsIn(node: Nodes | Nodes[] | undefined): number {\n if (!node) return 0\n if (Array.isArray(node)) return node.reduce((sum, child) => sum + wordsIn(child), 0)\n if (node.type === \"code\") return 0\n if (\"children\" in node && node.type !== \"paragraph\" && node.type !== \"heading\") {\n return (node.children as Nodes[]).reduce((sum, child) => sum + wordsIn(child), 0)\n }\n return countWords(toText(node))\n}\n\nexport function slugify(text: string, taken: Set<string>): string {\n const base =\n text\n .toLowerCase()\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60) || \"section\"\n let slug = base\n for (let n = 2; taken.has(slug); n++) slug = `${base}-${n}`\n taken.add(slug)\n return slug\n}\n\n/** The images a paragraph consists of, if it holds nothing but images (optionally linked). */\nexport function imagesOnly(children: PhrasingContent[]): { image: Image; href?: string }[] | null {\n const found: { image: Image; href?: string }[] = []\n for (const child of children) {\n if (child.type === \"image\") found.push({ image: child })\n else if (child.type === \"link\" && child.children.length === 1 && child.children[0].type === \"image\") {\n found.push({ image: child.children[0], href: child.url })\n } else if (child.type === \"break\" || (child.type === \"text\" && !child.value.trim())) continue\n else return null\n }\n return found.length ? found : null\n}\n","import type { PhrasingContent, Table } from \"mdast\"\nimport type { ChartSpec, ColumnType, TableColumn, TableModel, TableRow, VizKind, VizPlan } from \"../types\"\nimport { toText } from \"./text\"\n\ntype Unit = { prefix: string; suffix: string }\ntype ParsedNumber = { value: number } & Unit\n\nconst MISSING = /^(|-|–|—|n\\/?a|na|null|none|tbd|\\?)$/i\nconst CURRENCY = \"[$€£¥₹₩₽]|[A-Z]{1,3}\\\\$|(?:USD|EUR|GBP|SGD|JPY|CHF|AUD|CAD|INR|CNY)\\\\b\"\nconst NUMBER = new RegExp(\n `^([(]?)\\\\s*([-−–+]?)\\\\s*(${CURRENCY})?\\\\s*([-−–+]?)\\\\s*(\\\\d[\\\\d,' ]*(?:\\\\.\\\\d+)?|\\\\.\\\\d+)\\\\s*` +\n `(k|K|M|B|T|bn|mn|m|thousand|million|billion|trillion)?\\\\s*(%|‰|[a-zA-Z°µ²³/]{1,8})?\\\\s*([)]?)$`,\n)\nconst MAGNITUDE: Record<string, number> = {\n k: 1e3, K: 1e3, thousand: 1e3,\n M: 1e6, m: 1e6, mn: 1e6, million: 1e6,\n B: 1e9, bn: 1e9, billion: 1e9,\n T: 1e12, trillion: 1e12,\n}\n\nexport function parseNumber(raw: string): ParsedNumber | null {\n const text = raw.trim()\n const match = NUMBER.exec(text)\n if (!match) return null\n const [, open, signA, currency = \"\", signB, digits, magnitude, suffixRaw = \"\", close] = match\n let suffix = suffixRaw\n let scale = 1\n if (magnitude) {\n // A bare lowercase \"m\" is metres unless money is involved (\"$5m\").\n if (magnitude === \"m\" && !currency) suffix = `m${suffix}`\n else scale = MAGNITUDE[magnitude]\n }\n const value = Number(digits.replace(/[,' ]/g, \"\")) * scale\n if (!Number.isFinite(value)) return null\n const negative = (open && close) || /[-−–]/.test(signA + signB)\n return { value: negative ? -value : value, prefix: currency.trim(), suffix }\n}\n\nconst MONTHS = [\"jan\", \"feb\", \"mar\", \"apr\", \"may\", \"jun\", \"jul\", \"aug\", \"sep\", \"oct\", \"nov\", \"dec\"]\nconst monthIndex = (name: string) => MONTHS.indexOf(name.slice(0, 3).toLowerCase())\nconst MONTH_NAME = \"(jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|june?|july?|aug(?:ust)?|sep(?:t(?:ember)?)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)\\\\.?\"\nconst fullYear = (y: string) => (y.length === 2 ? 2000 + Number(y) : Number(y))\nconst validYear = (y: number) => y >= 1000 && y <= 2200\n\n/** Parses the date shapes that show up in tables. Returns UTC epoch milliseconds. */\nexport function parseDate(raw: string): number | null {\n const text = raw.trim().replace(/\\s+/g, \" \")\n let m: RegExpExecArray | null\n if ((m = /^(\\d{4})$/.exec(text))) return validYear(+m[1]) ? Date.UTC(+m[1], 0, 1) : null\n if ((m = /^(\\d{4})[-/.](\\d{1,2})(?:[-/.](\\d{1,2}))?(?:[T ][\\d:.]+Z?)?$/.exec(text))) {\n return +m[2] >= 1 && +m[2] <= 12 ? Date.UTC(+m[1], +m[2] - 1, +(m[3] ?? 1)) : null\n }\n if ((m = /^(?:FY|CY) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[1]), 0, 1)\n if ((m = /^Q([1-4]) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[2]), (+m[1] - 1) * 3, 1)\n if ((m = /^'?(\\d{2}|\\d{4}) ?Q([1-4])$/i.exec(text))) return Date.UTC(fullYear(m[1]), (+m[2] - 1) * 3, 1)\n if ((m = /^H([12]) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[2]), (+m[1] - 1) * 6, 1)\n if ((m = new RegExp(`^${MONTH_NAME}$`, \"i\").exec(text))) return Date.UTC(2000, monthIndex(m[1]), 1)\n if ((m = new RegExp(`^${MONTH_NAME} '?(\\\\d{2}|\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(fullYear(m[2]), monthIndex(m[1]), 1)\n }\n if ((m = new RegExp(`^${MONTH_NAME} (\\\\d{1,2})(?:st|nd|rd|th)?,? (\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(+m[3], monthIndex(m[1]), +m[2])\n }\n if ((m = new RegExp(`^(\\\\d{1,2})(?:st|nd|rd|th)? ${MONTH_NAME},? (\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(+m[3], monthIndex(m[2]), +m[1])\n }\n if ((m = /^(\\d{1,2})[/.](\\d{1,2})[/.](\\d{2}|\\d{4})$/.exec(text))) {\n const [a, b] = [+m[1], +m[2]]\n const [month, day] = a > 12 ? [b, a] : [a, b]\n return month >= 1 && month <= 12 && day <= 31 ? Date.UTC(fullYear(m[3]), month - 1, day) : null\n }\n return null\n}\n\nconst ID_HEADER = /^(#|no\\.?|nr\\.?|id|rank|pos(ition)?|s\\/n|index|ref)$/i\nconst TIME_HEADER = /\\b(year|date|when|period|month|quarter|fy|time|day|week)\\b/i\nconst SHARE_HEADER = /\\b(share|allocation|mix|breakdown|distribution|portion|weight|split|composition)\\b/i\nconst SUMMARY_LABEL = /^(grand )?(total|sum|overall|subtotal|average|avg|mean|median|all)\\b/i\n\n/** Reads \"Revenue ($M)\" → { prefix: \"$\", suffix: \"M\" }. */\nfunction unitFromHeader(label: string): Unit | undefined {\n const match = /[([]\\s*([^)\\]]{1,10})\\s*[)\\]]\\s*$/.exec(label)\n if (!match) return label.trim().endsWith(\"%\") ? { prefix: \"\", suffix: \"%\" } : undefined\n const hint = match[1].trim()\n const currency = new RegExp(`^(${CURRENCY})`).exec(hint)\n if (currency) return { prefix: currency[1], suffix: hint.slice(currency[1].length).trim() }\n if (/^in /i.test(hint)) return { prefix: \"\", suffix: ` ${hint.slice(3)}` }\n return { prefix: \"\", suffix: hint === \"%\" ? \"%\" : ` ${hint}` }\n}\n\nconst mostCommon = (values: string[]) => {\n const counts = new Map<string, number>()\n for (const v of values) counts.set(v, (counts.get(v) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? \"\"\n}\n\nexport function buildTableModel(node: Table): TableModel {\n const [head, ...body] = node.children\n const headers = (head?.children ?? []).map((cell) => toText(cell).trim())\n const width = Math.max(headers.length, ...body.map((row) => row.children.length))\n const cellText = body.map((row) => Array.from({ length: width }, (_, c) => toText(row.children[c]).trim()))\n\n const columns: TableColumn[] = []\n const parsed: (number | string | null)[][] = body.map(() => [])\n\n for (let c = 0; c < width; c++) {\n const label = headers[c] || \"\"\n const cells = cellText.map((row) => row[c])\n const present = cells.filter((text) => !MISSING.test(text))\n const numbers = cells.map((text) => (MISSING.test(text) ? null : parseNumber(text)))\n const dates = cells.map((text) => (MISSING.test(text) ? null : parseDate(text)))\n const numericCount = numbers.filter(Boolean).length\n const dateCount = dates.filter((d) => d != null).length\n const enough = (count: number) => present.length > 0 && count >= Math.max(1, Math.ceil(present.length * 0.9))\n\n const allYears = enough(dateCount) && present.every((text) => /^\\d{4}$/.test(text))\n let type: ColumnType = \"text\"\n // Bare four-digit numbers are years only where a time axis is expected.\n if (enough(dateCount) && (!allYears || c === 0 || TIME_HEADER.test(label))) type = \"date\"\n else if (enough(numericCount) && !ID_HEADER.test(label)) type = \"number\"\n\n let unit: Unit | undefined\n if (type === \"number\") {\n const found = numbers.filter((n): n is ParsedNumber => n != null)\n const prefix = mostCommon(found.map((n) => n.prefix))\n const suffix = mostCommon(found.map((n) => n.suffix))\n unit = prefix || suffix ? { prefix, suffix } : unitFromHeader(label)\n }\n\n const align = node.align?.[c] ?? (type === \"number\" ? \"right\" : \"left\")\n columns.push({ key: `c${c}`, label: label || `Column ${c + 1}`, type, unit, align })\n cellText.forEach((row, r) => {\n parsed[r][c] = type === \"number\" ? (numbers[r]?.value ?? null) : type === \"date\" ? dates[r] : row[c]\n })\n }\n\n const rows: TableRow[] = body.map((row, r) => ({\n text: Object.fromEntries(columns.map((col, c) => [col.key, cellText[r][c]])),\n value: Object.fromEntries(columns.map((col, c) => [col.key, parsed[r][c]])),\n cells: Array.from({ length: width }, (_, c) => (row.children[c]?.children ?? []) as PhrasingContent[]),\n }))\n\n return { node, columns, rows }\n}\n\nconst unitKey = (unit?: Unit) => `${unit?.prefix ?? \"\"}|${unit?.suffix ?? \"\"}`\n\n/**\n * Series are only plotted together when they share a unit and a comparable scale.\n * Anything else gets its own chart — two scales on one plot mislead.\n */\nfunction groupSeries(model: TableModel, numeric: TableColumn[], rowIndices: number[]): ChartSpec[] {\n const byUnit = new Map<string, TableColumn[]>()\n for (const column of numeric) {\n const key = unitKey(column.unit)\n byUnit.set(key, [...(byUnit.get(key) ?? []), column])\n }\n const charts: ChartSpec[] = []\n for (const group of byUnit.values()) {\n const peak = (column: TableColumn) =>\n Math.max(0, ...rowIndices.map((r) => Math.abs((model.rows[r].value[column.key] as number | null) ?? 0)))\n const sorted = [...group].sort((a, b) => peak(b) - peak(a))\n let cluster: TableColumn[] = []\n for (const column of sorted) {\n if (cluster.length && peak(cluster[0]) > peak(column) * 30) {\n charts.push({ seriesKeys: cluster.map((c) => c.key), unit: cluster[0].unit })\n cluster = []\n }\n cluster.push(column)\n }\n if (cluster.length) charts.push({ seriesKeys: cluster.map((c) => c.key), unit: cluster[0].unit })\n }\n // Keep the document's column order within and across charts.\n const order = (key: string) => model.columns.findIndex((c) => c.key === key)\n for (const chart of charts) chart.seriesKeys.sort((a, b) => order(a) - order(b))\n return charts.sort((a, b) => order(a.seriesKeys[0]) - order(b.seriesKeys[0]))\n}\n\n/** Chooses how a table is best shown, from its shape and the types of its columns. */\nexport function planViz(model: TableModel): VizPlan {\n const { columns, rows } = model\n const all = rows.map((_, i) => i)\n const table = (reason: string, candidates: VizKind[] = []): VizPlan => ({\n kind: \"table\",\n charts: [],\n rowIndices: all,\n candidates: [\"table\", ...candidates],\n reason,\n })\n\n if (rows.length === 0 || columns.length < 2) return table(\"too small to visualise\")\n\n let numeric = columns.filter((c) => c.type === \"number\")\n const dateColumn = columns.find((c) => c.type === \"date\")\n const texts = columns.filter((c) => c.type === \"text\")\n let label: TableColumn | undefined = dateColumn ?? texts[0]\n // A leading numeric column that only ever rises (1, 4, 8, 16…) is an ordered axis, not a measure.\n let ordinal = false\n if (!label && rows.length >= 3 && numeric.length >= 2 && numeric[0] === columns[0]) {\n const steps = rows.map((row) => row.value[columns[0].key] as number | null)\n if (steps.every((v, i) => v != null && (i === 0 || v > steps[i - 1]!))) {\n label = columns[0]\n numeric = numeric.slice(1)\n ordinal = true\n }\n }\n const otherTexts = texts.filter((c) => c !== label)\n const avgLength = (column: TableColumn) =>\n rows.reduce((sum, row) => sum + row.text[column.key].length, 0) / rows.length\n\n // A single row of numbers is a row of headline figures.\n if (rows.length === 1 && numeric.length >= 2 && numeric.length <= 6) {\n return {\n kind: \"stats\",\n labelKey: label?.key,\n charts: [{ seriesKeys: numeric.map((c) => c.key) }],\n rowIndices: all,\n candidates: [\"stats\", \"table\"],\n reason: \"one row of figures\",\n }\n }\n if (rows.length < 2) return table(\"single row\")\n\n if (numeric.length === 0) {\n if (dateColumn && otherTexts.length + (texts.includes(label!) ? 0 : texts.length) >= 1 && rows.length >= 3) {\n return {\n kind: \"timeline\",\n labelKey: dateColumn.key,\n charts: [],\n rowIndices: all,\n candidates: [\"timeline\", \"table\"],\n reason: \"dated events without figures\",\n }\n }\n if (columns.length === 2 && rows.length <= 12 && avgLength(columns[0]) <= 28) {\n return {\n kind: \"facts\",\n labelKey: columns[0].key,\n charts: [],\n rowIndices: all,\n candidates: [\"facts\", \"table\"],\n reason: \"short key–value pairs\",\n }\n }\n return table(\"no numeric columns\")\n }\n\n if (!label) {\n if (numeric.length >= 2 && rows.length >= 5) {\n return {\n kind: \"scatter\",\n labelKey: numeric[0].key,\n charts: [{ seriesKeys: [numeric[1].key], unit: numeric[1].unit }],\n rowIndices: all,\n candidates: [\"scatter\", \"table\"],\n reason: \"two measures and no category\",\n }\n }\n return table(\"no label column\")\n }\n\n // Records with as much description as measurement read better as a table.\n if (otherTexts.length >= numeric.length || otherTexts.some((c) => avgLength(c) > 40)) {\n // …unless they are dated, in which case they are a sequence of events.\n if (dateColumn && rows.length >= 3 && numeric.length <= 1) {\n return {\n kind: \"timeline\",\n labelKey: dateColumn.key,\n charts: [],\n rowIndices: all,\n candidates: [\"timeline\", \"table\"],\n reason: \"dated events with descriptions\",\n }\n }\n return table(\"descriptive columns outweigh figures\", dateColumn ? [\"timeline\"] : [])\n }\n\n const labels = rows.map((row) => row.text[label.key])\n let rowIndices = all.filter((r) => !(rows.length > 2 && SUMMARY_LABEL.test(labels[r])))\n if (new Set(rowIndices.map((r) => labels[r])).size < rowIndices.length) {\n return table(\"repeated labels — these are records, not categories\")\n }\n if (rowIndices.length < 2) return table(\"too few rows\")\n\n const charts = groupSeries(model, numeric, rowIndices)\n if (charts.length > 3 || charts.some((c) => c.seriesKeys.length > 8)) {\n return table(\"too many unrelated measures\", [\"bar\"])\n }\n const single = charts.length === 1 && charts[0].seriesKeys.length === 1\n const count = rowIndices.length\n\n if (label.type === \"date\" || ordinal) {\n const axis = label.key\n const times = rowIndices.map((r) => rows[r].value[axis] as number)\n if (times[0] > times[times.length - 1]) rowIndices = [...rowIndices].reverse()\n // One measure per plot: a trend once there are enough periods, bars to compare a few.\n const alone = charts.every((chart) => chart.seriesKeys.length === 1)\n const kind: VizKind = alone ? (count >= 8 ? \"area\" : \"bar\") : count >= 4 ? \"line\" : \"bar\"\n return {\n kind,\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [...new Set<VizKind>([kind, \"line\", \"bar\", \"area\", \"table\"])],\n reason: `${count} ${ordinal ? \"steps\" : \"periods\"} × ${numeric.length} measure(s)`,\n }\n }\n\n if (count > 30) return table(\"too many categories for a readable chart\", [\"bar\"])\n\n if (single) {\n const column = columns.find((c) => c.key === charts[0].seriesKeys[0])!\n const values = rowIndices.map((r) => (rows[r].value[column.key] as number | null) ?? 0)\n if (count <= 4 && otherTexts.length === 0) {\n return {\n kind: \"stats\",\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [\"stats\", \"bar\", \"table\"],\n reason: \"a handful of headline figures\",\n }\n }\n const sum = values.reduce((a, b) => a + b, 0)\n const wholeOf100 = column.unit?.suffix === \"%\" && sum > 98 && sum < 102\n if (count >= 3 && count <= 6 && values.every((v) => v >= 0) && (wholeOf100 || SHARE_HEADER.test(column.label))) {\n return {\n kind: \"donut\",\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [\"donut\", \"bar\", \"table\"],\n reason: \"parts of a whole\",\n }\n }\n }\n\n const cells = count * numeric.length\n if (!single && cells > 48) return table(\"too dense to chart\", [\"bar\"])\n const longest = Math.max(...rowIndices.map((r) => labels[r].length))\n return {\n kind: \"bar\",\n labelKey: label.key,\n charts,\n horizontal: single && (count > 7 || longest > 14),\n rowIndices,\n candidates: single && count <= 6 ? [\"bar\", \"donut\", \"stats\", \"table\"] : [\"bar\", \"table\"],\n reason: `${count} categories × ${numeric.length} measure(s)`,\n }\n}\n\n/** Re-plans a table as a specific form, when that form is one of its candidates. */\nexport function withVizKind(plan: VizPlan, model: TableModel, kind: VizKind): VizPlan {\n if (kind === plan.kind || !plan.candidates.includes(kind)) return plan\n const next: VizPlan = { ...plan, kind, reason: `${plan.reason} → overridden to ${kind}` }\n if (kind === \"timeline\") {\n next.labelKey = model.columns.find((c) => c.type === \"date\")?.key ?? plan.labelKey\n next.rowIndices = model.rows.map((_, i) => i)\n }\n if (kind === \"bar\" && plan.charts.length === 0) {\n const numeric = model.columns.filter((c) => c.type === \"number\")\n const label = model.columns.find((c) => c.type !== \"number\")\n if (!numeric.length || !label) return plan\n next.labelKey = label.key\n next.charts = groupSeries(model, numeric, plan.rowIndices)\n }\n if (kind === \"bar\") {\n const longest = Math.max(...next.rowIndices.map((r) => model.rows[r].text[next.labelKey ?? \"\"]?.length ?? 0))\n const single = next.charts.length === 1 && next.charts[0].seriesKeys.length === 1\n next.horizontal = single && (next.rowIndices.length > 7 || longest > 14)\n }\n return next\n}\n\n/** Compact, unit-aware number formatting for axes, tooltips and stat tiles. */\nexport function formatValue(value: number, unit?: Unit): string {\n const abs = Math.abs(value)\n const body =\n abs >= 10000\n ? new Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 }).format(value)\n : new Intl.NumberFormat(\"en\", { maximumFractionDigits: abs < 10 ? 2 : abs < 100 ? 1 : 0 }).format(value)\n const sign = body.startsWith(\"-\") ? \"−\" : \"\"\n return `${sign}${unit?.prefix ?? \"\"}${body.replace(/^-/, \"\")}${unit?.suffix ?? \"\"}`\n}\n","import type { Blockquote, Heading, List, Paragraph, PhrasingContent, Root, RootContent } from \"mdast\"\nimport type { Frontmatter } from \"../parse\"\nimport type {\n Block,\n DocumentPlan,\n Hero,\n ImageMeta,\n ImageRef,\n Judgements,\n ListVariant,\n Section,\n SectionLayout,\n TocEntry,\n} from \"../types\"\nimport { buildTableModel, planViz, withVizKind } from \"./tables\"\nimport { countWords, imagesOnly, slugify, toText, wordsIn } from \"./text\"\n\nexport type ImageMetaMap = Record<string, ImageMeta | null | undefined>\n\nexport type PlanInput = {\n root: Root\n frontmatter?: Frontmatter\n /** Natural image sizes keyed by the URL written in the markdown. */\n images?: ImageMetaMap\n judgements?: Judgements\n}\n\nconst BADGE_URL = /shields\\.io|badgen\\.net|badge\\.fury\\.io|\\/badge(s)?[./]|badge\\.svg|travis-ci|circleci\\.com|codecov\\.io|coveralls\\.io|img\\.shields/i\nconst LOGO_NAME = /logo|icon|brand|wordmark|avatar|emblem/i\nconst BANNER_NAME = /banner|cover|hero|header|splash|masthead/i\n\n/** Every image URL in the document, for size probing. */\nexport function collectImageUrls(root: Root): string[] {\n const urls = new Set<string>()\n const visit = (node: unknown) => {\n const n = node as { type?: string; url?: string; children?: unknown[] }\n if (n.type === \"image\" && n.url) urls.add(n.url)\n n.children?.forEach(visit)\n }\n visit(root)\n return [...urls]\n}\n\nfunction isBadge(image: ImageRef): boolean {\n if (BADGE_URL.test(image.src)) return true\n return !!image.meta && image.meta.height <= 40 && image.meta.width <= 320\n}\n\nfunction classifyHeroImage(image: ImageRef): Hero[\"variant\"] | null {\n const meta = image.meta\n // An image that could not be measured cannot be trusted to carry the page.\n if (!meta || meta.width < 48) return null\n const aspect = meta.width / meta.height\n const name = `${image.src.split(/[?#]/)[0]} ${image.alt}`\n const vector = /\\.svg$/i.test(image.src.split(/[?#]/)[0])\n if (LOGO_NAME.test(name) && !(meta.width >= 1600 && aspect >= 1.8)) return \"logo\"\n if (meta.width >= 1200 && aspect >= 1.5 && !vector) return \"banner\"\n if (BANNER_NAME.test(name) && meta.width >= 900 && aspect >= 1.5) return \"banner\"\n if (vector || Math.max(meta.width, meta.height) <= 640) return \"logo\"\n return \"figure\"\n}\n\ntype Context = {\n images: ImageMetaMap\n judgements: Judgements\n slugs: Set<string>\n sectionDepth: number\n splitCount: number\n dataCount: number\n}\n\nfunction imageRef(found: { image: { url: string; alt?: string | null; title?: string | null }; href?: string }, ctx: Context): ImageRef {\n return {\n src: found.image.url,\n alt: found.image.alt ?? \"\",\n title: found.image.title ?? undefined,\n href: found.href,\n meta: ctx.images[found.image.url] ?? undefined,\n }\n}\n\nfunction planList(node: List): { variant: ListVariant; columns: 1 | 2 } {\n const items = node.children\n if (items.some((item) => item.checked != null)) return { variant: \"checklist\", columns: 1 }\n const nested = items.some((item) => item.children.some((child) => child.type === \"list\" || child.type === \"code\"))\n const words = items.map((item) => wordsIn(item))\n const total = words.reduce((a, b) => a + b, 0)\n const longest = Math.max(0, ...words)\n // Short lists are a moment of emphasis; long ones are body copy that happens to be bulleted.\n if (!nested && items.length >= 2 && items.length <= 8 && longest <= 28 && total <= 130) {\n return { variant: \"feature\", columns: items.length >= 4 && longest <= 12 ? 2 : 1 }\n }\n return { variant: \"body\", columns: 1 }\n}\n\nconst ATTRIBUTION = /^\\s*(?:[—–]|--|~)\\s*(.+)$/\n\nfunction planQuote(node: Blockquote): Extract<Block, { kind: \"quote\" }> {\n let children = node.children as RootContent[]\n const first = children[0]\n\n // GitHub-style alerts: > [!NOTE]\n if (first?.type === \"paragraph\" && first.children[0]?.type === \"text\") {\n const match = /^\\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\]\\s*/i.exec(first.children[0].value)\n if (match) {\n const rest: PhrasingContent[] = [\n { type: \"text\", value: first.children[0].value.slice(match[0].length) },\n ...first.children.slice(1),\n ]\n const body = rest.some((child) => toText(child).trim()) ? [{ ...first, children: rest }] : []\n return { kind: \"quote\", variant: \"callout\", calloutType: match[1].toLowerCase(), children: [...body, ...children.slice(1)] }\n }\n }\n\n let attribution: string | undefined\n const last = children[children.length - 1]\n if (last?.type === \"paragraph\") {\n const whole = ATTRIBUTION.exec(toText(last))\n if (whole && children.length > 1) {\n attribution = whole[1].trim()\n children = children.slice(0, -1)\n } else {\n // Attribution on the final line of the same paragraph.\n const breakAt = last.children.findLastIndex((child) => child.type === \"break\")\n const tail = breakAt >= 0 ? last.children.slice(breakAt + 1) : []\n const lineMatch = tail.length ? ATTRIBUTION.exec(toText(tail)) : /\\n\\s*(?:[—–]|--|~)\\s*([^\\n]+)$/.exec(toText(last))\n if (lineMatch && breakAt >= 0) {\n attribution = lineMatch[1].trim()\n children = [...children.slice(0, -1), { ...last, children: last.children.slice(0, breakAt) }]\n } else if (lineMatch && last.children.length === 1 && last.children[0].type === \"text\") {\n attribution = lineMatch[1].trim()\n const value = last.children[0].value.replace(/\\n\\s*(?:[—–]|--|~)\\s*[^\\n]+$/, \"\")\n children = [...children.slice(0, -1), { ...last, children: [{ type: \"text\", value }] }]\n }\n }\n }\n\n const words = wordsIn(children)\n const simple = children.every((child) => child.type === \"paragraph\")\n return { kind: \"quote\", variant: simple && words <= 45 ? \"pull\" : \"aside\", children, attribution }\n}\n\nfunction buildBlocks(nodes: RootContent[], ctx: Context, sectionId: string): Block[] {\n const blocks: Block[] = []\n for (const node of nodes) {\n switch (node.type) {\n case \"heading\":\n blocks.push({\n kind: \"heading\",\n depth: Math.max(1, node.depth - ctx.sectionDepth),\n id: slugify(toText(node), ctx.slugs),\n children: node.children,\n })\n break\n case \"paragraph\": {\n const found = imagesOnly(node.children)\n const refs = found?.map((f) => imageRef(f, ctx))\n if (refs && !refs.every(isBadge)) {\n const previous = blocks[blocks.length - 1]\n const images = previous?.kind === \"media\" ? [...previous.images, ...refs] : refs\n const media: Block = {\n kind: \"media\",\n images,\n variant: images.length >= 3 ? \"slideshow\" : images.length === 2 ? \"pair\" : \"single\",\n }\n if (previous?.kind === \"media\") blocks[blocks.length - 1] = media\n else blocks.push(media)\n } else blocks.push({ kind: \"content\", node })\n break\n }\n case \"list\":\n blocks.push({ kind: \"list\", node, ...planList(node) })\n break\n case \"blockquote\":\n blocks.push(planQuote(node))\n break\n case \"code\":\n blocks.push({ kind: \"code\", lang: node.lang ?? undefined, value: node.value })\n break\n case \"table\": {\n const id = `${sectionId}-data-${++ctx.dataCount}`\n const table = buildTableModel(node)\n const viz = planViz(table)\n const wanted = ctx.judgements.viz?.[id]\n blocks.push({ kind: \"data\", id, table, viz: wanted ? withVizKind(viz, table, wanted) : viz })\n break\n }\n case \"thematicBreak\":\n blocks.push({ kind: \"rule\" })\n break\n default:\n blocks.push({ kind: \"content\", node })\n }\n }\n return blocks\n}\n\ntype RawSection = { heading?: Heading; nodes: RootContent[] }\n\ntype Shape = {\n words: number\n images: ImageRef[]\n heavy: boolean\n quoteOnly: boolean\n cards: { heading: Heading; nodes: RootContent[] }[] | null\n cardIntro: RootContent[]\n}\n\nfunction measure(raw: RawSection, ctx: Context): Shape {\n const { nodes } = raw\n const images = nodes.flatMap((node) =>\n node.type === \"paragraph\" ? (imagesOnly(node.children) ?? []).map((f) => imageRef(f, ctx)).filter((i) => !isBadge(i)) : [],\n )\n const prose = nodes.filter((node) => node.type !== \"table\" && node.type !== \"code\")\n const heavy = nodes.some((node) => node.type === \"table\" || node.type === \"code\" || node.type === \"math\")\n const quotes = nodes.filter((node) => node.type === \"blockquote\")\n const quoteOnly =\n quotes.length === 1 &&\n !heavy &&\n images.length === 0 &&\n wordsIn(quotes[0]) <= 70 &&\n wordsIn(nodes.filter((node) => node !== quotes[0])) <= 25 &&\n !/^\\[!/.test(toText(quotes[0]).trim())\n\n // Sub-sections that are each a short blurb read as a set of cards.\n const subDepth = ctx.sectionDepth + 1\n const firstSub = nodes.findIndex((node) => node.type === \"heading\" && node.depth === subDepth)\n let cards: Shape[\"cards\"] = null\n if (firstSub >= 0 && !nodes.some((node) => node.type === \"heading\" && node.depth > subDepth)) {\n const groups: { heading: Heading; nodes: RootContent[] }[] = []\n for (const node of nodes.slice(firstSub)) {\n if (node.type === \"heading\") groups.push({ heading: node, nodes: [] })\n else groups[groups.length - 1].nodes.push(node)\n }\n const blurb = (group: { nodes: RootContent[] }) =>\n group.nodes.length > 0 &&\n wordsIn(group.nodes) <= 70 &&\n group.nodes.every(\n (node) => node.type === \"paragraph\" || (node.type === \"list\" && node.children.length <= 5 && wordsIn(node) <= 50),\n ) &&\n group.nodes.filter((node) => node.type === \"paragraph\" && imagesOnly(node.children)).length <= 1\n if (groups.length >= 2 && groups.length <= 12 && groups.every(blurb)) cards = groups\n }\n\n return {\n words: wordsIn(prose),\n images,\n heavy,\n quoteOnly,\n cards,\n cardIntro: firstSub >= 0 ? nodes.slice(0, firstSub) : nodes,\n }\n}\n\n/** Layouts the content can fill, best fit first. `prose` always works. */\nfunction rankLayouts(raw: RawSection, shape: Shape): { layouts: SectionLayout[]; reason: string } {\n const { words, images, heavy } = shape\n const layouts: SectionLayout[] = []\n let reason = \"default reading layout\"\n const pick = (layout: SectionLayout, why: string) => {\n if (!layouts.length) reason = why\n if (!layouts.includes(layout)) layouts.push(layout)\n }\n const lead = images[0]?.meta\n const aspect = lead ? lead.width / lead.height : 0\n const simple = !heavy && !shape.cards\n\n if (shape.quoteOnly) pick(\"quote\", \"a single short quotation\")\n if (simple && images.length === 1 && lead && lead.width >= 1400 && aspect >= 1.3 && words <= 90) {\n pick(\"fullbleed\", `large ${lead.width}×${lead.height} image with ${words} words`)\n }\n if (simple && images.length === 1 && lead && lead.width >= 320 && words >= 20 && words <= 260) {\n pick(\"split\", `one image beside ${words} words`)\n }\n // A long run of prose before the sub-sections is an article with asides, not a card deck.\n const cardsLead = !!shape.cards && (wordsIn(shape.cardIntro) <= 90 || shape.cards.length >= 4)\n if (cardsLead) pick(\"cards\", `${shape.cards!.length} short sub-sections`)\n if (!heavy && images.length >= 2 && words <= 80) pick(\"showcase\", `${images.length} images, little text`)\n // Only a titled section is promoted to a statement: untitled opening text that\n // was not made a hero should not be dressed up as one.\n if (simple && raw.heading && images.length === 0 && words <= 45 && raw.nodes.length <= 3) {\n pick(\"statement\", `only ${words} words — give it room`)\n }\n pick(\"prose\", reason)\n\n // Looser fits: not the first choice, but still valid when picked by hand.\n if (shape.cards) pick(\"cards\", \"\")\n if (simple && images.length >= 1 && lead && lead.width >= 1000 && aspect >= 1.2 && words <= 160) pick(\"fullbleed\", \"\")\n if (simple && images.length >= 1 && lead && words >= 8 && words <= 400) pick(\"split\", \"\")\n if (!heavy && images.length >= 1 && words <= 160) pick(\"showcase\", \"\")\n if (simple && images.length === 0 && words > 0 && words <= 110 && raw.nodes.length <= 5) pick(\"statement\", \"\")\n return { layouts, reason }\n}\n\nfunction buildSection(raw: RawSection, ctx: Context, index: number): Section {\n const titleText = raw.heading ? toText(raw.heading).trim() : \"\"\n const id = raw.heading ? slugify(titleText, ctx.slugs) : slugify(\"introduction\", ctx.slugs)\n const shape = measure(raw, ctx)\n const { layouts, reason } = rankLayouts(raw, shape)\n const wanted = ctx.judgements.layouts?.[id]\n const layout = wanted && layouts.includes(wanted) ? wanted : layouts[0]\n\n let blocks: Block[]\n let feature: ImageRef | undefined\n let flip: boolean | undefined\n\n if (layout === \"cards\" && shape.cards) {\n blocks = [\n ...buildBlocks(shape.cardIntro, ctx, id),\n {\n kind: \"cards\",\n items: shape.cards.map((card) => ({\n id: slugify(toText(card.heading), ctx.slugs),\n title: card.heading.children,\n blocks: buildBlocks(card.nodes, ctx, id),\n })),\n },\n ]\n } else if (layout === \"split\" || layout === \"fullbleed\") {\n feature = shape.images[0]\n // The feature image leaves the flow; any further images stay where they were.\n let taken = false\n const rest = raw.nodes.filter((node) => {\n if (taken || node.type !== \"paragraph\") return true\n const found = imagesOnly(node.children)\n if (found?.length === 1 && found[0].image.url === feature!.src) return !(taken = true)\n return true\n })\n blocks = buildBlocks(rest, ctx, id)\n if (layout === \"split\") flip = ctx.splitCount++ % 2 === 1\n } else {\n blocks = buildBlocks(raw.nodes, ctx, id)\n }\n\n const tone = layout === \"quote\" ? \"invert\" : layout === \"statement\" ? \"tint\" : \"plain\"\n return {\n id,\n title: raw.heading?.children ?? [],\n titleText,\n layout,\n tone,\n blocks,\n feature,\n flip,\n words: shape.words,\n reason: wanted && layout === wanted ? `chosen: ${wanted}` : `${reason}${index === 0 && !raw.heading ? \" (introduction)\" : \"\"}`,\n alternatives: layouts,\n }\n}\n\nconst asString = (value: unknown) => (typeof value === \"string\" && value.trim() ? value.trim() : undefined)\n\n/**\n * Turns a parsed document into a layout plan. Pure and deterministic: the same\n * tree, image sizes and judgements always yield the same plan.\n */\nexport function planDocument(input: PlanInput): DocumentPlan {\n const { root } = input\n const frontmatter = input.frontmatter ?? {}\n const nodes = root.children\n const headings = nodes.filter((node): node is Heading => node.type === \"heading\")\n\n // The title is a leading H1 — one that comes before any other heading.\n const titleNode = headings[0]?.depth === 1 ? headings[0] : undefined\n const sectionHeadings = headings.filter((h) => h !== titleNode)\n const sectionDepth = sectionHeadings.length ? Math.min(...sectionHeadings.map((h) => h.depth)) : 2\n\n const ctx: Context = {\n images: input.images ?? {},\n judgements: input.judgements ?? {},\n slugs: new Set([\"top\"]),\n sectionDepth,\n splitCount: 0,\n dataCount: 0,\n }\n\n const firstSection = nodes.findIndex((node) => node.type === \"heading\" && node !== titleNode && node.depth === sectionDepth)\n const preamble = (firstSection >= 0 ? nodes.slice(0, firstSection) : nodes).filter((node) => node !== titleNode)\n const body = firstSection >= 0 ? nodes.slice(firstSection) : []\n\n // --- Hero -----------------------------------------------------------------\n const badges: ImageRef[] = []\n const lead: PhrasingContent[][] = []\n let heroImage: ImageRef | undefined\n let heroVariant: Hero[\"variant\"] = \"plain\"\n const intro: RootContent[] = []\n let leadOpen = true\n let leadWords = 0\n\n const coverUrl = asString(frontmatter.image) ?? asString(frontmatter.cover) ?? asString(frontmatter.banner)\n if (coverUrl) {\n const candidate: ImageRef = { src: coverUrl, alt: \"\", meta: ctx.images[coverUrl] ?? undefined }\n const variant = classifyHeroImage(candidate)\n if (variant) [heroImage, heroVariant] = [candidate, variant]\n }\n\n for (const node of preamble) {\n if (node.type === \"paragraph\") {\n const found = imagesOnly(node.children)\n if (found) {\n const refs = found.map((f) => imageRef(f, ctx))\n if (refs.every(isBadge)) {\n badges.push(...refs)\n continue\n }\n if (!heroImage && refs.length === 1 && ctx.judgements.heroImageUsable !== false) {\n const variant = classifyHeroImage(refs[0])\n if (variant) {\n ;[heroImage, heroVariant] = [refs[0], variant]\n continue\n }\n }\n } else if (leadOpen && lead.length < 2) {\n const words = countWords(toText(node))\n if (leadWords + words <= 70) {\n lead.push((node as Paragraph).children)\n leadWords += words\n continue\n }\n }\n }\n // The lead is the opening run of short paragraphs; anything else ends it.\n if (!(node.type === \"paragraph\" && imagesOnly(node.children))) leadOpen = false\n intro.push(node)\n }\n\n // A hero is never forced: without a title or an image fit to lead the page,\n // the opening paragraphs are simply the start of the text.\n const frontTitle = asString(frontmatter.title)\n const hasHero = !!titleNode || !!frontTitle || !!heroImage\n if (!hasHero) {\n intro.splice(0, intro.length, ...preamble)\n lead.length = 0\n badges.length = 0\n leadWords = 0\n }\n\n const description = asString(frontmatter.description) ?? asString(frontmatter.subtitle) ?? asString(frontmatter.summary)\n if (hasHero && description && !lead.length) lead.push([{ type: \"text\", value: description }])\n\n const title: PhrasingContent[] = titleNode?.children ?? (frontTitle ? [{ type: \"text\", value: frontTitle }] : [])\n const eyebrowParts = [asString(frontmatter.category), asString(frontmatter.author)]\n const date = frontmatter.date\n if (date instanceof Date) eyebrowParts.push(date.toISOString().slice(0, 10))\n else if (asString(date)) eyebrowParts.push(asString(date))\n\n const hero: Hero = {\n variant: heroImage ? heroVariant : \"plain\",\n title,\n titleText: toText(title).trim(),\n lead,\n image: heroImage,\n badges,\n eyebrow: (hasHero && eyebrowParts.filter(Boolean).join(\" · \")) || undefined,\n }\n\n // --- Sections ---------------------------------------------------------------\n const raws: RawSection[] = []\n if (intro.length) raws.push({ nodes: intro })\n for (const node of body) {\n if (node.type === \"heading\" && node.depth === sectionDepth) raws.push({ heading: node, nodes: [] })\n else raws[raws.length - 1].nodes.push(node)\n }\n const sections = raws.map((raw, index) => buildSection(raw, ctx, index))\n\n // Two tinted bands in a row would merge into one; keep the rhythm.\n for (let i = 1; i < sections.length; i++) {\n if (sections[i].tone === \"tint\" && sections[i - 1].tone === \"tint\") sections[i].tone = \"plain\"\n }\n\n // --- Navigation ---------------------------------------------------------------\n const toc: TocEntry[] = []\n for (const section of sections) {\n if (!section.titleText) continue\n toc.push({ id: section.id, text: section.titleText, depth: 0 })\n const subs: { id: string; text: string }[] = []\n for (const block of section.blocks) {\n if (block.kind === \"heading\" && block.depth === 1) subs.push({ id: block.id, text: toText(block.children) })\n if (block.kind === \"cards\") for (const item of block.items) subs.push({ id: item.id, text: toText(item.title) })\n }\n for (const sub of subs) toc.push({ ...sub, depth: 1 })\n }\n const titled = sections.filter((s) => s.titleText).length\n const words = sections.reduce((sum, s) => sum + s.words, 0) + leadWords\n\n return {\n hero,\n sections,\n toc: toc.length > 40 ? toc.filter((entry) => entry.depth === 0) : toc,\n showToc: titled >= 3,\n words,\n readingTime: Math.max(1, Math.round(words / 220)),\n }\n}\n","import type { CSSProperties } from \"react\"\nimport type { Appearance, FontPairingId, PaletteId, ThemeChoice } from \"../types\"\n\nexport type PaletteTokens = {\n bg: string\n /** Cards, code blocks and tinted section bands. */\n surface: string\n fg: string\n /** Secondary text. */\n muted: string\n border: string\n accent: string\n accentFg: string\n}\n\n/**\n * Chart drawing styles: `linework` is monochrome print-style ink with hatching,\n * `instrument` has rounded, saturated marks on calm surfaces, `soft` adds\n * gradients and depth, and `flat` is plain solid colour.\n */\nexport type ChartStyle = \"linework\" | \"instrument\" | \"soft\" | \"flat\"\n\nexport type Theme = {\n id: PaletteId\n name: string\n /** The kinds of document this theme suits. */\n description: string\n /** Its key colours in a few plain words — read by the classifier alongside the description. */\n look: string\n /** Typography used unless the caller picks another. */\n fonts: FontPairingId\n /** 0 = soft and rounded … 1 = sharp and formal. Sets the corner radius. */\n formality: number\n /** How charts are drawn under this theme. */\n chart: ChartStyle\n /** Fallback matching when no classifier is configured. */\n keywords: RegExp\n light: PaletteTokens\n dark: PaletteTokens\n}\n\nconst tokens = (bg: string, surface: string, fg: string, muted: string, border: string, accent: string, accentFg: string): PaletteTokens => ({\n bg,\n surface,\n fg,\n muted,\n border,\n accent,\n accentFg,\n})\n\nexport const themes: Record<PaletteId, Theme> = {\n paper: {\n id: \"paper\",\n name: \"Paper\",\n description: \"essays, stories, opinion, personal writing\",\n look: \"cream paper, terracotta accent\",\n fonts: \"editorial\",\n formality: 0.5,\n chart: \"flat\",\n keywords: /\\b(essay|story|chapter|novel|memoir|poem|letter|journal|philosophy|opinion|notebook|writing)\\b/gi,\n light: tokens(\"#faf7f2\", \"#f1ebe1\", \"#1f1b16\", \"#6b6257\", \"#e0d7c9\", \"#a8481f\", \"#ffffff\"),\n dark: tokens(\"#171411\", \"#221d18\", \"#f1ebe2\", \"#a89f92\", \"#352e26\", \"#e59468\", \"#1a120c\"),\n },\n ink: {\n id: \"ink\",\n name: \"Ink\",\n description: \"plain notes, memos, minimal design writing\",\n look: \"white, black ink, no colour\",\n fonts: \"modern\",\n formality: 0.7,\n chart: \"linework\",\n keywords: /\\b(design|minimal|typography|studio|portfolio|notes|memo|manifesto)\\b/gi,\n light: tokens(\"#ffffff\", \"#f4f4f5\", \"#0a0a0a\", \"#5f5f68\", \"#e4e4e7\", \"#18181b\", \"#ffffff\"),\n dark: tokens(\"#0a0a0a\", \"#18181b\", \"#fafafa\", \"#a1a1aa\", \"#27272a\", \"#f4f4f5\", \"#0a0a0a\"),\n },\n ocean: {\n id: \"ocean\",\n name: \"Ocean\",\n description: \"business reports, finance, strategy, investors\",\n look: \"cool white, navy, corporate blue\",\n fonts: \"modern\",\n formality: 0.6,\n chart: \"soft\",\n keywords: /\\b(revenue|profit|quarter|q[1-4]|market|investor|financial|growth|customers?|sales|strategy|kpi|forecast|budget|margin|earnings|business)\\b/gi,\n light: tokens(\"#f7fafc\", \"#eaf1f7\", \"#0f1f2e\", \"#52667a\", \"#d5e0eb\", \"#0b5fa8\", \"#ffffff\"),\n dark: tokens(\"#0b1420\", \"#121f2e\", \"#e8f0f7\", \"#93a7ba\", \"#213347\", \"#62b0f0\", \"#06121d\"),\n },\n forest: {\n id: \"forest\",\n name: \"Forest\",\n description: \"nature, environment, outdoors, gardening\",\n look: \"sage background, deep green\",\n fonts: \"friendly\",\n formality: 0.35,\n chart: \"instrument\",\n keywords: /\\b(nature|climate|forest|garden|plants?|sustainab\\w+|environment\\w*|organic|wildlife|hiking|ecology|carbon|farm\\w*|valley|trail)\\b/gi,\n light: tokens(\"#f6f8f3\", \"#e9efe2\", \"#17231a\", \"#586a5b\", \"#d3ddcd\", \"#2b6a3c\", \"#ffffff\"),\n dark: tokens(\"#0e1510\", \"#17211a\", \"#e6efe6\", \"#97aa9a\", \"#28372c\", \"#7fc890\", \"#0b160e\"),\n },\n sunset: {\n id: \"sunset\",\n name: \"Sunset\",\n description: \"travel journals, itineraries, destinations\",\n look: \"warm peach, burnt orange\",\n fonts: \"elegant\",\n formality: 0.4,\n chart: \"soft\",\n keywords: /\\b(travel|trip|beach|hotel|festival|holiday|itinerary|adventure|temples?|shrine|guesthouse|city|walks?|journey|island)\\b/gi,\n light: tokens(\"#fff9f4\", \"#fdeee2\", \"#2a1710\", \"#78594b\", \"#f0d8c8\", \"#bb3a15\", \"#ffffff\"),\n dark: tokens(\"#1a100c\", \"#281912\", \"#fbeee6\", \"#c0a497\", \"#3d281e\", \"#ff8f63\", \"#200e06\"),\n },\n violet: {\n id: \"violet\",\n name: \"Violet\",\n description: \"tech products, startups, AI, launches\",\n look: \"lavender, vivid purple\",\n fonts: \"friendly\",\n formality: 0.25,\n chart: \"instrument\",\n keywords: /\\b(product|startup|launch|ai|model|platform|features?|app|saas|creative|innovation|roadmap|pricing|beta)\\b/gi,\n light: tokens(\"#faf8ff\", \"#f0ebfd\", \"#1a1530\", \"#625b7e\", \"#dfd8f5\", \"#6236e0\", \"#ffffff\"),\n dark: tokens(\"#100d1c\", \"#1a162c\", \"#efeaff\", \"#a69fc4\", \"#2c2647\", \"#a892ff\", \"#120b2a\"),\n },\n terminal: {\n id: \"terminal\",\n name: \"Terminal\",\n description: \"software docs, READMEs, API and developer guides\",\n look: \"cool grey, teal\",\n fonts: \"technical\",\n formality: 0.6,\n chart: \"flat\",\n keywords: /\\b(install|npm|api|cli|usage|config\\w*|repository|function|library|docker|git|sdk|endpoint|compile|typescript|python|server|deploy\\w*)\\b/gi,\n light: tokens(\"#f6f8f9\", \"#e9eff1\", \"#0d1b21\", \"#4f656e\", \"#d2dde1\", \"#0a716c\", \"#ffffff\"),\n dark: tokens(\"#0a0f12\", \"#121b20\", \"#e2ecef\", \"#8ba2ab\", \"#202f36\", \"#45dcc2\", \"#04201b\"),\n },\n chambers: {\n id: \"chambers\",\n name: \"Chambers\",\n description: \"legal documents, contracts, policy, regulation\",\n look: \"ivory, navy and gold\",\n fonts: \"classic\",\n formality: 0.9,\n chart: \"flat\",\n keywords: /\\b(agreement|contract|clause|shall|court|law|legal|policy|regulation|act|statute|party|parties|compliance|hereby|pursuant|terms)\\b/gi,\n light: tokens(\"#fbfaf7\", \"#f0eee6\", \"#151c2c\", \"#575e70\", \"#dbd8cd\", \"#1f3a6e\", \"#ffffff\"),\n dark: tokens(\"#0d111b\", \"#161c2b\", \"#ece9e0\", \"#a0a6b5\", \"#283046\", \"#cdae66\", \"#1a1405\"),\n },\n academia: {\n id: \"academia\",\n name: \"Academia\",\n description: \"scholarly papers, research, theses, lecture notes\",\n look: \"ivory, oxblood red\",\n fonts: \"scholarly\",\n formality: 0.9,\n chart: \"linework\",\n keywords: /\\b(research|study|abstract|hypothesis|methodology|findings|literature|thesis|theorem|proof|citation|journal|university|experiment)\\b/gi,\n light: tokens(\"#fbf9f3\", \"#f1eddf\", \"#1c1812\", \"#655c4c\", \"#ddd6c2\", \"#7b1e22\", \"#ffffff\"),\n dark: tokens(\"#13110c\", \"#1e1b13\", \"#efe9d8\", \"#aca38c\", \"#332e20\", \"#e58a86\", \"#240808\"),\n },\n blueprint: {\n id: \"blueprint\",\n name: \"Blueprint\",\n description: \"engineering specs, architecture, hardware, proposals\",\n look: \"drafting blue-white, cobalt\",\n fonts: \"geometric\",\n formality: 0.8,\n chart: \"flat\",\n keywords: /\\b(specification|architecture|system|design doc|requirements?|protocol|diagram|engineering|hardware|sensor|circuit|tolerance|proposal|rfc)\\b/gi,\n light: tokens(\"#f5f8fd\", \"#e6eefa\", \"#0c1a33\", \"#4c5f80\", \"#cfdcf0\", \"#1447c8\", \"#ffffff\"),\n dark: tokens(\"#08122a\", \"#0f1d3d\", \"#e4ecfb\", \"#93a6cc\", \"#1d3160\", \"#7aa5ff\", \"#05102a\"),\n },\n midnight: {\n id: \"midnight\",\n name: \"Midnight\",\n description: \"night-time, space, science fiction, games, nightlife\",\n look: \"deep indigo, electric cyan\",\n fonts: \"geometric\",\n formality: 0.4,\n chart: \"instrument\",\n keywords: /\\b(space|galaxy|stars?|orbit|planet|astronom\\w+|game|gaming|cyber\\w*|future|sci-?fi|night|dark|dusk|cinematic|neon|milky way)\\b/gi,\n light: tokens(\"#f6f6fc\", \"#eaeaf7\", \"#14132b\", \"#5a5980\", \"#d7d6ee\", \"#3d2fd0\", \"#ffffff\"),\n dark: tokens(\"#07071a\", \"#10102a\", \"#ecebff\", \"#9c9bc6\", \"#232350\", \"#5ee6ff\", \"#03141a\"),\n },\n rose: {\n id: \"rose\",\n name: \"Rose\",\n description: \"weddings, beauty, fashion, celebrations\",\n look: \"blush pink, deep rose\",\n fonts: \"luxe\",\n formality: 0.3,\n chart: \"soft\",\n keywords: /\\b(wedding|bride|beauty|fashion|skincare|romance|love|invitation|bouquet|engagement|anniversary|bridal)\\b/gi,\n light: tokens(\"#fff7f7\", \"#fbe9ea\", \"#2b1519\", \"#7a5560\", \"#f1d3d6\", \"#b3305a\", \"#ffffff\"),\n dark: tokens(\"#1a0e11\", \"#27161b\", \"#fbe9ec\", \"#c59ba5\", \"#3e242b\", \"#ff8fae\", \"#2a0a14\"),\n },\n sand: {\n id: \"sand\",\n name: \"Sand\",\n description: \"interiors, craft, slow living, quiet luxury\",\n look: \"stone beige, muted olive\",\n fonts: \"luxe\",\n formality: 0.7,\n chart: \"flat\",\n keywords: /\\b(interior|furniture|ceramics?|craft|atelier|linen|slow living|minimalis[mt]|gallery|curated|artisan)\\b/gi,\n light: tokens(\"#f8f5ef\", \"#ece6da\", \"#26221b\", \"#6a6253\", \"#dcd3c2\", \"#5d6b2f\", \"#ffffff\"),\n dark: tokens(\"#15130f\", \"#201d17\", \"#efe9dc\", \"#aba28f\", \"#353026\", \"#b9c77a\", \"#171a08\"),\n },\n citrus: {\n id: \"citrus\",\n name: \"Citrus\",\n description: \"children, schools, community, playful guides\",\n look: \"sunny yellow, bold orange\",\n fonts: \"rounded\",\n formality: 0.05,\n chart: \"instrument\",\n keywords: /\\b(kids?|children|school|classroom|play|fun|games?|party|club|camp|volunteers?|community|activities|learn\\w*)\\b/gi,\n light: tokens(\"#fffdf2\", \"#fbf3c9\", \"#1f1a05\", \"#6b6130\", \"#eee2a6\", \"#b84a00\", \"#ffffff\"),\n dark: tokens(\"#151302\", \"#211e08\", \"#fdf8d8\", \"#bdb37a\", \"#37320f\", \"#ffd23f\", \"#1c1600\"),\n },\n crimson: {\n id: \"crimson\",\n name: \"Crimson\",\n description: \"news, journalism, press releases, politics\",\n look: \"newsprint white, strong red\",\n fonts: \"gazette\",\n formality: 0.85,\n chart: \"flat\",\n keywords: /\\b(news|report(ed|er|ing)?|press release|journalis\\w+|election|government|minister|breaking|investigation|headline|spokesperson|announced)\\b/gi,\n light: tokens(\"#ffffff\", \"#f6f2f2\", \"#120a0a\", \"#5f5252\", \"#e6dcdc\", \"#c1121f\", \"#ffffff\"),\n dark: tokens(\"#0f0a0a\", \"#1b1313\", \"#f7efef\", \"#b5a3a3\", \"#2e2121\", \"#ff5a63\", \"#1f0406\"),\n },\n slate: {\n id: \"slate\",\n name: \"Slate\",\n description: \"operations manuals, industrial reports, safety procedures\",\n look: \"steel grey, safety orange\",\n fonts: \"slab\",\n formality: 0.75,\n chart: \"flat\",\n keywords: /\\b(manual|procedure|maintenance|safety|inspection|operations?|runbook|checklist|equipment|construction|logistics|warehouse|incident)\\b/gi,\n light: tokens(\"#f4f6f7\", \"#e5eaed\", \"#131c22\", \"#4d5c66\", \"#cfd8de\", \"#b4470b\", \"#ffffff\"),\n dark: tokens(\"#0d1215\", \"#161d22\", \"#e3eaee\", \"#93a2ab\", \"#26313a\", \"#ff9248\", \"#1e0d02\"),\n },\n lagoon: {\n id: \"lagoon\",\n name: \"Lagoon\",\n description: \"healthcare, medicine, patient information, wellbeing\",\n look: \"white and aqua, calm teal\",\n fonts: \"modern\",\n formality: 0.45,\n chart: \"instrument\",\n keywords: /\\b(health\\w*|medical|patients?|clinic\\w*|treatment|symptoms?|doctor|nurse|therapy|wellness|wellbeing|diagnos\\w+|care|vaccine)\\b/gi,\n light: tokens(\"#f5fbfb\", \"#e2f3f3\", \"#0b2226\", \"#46666b\", \"#c8e2e3\", \"#0a7480\", \"#ffffff\"),\n dark: tokens(\"#06161a\", \"#0d2126\", \"#e0f3f4\", \"#8db4b9\", \"#17363d\", \"#4fd4df\", \"#031a1d\"),\n },\n plum: {\n id: \"plum\",\n name: \"Plum\",\n description: \"arts, music, theatre, film, exhibitions\",\n look: \"soft mauve, deep plum\",\n fonts: \"elegant\",\n formality: 0.5,\n chart: \"soft\",\n keywords: /\\b(art|artist|music|concert|theatre|theater|film|exhibition|gallery|opera|dance|festival|programme|culture|orchestra)\\b/gi,\n light: tokens(\"#fbf7fa\", \"#f1e6ef\", \"#24121f\", \"#6c5066\", \"#e2d0de\", \"#7a1f6b\", \"#ffffff\"),\n dark: tokens(\"#150b13\", \"#21131e\", \"#f5e8f1\", \"#b99ab2\", \"#372232\", \"#f0a6d8\", \"#2a0a22\"),\n },\n poster: {\n id: \"poster\",\n name: \"Poster\",\n description: \"events, sports, bold announcements, manifestos\",\n look: \"black and white, electric blue\",\n fonts: \"poster\",\n formality: 1,\n chart: \"flat\",\n keywords: /\\b(event|tickets?|match|league|team|championship|tournament|race|drop|lineup|kick-?off|season|score|win)\\b/gi,\n light: tokens(\"#ffffff\", \"#f0f0f0\", \"#000000\", \"#555555\", \"#d9d9d9\", \"#1a3cff\", \"#ffffff\"),\n dark: tokens(\"#000000\", \"#141414\", \"#ffffff\", \"#a8a8a8\", \"#2b2b2b\", \"#e8ff3a\", \"#101400\"),\n },\n espresso: {\n id: \"espresso\",\n name: \"Espresso\",\n description: \"food, recipes, coffee, restaurants, small makers\",\n look: \"cream, coffee brown, caramel\",\n fonts: \"slab\",\n formality: 0.5,\n chart: \"flat\",\n keywords: /\\b(recipe|food|restaurant|cook\\w*|bak\\w+|coffee|cafe|menu|ingredients?|wine|taste|kitchen|dinner|chef|flavou?r)\\b/gi,\n light: tokens(\"#f8f1e9\", \"#eee0d0\", \"#2a1a10\", \"#6f5646\", \"#dfcbb7\", \"#8b4a12\", \"#ffffff\"),\n dark: tokens(\"#17100b\", \"#231912\", \"#f3e6d8\", \"#b79f8c\", \"#3a2a1f\", \"#e9a763\", \"#241204\"),\n },\n console: {\n id: \"console\",\n name: \"Console\",\n description: \"changelogs, release notes, security write-ups, logs\",\n look: \"black screen, phosphor green\",\n fonts: \"mono\",\n formality: 0.95,\n chart: \"linework\",\n keywords: /\\b(changelog|release notes|patch|exploit|vulnerabilit\\w+|cve|payload|shell|kernel|stack trace|commit|binary|ctf|debug\\w*)\\b/gi,\n light: tokens(\"#f7f9f4\", \"#e8eee0\", \"#101a0e\", \"#4c5f48\", \"#d0dcc6\", \"#1f7a1f\", \"#ffffff\"),\n dark: tokens(\"#050a05\", \"#0c140c\", \"#d7f5d0\", \"#86a880\", \"#1a2a1a\", \"#5cf25c\", \"#021002\"),\n },\n}\n\nexport const themeList = Object.values(themes)\n\nexport type FontPairing = {\n id: FontPairingId\n name: string\n /** The headline typeface and its character, in a few words — read by the classifier. */\n look: string\n heading: string\n body: string\n mono: string\n /** Google Fonts `family=` parameters. */\n google: string[]\n headingWeight: number\n /** Heading letter-spacing in em. */\n tracking: number\n}\n\nconst MONO = `\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace`\nconst MONO_GOOGLE = \"JetBrains+Mono:wght@400;600\"\nconst SANS = \"system-ui, sans-serif\"\nconst SERIF = \"Georgia, serif\"\n\nexport const fontPairings: Record<FontPairingId, FontPairing> = {\n editorial: {\n id: \"editorial\",\n name: \"Editorial\",\n look: \"Fraunces, literary serif\",\n heading: `\"Fraunces\", ${SERIF}`,\n body: `\"Newsreader\", ${SERIF}`,\n mono: MONO,\n google: [\"Fraunces:opsz,wght@9..144,400..700\", \"Newsreader:ital,opsz,wght@0,6..72,400..600;1,6..72,400..600\", MONO_GOOGLE],\n headingWeight: 560,\n tracking: -0.02,\n },\n modern: {\n id: \"modern\",\n name: \"Modern\",\n look: \"Inter, neutral sans\",\n heading: `\"Inter Tight\", \"Inter\", ${SANS}`,\n body: `\"Inter\", ${SANS}`,\n mono: MONO,\n google: [\"Inter+Tight:wght@500..800\", \"Inter:wght@400..700\", MONO_GOOGLE],\n headingWeight: 680,\n tracking: -0.03,\n },\n technical: {\n id: \"technical\",\n name: \"Technical\",\n look: \"Space Grotesk, engineered sans\",\n heading: `\"Space Grotesk\", ${SANS}`,\n body: `\"IBM Plex Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Space+Grotesk:wght@400..700\", \"IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.03,\n },\n elegant: {\n id: \"elegant\",\n name: \"Elegant\",\n look: \"Playfair Display, display serif\",\n heading: `\"Playfair Display\", ${SERIF}`,\n body: `\"Source Sans 3\", ${SANS}`,\n mono: MONO,\n google: [\"Playfair+Display:ital,wght@0,400..800;1,400..800\", \"Source+Sans+3:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.015,\n },\n friendly: {\n id: \"friendly\",\n name: \"Friendly\",\n look: \"Bricolage Grotesque, warm sans\",\n heading: `\"Bricolage Grotesque\", ${SANS}`,\n body: `\"DM Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Bricolage+Grotesque:opsz,wght@12..96,400..800\", \"DM+Sans:ital,opsz,wght@0,9..40,400..700;1,9..40,400..700\", MONO_GOOGLE],\n headingWeight: 700,\n tracking: -0.03,\n },\n classic: {\n id: \"classic\",\n name: \"Classic\",\n look: \"Spectral, book serif\",\n heading: `\"Spectral\", ${SERIF}`,\n body: `\"Public Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Spectral:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500\", \"Public+Sans:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.012,\n },\n scholarly: {\n id: \"scholarly\",\n name: \"Scholarly\",\n look: \"EB Garamond, old-style serif\",\n heading: `\"EB Garamond\", ${SERIF}`,\n body: `\"EB Garamond\", ${SERIF}`,\n mono: MONO,\n google: [\"EB+Garamond:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.01,\n },\n geometric: {\n id: \"geometric\",\n name: \"Geometric\",\n look: \"Sora, geometric sans\",\n heading: `\"Sora\", ${SANS}`,\n body: `\"Manrope\", ${SANS}`,\n mono: MONO,\n google: [\"Sora:wght@400..700\", \"Manrope:wght@400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.035,\n },\n luxe: {\n id: \"luxe\",\n name: \"Luxe\",\n look: \"Cormorant Garamond, fashion serif\",\n heading: `\"Cormorant Garamond\", ${SERIF}`,\n body: `\"Jost\", ${SANS}`,\n mono: MONO,\n google: [\"Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500\", \"Jost:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 500,\n tracking: -0.01,\n },\n rounded: {\n id: \"rounded\",\n name: \"Rounded\",\n look: \"Nunito, rounded sans\",\n heading: `\"Nunito\", ${SANS}`,\n body: `\"Nunito Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Nunito:wght@400;600;700;800;900\", \"Nunito+Sans:ital,wght@0,400;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 800,\n tracking: -0.02,\n },\n gazette: {\n id: \"gazette\",\n name: \"Gazette\",\n look: \"DM Serif Display, newspaper serif\",\n heading: `\"DM Serif Display\", ${SERIF}`,\n body: `\"Libre Franklin\", ${SANS}`,\n mono: MONO,\n google: [\"DM+Serif+Display:ital@0;1\", \"Libre+Franklin:ital,wght@0,400;0,500;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 400,\n tracking: -0.01,\n },\n slab: {\n id: \"slab\",\n name: \"Slab\",\n look: \"Zilla Slab, sturdy slab serif\",\n heading: `\"Zilla Slab\", ${SERIF}`,\n body: `\"Work Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Zilla+Slab:ital,wght@0,400;0,500;0,600;0,700;1,400\", \"Work+Sans:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.015,\n },\n poster: {\n id: \"poster\",\n name: \"Poster\",\n look: \"Archivo Black, heavy headlines\",\n heading: `\"Archivo Black\", \"Archivo\", ${SANS}`,\n body: `\"Archivo\", ${SANS}`,\n mono: MONO,\n google: [\"Archivo+Black\", \"Archivo:ital,wght@0,400;0,500;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 400,\n tracking: -0.035,\n },\n mono: {\n id: \"mono\",\n name: \"Mono\",\n look: \"JetBrains Mono, monospace\",\n heading: MONO,\n body: `\"IBM Plex Sans\", ${SANS}`,\n mono: MONO,\n google: [\"JetBrains+Mono:wght@400;500;600;700\", \"IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;1,400\"],\n headingWeight: 600,\n tracking: -0.04,\n },\n}\n\nexport const fontPairingList = Object.values(fontPairings)\n\nexport function googleFontsUrl(pairing: FontPairing): string {\n return `https://fonts.googleapis.com/css2?${pairing.google.map((family) => `family=${family}`).join(\"&\")}&display=swap`\n}\n\n/**\n * What the classifier reads when choosing a theme: the content it suits, its\n * key colours and its typeface, so the choice can weigh appearance as well as\n * subject. Kept terse on purpose — classifier latency grows with every\n * character here, across every theme.\n */\nexport function describeTheme(theme: Theme): string {\n return `${theme.description}; ${theme.look}; ${fontPairings[theme.fonts].look}`\n}\n\n/** The complete default choice a theme stands for. */\nexport function themeChoice(id: PaletteId): ThemeChoice {\n const theme = themes[id]\n return { palette: id, fonts: theme.fonts, formality: theme.formality }\n}\n\n/**\n * The theme whose vocabulary stands out in the text, or `null` when none does.\n * This is evidence from the words themselves, independent of any classifier.\n */\nexport function matchTheme(text: string, stats: { codeBlocks: number; tables: number }): PaletteId | null {\n const words = Math.max(200, text.split(/\\s+/).length)\n let best: PaletteId | null = null\n let bestScore = 0.6\n for (const theme of themeList) {\n let score = ((text.match(theme.keywords) ?? []).length / words) * 100\n // Code and tables hint at a genre, but only words can confirm it.\n if (theme.id === \"terminal\") score += Math.min(3, stats.codeBlocks * 0.75)\n if (theme.id === \"ocean\" && score > 0) score += Math.min(0.6, stats.tables * 0.15)\n if (score > bestScore) [best, bestScore] = [theme.id, score]\n }\n return best\n}\n\n/**\n * Picks a theme from the words in the document — the fallback when no classifier\n * is configured, and what the loader is drawn in while the classifier decides.\n */\nexport function guessTheme(text: string, stats: { codeBlocks: number; tables: number }): ThemeChoice {\n return themeChoice(matchTheme(text, stats) ?? \"paper\")\n}\n\n/**\n * CSS custom properties for a theme. They use shadcn's token names, so every\n * shadcn component inside the scope picks the theme up without changes.\n */\nexport function themeVars(choice: ThemeChoice, appearance: Appearance): CSSProperties {\n const tokens = themes[choice.palette][appearance]\n const fonts = fontPairings[choice.fonts]\n const radius = 0.25 + (1 - choice.formality) * 0.75\n const soft = `color-mix(in oklab, ${tokens.accent} 12%, ${tokens.bg})`\n const vars: Record<string, string> = {\n \"--background\": tokens.bg,\n \"--foreground\": tokens.fg,\n \"--card\": tokens.surface,\n \"--card-foreground\": tokens.fg,\n \"--popover\": appearance === \"dark\" ? tokens.surface : tokens.bg,\n \"--popover-foreground\": tokens.fg,\n \"--primary\": tokens.accent,\n \"--primary-foreground\": tokens.accentFg,\n \"--secondary\": tokens.surface,\n \"--secondary-foreground\": tokens.fg,\n \"--muted\": tokens.surface,\n \"--muted-foreground\": tokens.muted,\n \"--accent\": soft,\n \"--accent-foreground\": tokens.fg,\n \"--border\": tokens.border,\n \"--input\": tokens.border,\n \"--ring\": tokens.accent,\n \"--radius\": `${radius.toFixed(3)}rem`,\n \"--smd-soft\": soft,\n \"--smd-bg\": tokens.bg,\n \"--smd-fg\": tokens.fg,\n \"--smd-surface\": tokens.surface,\n \"--smd-accent\": tokens.accent,\n \"--smd-font-heading\": fonts.heading,\n \"--smd-font-body\": fonts.body,\n \"--smd-font-mono\": fonts.mono,\n \"--smd-heading-weight\": String(fonts.headingWeight),\n \"--smd-tracking\": `${fonts.tracking}em`,\n colorScheme: appearance,\n }\n return vars as CSSProperties\n}\n","import { toText } from \"./analyze/text\"\nimport { describeTheme, themeList, themes } from \"./theme/themes\"\nimport type { DocumentPlan, Judgements, PaletteId, VizKind } from \"./types\"\n\n/**\n * Question shapes of a \"jev\"-compatible classifier endpoint: the request carries\n * a `state` (the text to judge) and named questions, each answered independently.\n */\nexport type ClassifierQuestion =\n | { type: \"choice\"; criteria: Record<string, string> }\n | { type: \"noul\"; criteria: { true: string; false: string } }\n | { type: \"score\"; criteria: string[] }\n\nexport type ClassifierRequest = {\n state: string\n questions: Record<string, ClassifierQuestion>\n}\n\nexport type ClassifierAnswer =\n | { type: \"choice\"; choice: string; confidence: number; probabilities?: Record<string, number> }\n | { type: \"noul\"; noul: number }\n | { type: \"score\"; score: number; confidence?: number }\n\nexport type ClassifierAnswers = Record<string, ClassifierAnswer>\n\n/** Anything that can answer a classifier request — usually a call to your own proxy route. */\nexport type Classify = (request: ClassifierRequest, signal?: AbortSignal) => Promise<ClassifierAnswers>\n\nconst cache = new Map<string, Promise<ClassifierAnswers>>()\n\n/**\n * A classifier that posts to `endpoint`. Point it at a route on your own server\n * that adds the API key (see `createClassifierHandler` in `stunning-md/server`) —\n * a key placed in browser code is public.\n */\nexport function createClassifier(options: { endpoint: string; headers?: Record<string, string> }): Classify {\n return (request) => {\n // Identical questions share one request, so it is never aborted on behalf of a single caller.\n const key = `${options.endpoint}\\n${JSON.stringify(request)}`\n const hit = cache.get(key)\n if (hit) return hit\n const pending = fetch(options.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...options.headers },\n body: JSON.stringify(request),\n }).then(async (response) => {\n if (!response.ok) throw new Error(`classifier responded ${response.status}`)\n const data = (await response.json()) as { answers?: ClassifierAnswers }\n if (!data.answers) throw new Error(\"classifier response has no answers\")\n return data.answers\n })\n cache.set(key, pending)\n pending.catch(() => cache.delete(key))\n return pending\n }\n}\n\n/** Viz forms that plot figures against each other, as opposed to listing them. */\nconst COMPARATIVE: VizKind[] = [\"bar\", \"line\", \"area\", \"donut\", \"scatter\", \"stats\"]\n\nconst COMPARE_QUESTION: ClassifierQuestion = {\n type: \"noul\",\n criteria: {\n true: \"the numbers are measurements meant to be compared with each other, ranked, or read as a trend\",\n false: \"the numbers are identifiers, codes, settings, prices or specifications that are looked up one at a time\",\n },\n}\n\nconst WHOLE_QUESTION: ClassifierQuestion = {\n type: \"noul\",\n criteria: {\n true: \"the rows are parts that together make up one whole, such as shares of a total or a budget breakdown\",\n false: \"the rows are independent items that do not add up to a meaningful whole\",\n },\n}\n\n/**\n * A compact summary of the document: enough for tone and topic, small enough to\n * be cheap. `prose` should be running text only — code and table cells mislead.\n */\nexport function documentDigest(plan: DocumentPlan, prose: string): string {\n const headings = plan.sections.map((s) => s.titleText).filter(Boolean).slice(0, 12)\n return [\n plan.hero.titleText && `Title: ${plan.hero.titleText}`,\n headings.length && `Sections: ${headings.join(\" | \")}`,\n `Excerpt: ${prose.replace(/\\s+/g, \" \").slice(0, 400)}`,\n ]\n .filter(Boolean)\n .join(\"\\n\")\n}\n\n/** How much probability a keyword match is worth when weighing the classifier's theme options. */\nconst HINT_WEIGHT = 0.25\n\nexport type JudgeOptions = {\n /** Minimum score before the classifier's theme is accepted over the keyword guess. */\n confidence?: number\n /** The theme the document's own keywords point to, if any (see `matchTheme`). */\n themeHint?: PaletteId\n /** Requests in flight at once. Default 3. */\n concurrency?: number\n /** Upper bound on tables sent for a form judgement. */\n maxTables?: number\n signal?: AbortSignal\n /**\n * Called as each answer lands, with the judgements so far and what is still\n * outstanding: `\"theme\"`, `\"hero\"`, or the id of a data block.\n */\n onProgress?: (progress: JudgeProgress) => void\n}\n\nexport type JudgeProgress = { judgements: Judgements; pending: string[] }\n\n/**\n * Asks the classifier the questions structure cannot answer: which theme —\n * colours and typefaces together — suits the content, whether a table's numbers\n * are there to be compared or just looked up, and whether the leading image\n * deserves to be the hero.\n * Questions are asked top-down — theme, hero, then tables in document order —\n * so the top of the page settles first. A failed request simply leaves its\n * judgement unset.\n */\nexport async function judgeDocument(\n plan: DocumentPlan,\n prose: string,\n classify: Classify,\n options: JudgeOptions = {},\n): Promise<Judgements> {\n const threshold = options.confidence ?? 0.4\n const judgements: Judgements = {}\n // A few requests at a time, in order, so small classifier deployments are not\n // flooded by a document full of tables.\n const queue: (() => Promise<void>)[] = []\n const pending = new Set<string>()\n const report = () =>\n options.onProgress?.({ judgements: { ...judgements, viz: judgements.viz && { ...judgements.viz } }, pending: [...pending] })\n const attempt = (key: string, request: ClassifierRequest, apply: (answers: ClassifierAnswers) => void) => {\n pending.add(key)\n queue.push(() =>\n classify(request, options.signal)\n .then(apply, () => undefined)\n .then(() => {\n pending.delete(key)\n if (!options.signal?.aborted) report()\n }),\n )\n }\n\n // One question settles the whole look. Each option spells out the theme's\n // colours and typefaces as well as the content it suits.\n attempt(\n \"theme\",\n {\n state: documentDigest(plan, prose),\n questions: { theme: { type: \"choice\", criteria: Object.fromEntries(themeList.map((t) => [t.id, describeTheme(t)])) } },\n },\n ({ theme }) => {\n if (theme?.type !== \"choice\") return\n // The document's own vocabulary counts as evidence too: it settles close\n // calls, but cannot overturn a classifier that is sure of itself.\n const odds: Record<string, number> = theme.probabilities ?? { [theme.choice]: theme.confidence }\n let best = \"\"\n let bestScore = 0\n for (const id of Object.keys(odds)) {\n const score = odds[id] + (id === options.themeHint ? HINT_WEIGHT : 0)\n if (id in themes && score > bestScore) [best, bestScore] = [id, score]\n }\n if (!best || bestScore < threshold) return\n const chosen = themes[best as PaletteId]\n judgements.theme = { palette: chosen.id, fonts: chosen.fonts, formality: chosen.formality }\n },\n )\n\n const image = plan.hero.image\n if (image) {\n attempt(\n \"hero\",\n {\n state: [\n `Document: ${plan.hero.titleText}`,\n `First image — alt text: \"${image.alt}\", file: ${image.src.split(/[?#]/)[0].split(\"/\").pop()}`,\n image.meta && `size: ${image.meta.width}×${image.meta.height}px`,\n `Text right after it: ${toText(plan.hero.lead.flat()).slice(0, 200)}`,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n questions: {\n hero: {\n type: \"noul\",\n criteria: {\n true: \"the image is a logo, banner, cover photo or key visual that represents the whole document\",\n false: \"the image is a badge, screenshot, diagram, chart or incidental illustration that belongs in the body\",\n },\n },\n },\n },\n ({ hero }) => {\n // Only a clear \"no\" demotes the image; the structural checks already vouched for it.\n if (hero?.type === \"noul\" && hero.noul < 0.2) judgements.heroImageUsable = false\n },\n )\n }\n\n const tables = plan.sections\n .flatMap((section) =>\n section.blocks\n .flatMap((block) => (block.kind === \"cards\" ? block.items.flatMap((item) => item.blocks) : [block]))\n .flatMap((block) => (block.kind === \"data\" ? [{ section, block }] : [])),\n )\n .filter(({ block }) => block.viz.candidates.length > 1)\n .slice(0, options.maxTables ?? 8)\n\n for (const { section, block } of tables) {\n const { columns, rows } = block.table\n const { viz } = block\n if (!COMPARATIVE.includes(viz.kind)) continue\n const lines = [\n columns.map((c) => c.label).join(\" | \"),\n ...rows.slice(0, 12).map((row) => columns.map((c) => row.text[c.key]).join(\" | \")),\n ]\n // Whether numbers are measurements or mere reference values, and whether rows\n // form a whole, depends on what they mean — which the column types cannot say.\n const partsPossible = viz.candidates.includes(\"donut\") && viz.rowIndices.length >= 3\n attempt(\n block.id,\n {\n state: `Section: ${section.titleText || plan.hero.titleText}\\n${lines.join(\"\\n\")}`,\n questions: { compare: COMPARE_QUESTION, ...(partsPossible ? { whole: WHOLE_QUESTION } : {}) },\n },\n ({ compare, whole }) => {\n const set = (kind: VizKind) => ((judgements.viz ??= {})[block.id] = kind)\n if (compare?.type === \"noul\" && compare.noul < 0.12) return set(\"table\")\n if (whole?.type !== \"noul\") return\n if (whole.noul >= 0.9 && viz.kind !== \"donut\") set(\"donut\")\n else if (whole.noul <= 0.12 && viz.kind === \"donut\") set(\"bar\")\n },\n )\n }\n\n const worker = async () => {\n for (let task = queue.shift(); task; task = queue.shift()) {\n if (options.signal?.aborted) return\n await task()\n }\n }\n report()\n // The theme question is by far the heaviest and everything visible depends on\n // it, so it runs alone; the lighter questions then share the connection.\n await queue.shift()?.()\n await Promise.all(Array.from({ length: options.concurrency ?? 3 }, worker))\n return judgements\n}\n","import type { Image, Paragraph, PhrasingContent, Root, RootContent } from \"mdast\"\nimport remarkFrontmatter from \"remark-frontmatter\"\nimport remarkGfm from \"remark-gfm\"\nimport remarkMath from \"remark-math\"\nimport remarkParse from \"remark-parse\"\nimport { unified } from \"unified\"\nimport { parse as parseYaml } from \"yaml\"\n\nexport type Frontmatter = Record<string, unknown>\n\nexport type ParsedMarkdown = {\n root: Root\n frontmatter: Frontmatter\n}\n\nconst processor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).use(remarkFrontmatter, [\"yaml\"])\n\nconst attr = (tag: string, name: string) =>\n new RegExp(`\\\\b${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, \"i\").exec(tag)?.slice(2).find((v) => v != null)\n\nconst decodeEntities = (text: string) =>\n text\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n\n/**\n * Raw HTML is never injected. The useful parts are recovered as markdown nodes —\n * images, line breaks and text — and everything else is dropped.\n */\nfunction htmlToPhrasing(html: string): PhrasingContent[] {\n const out: PhrasingContent[] = []\n const withoutComments = html.replace(/<!--[\\s\\S]*?-->/g, \"\").replace(/<(script|style)[\\s\\S]*?<\\/\\1>/gi, \"\")\n const tokens = withoutComments.split(/(<[^>]+>)/g)\n let href: string | undefined\n for (const token of tokens) {\n if (!token) continue\n if (token.startsWith(\"<\")) {\n if (/^<img\\b/i.test(token)) {\n const src = attr(token, \"src\")\n if (!src) continue\n const image: Image = { type: \"image\", url: src, alt: attr(token, \"alt\") ?? \"\", title: attr(token, \"title\") ?? null }\n out.push(href ? { type: \"link\", url: href, children: [image] } : image)\n } else if (/^<br\\b/i.test(token)) {\n out.push({ type: \"break\" })\n } else if (/^<a\\b/i.test(token)) {\n href = attr(token, \"href\")\n } else if (/^<\\/a/i.test(token)) {\n href = undefined\n }\n continue\n }\n const text = decodeEntities(token).replace(/\\s+/g, \" \")\n if (!text.trim()) continue\n out.push(href ? { type: \"link\", url: href, children: [{ type: \"text\", value: text }] } : { type: \"text\", value: text })\n }\n return out\n}\n\ntype Definitions = Map<string, { url: string; title?: string | null }>\n\nfunction collectDefinitions(nodes: RootContent[], into: Definitions = new Map()): Definitions {\n for (const node of nodes) {\n if (node.type === \"definition\") into.set(node.identifier, { url: node.url, title: node.title })\n else if (\"children\" in node) collectDefinitions(node.children as RootContent[], into)\n }\n return into\n}\n\nfunction cleanPhrasing(children: PhrasingContent[], defs: Definitions): PhrasingContent[] {\n return children.flatMap((child, index): PhrasingContent[] => {\n // \"$60M and $64M\" is money, not maths: as in Pandoc, the dollars must hug the\n // formula and the closing one must not run into a digit.\n if (child.type === \"inlineMath\") {\n const next = children[index + 1]\n const digitAfter = next?.type === \"text\" && /^\\d/.test(next.value)\n if (/^\\s|\\s$/.test(child.value) || digitAfter) return [{ type: \"text\", value: `$${child.value}$` }]\n }\n if (child.type === \"html\") return htmlToPhrasing(child.value)\n // Reference-style links and images are resolved so renderers only meet the direct forms.\n if (child.type === \"imageReference\") {\n const def = defs.get(child.identifier)\n return def ? [{ type: \"image\", url: def.url, alt: child.alt ?? \"\", title: def.title }] : []\n }\n if (child.type === \"linkReference\") {\n const def = defs.get(child.identifier)\n const inner = cleanPhrasing(child.children, defs)\n return def ? [{ type: \"link\", url: def.url, title: def.title, children: inner } as PhrasingContent] : inner\n }\n if (\"children\" in child) {\n return [{ ...child, children: cleanPhrasing(child.children as PhrasingContent[], defs) } as PhrasingContent]\n }\n return [child]\n })\n}\n\nfunction cleanBlocks(nodes: RootContent[], defs: Definitions): RootContent[] {\n return nodes.flatMap((node): RootContent[] => {\n if (node.type === \"html\") {\n // An HTML heading (`<h1 align=\"center\">`) keeps its role.\n const heading = /^\\s*<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>\\s*$/i.exec(node.value)\n if (heading) {\n const children = htmlToPhrasing(heading[2])\n return children.length ? [{ type: \"heading\", depth: Number(heading[1]) as 1, children }] : []\n }\n const children = htmlToPhrasing(node.value)\n return children.length ? [{ type: \"paragraph\", children } satisfies Paragraph] : []\n }\n if (node.type === \"yaml\" || node.type === \"definition\") return []\n if (node.type === \"paragraph\" || node.type === \"heading\") {\n const children = cleanPhrasing(node.children, defs)\n return children.length ? [{ ...node, children }] : []\n }\n if (node.type === \"tableCell\") return [{ ...node, children: cleanPhrasing(node.children, defs) }]\n if (\"children\" in node) {\n return [{ ...node, children: cleanBlocks(node.children as RootContent[], defs) } as RootContent]\n }\n return [node]\n })\n}\n\nexport function parseMarkdown(markdown: string): ParsedMarkdown {\n const tree = processor.parse(markdown) as Root\n let frontmatter: Frontmatter = {}\n const first = tree.children[0]\n if (first?.type === \"yaml\") {\n try {\n const data = parseYaml(first.value)\n if (data && typeof data === \"object\" && !Array.isArray(data)) frontmatter = data as Frontmatter\n } catch {\n // Malformed frontmatter is ignored rather than failing the whole document.\n }\n }\n return { root: { ...tree, children: cleanBlocks(tree.children, collectDefinitions(tree.children)) }, frontmatter }\n}\n","import { createTheme, type ChartTheme, type ChartThemeTokens, type ThemeId } from \"generative-charts\"\nimport type { Appearance, ThemeChoice } from \"../types\"\nimport { checkPalette, contrast, cvdDistance, deltaE, fromOklch, PALETTE_RULES, toOklch } from \"./color\"\nimport { fontPairings, themes, type ChartStyle, type PaletteTokens } from \"./themes\"\n\n/**\n * The fallback series colours: a fixed order of eight hues known to keep\n * neighbours apart for colour-blind readers. Used only if a theme's own\n * palette cannot be built to the same standard.\n */\nconst REFERENCE = {\n light: [\"#2a78d6\", \"#eb6834\", \"#1baf7a\", \"#eda100\", \"#e87ba4\", \"#008300\", \"#4a3aa7\", \"#e34948\"],\n dark: [\"#3987e5\", \"#d95926\", \"#199e70\", \"#c98500\", \"#d55181\", \"#008300\", \"#9085e9\", \"#e66767\"],\n}\n\nconst SLOTS = 8\nconst cache = new Map<string, string[]>()\n\n/**\n * Builds a theme's series colours from its accent. The accent (moved into the\n * legible lightness band if need be) leads; each further colour is the candidate\n * that stays furthest from the ones before it — to readers with and without\n * colour-vision deficiency. Candidates share the accent's intensity, so a muted\n * theme gets muted charts and a vivid one vivid charts. The result is checked\n * against the same rules as the reference palette and only used if it passes.\n */\nexport function seriesColors(accent: string, surface: string, mode: Appearance): string[] {\n const key = `${accent}|${surface}|${mode}`\n const hit = cache.get(key)\n if (hit) return hit\n\n const [lo, hi] = PALETTE_RULES.band[mode]\n const legible = (hex: string) => contrast(hex, surface) >= PALETTE_RULES.contrastMin\n const source = toOklch(accent)\n // A colourless accent (black ink, white chalk) cannot identify a series; start from a neutral blue.\n const hue = source.c < 0.04 ? 255 : source.h\n\n // The lead colour is the nearest thing to the accent that is legible on the\n // surface and saturated enough to read as a colour. Some hues (teal, for one)\n // cannot hold their saturation when dark, so lightness may move, then hue.\n let anchor = \"\"\n let nearest = Infinity\n for (let shift = 0; shift <= 30; shift += 5) {\n for (const h of shift ? [hue - shift, hue + shift] : [hue]) {\n for (let l = lo + 0.01; l <= hi - 0.01; l += 0.01) {\n const hex = fromOklch({ l, c: Math.max(source.c, 0.12), h: (h + 360) % 360 })\n if (toOklch(hex).c < PALETTE_RULES.chromaFloor + 0.005 || !legible(hex)) continue\n const distance = Math.abs(l - source.l) * 2 + shift / 60\n if (distance < nearest) [anchor, nearest] = [hex, distance]\n }\n }\n }\n\n const levels = mode === \"light\" ? [0.47, 0.55, 0.63, 0.7] : [0.52, 0.58, 0.64]\n const intensity = Math.min(0.17, Math.max(0.115, toOklch(anchor || accent).c))\n\n let result: string[] | null = null\n for (const chroma of [intensity, intensity + 0.02, intensity + 0.04, 0.19]) {\n if (!anchor) break\n const candidates: string[] = []\n for (let h = 0; h < 360; h += 10) {\n for (const l of levels) {\n const hex = fromOklch({ l, c: chroma, h })\n if (toOklch(hex).c >= PALETTE_RULES.chromaFloor + 0.005 && legible(hex)) candidates.push(hex)\n }\n }\n const chosen = [anchor]\n while (chosen.length < SLOTS) {\n const previous = chosen[chosen.length - 1]\n let best = \"\"\n let bestScore = -1\n for (const candidate of candidates) {\n if (chosen.includes(candidate)) continue\n // Neighbours matter most (they touch in bars and legends); every other pair must still differ.\n let score = Math.min(cvdDistance(previous, candidate) / PALETTE_RULES.cvdTarget, deltaE(previous, candidate) / PALETTE_RULES.normalFloor)\n for (const other of chosen) {\n score = Math.min(score, cvdDistance(other, candidate) / 5, deltaE(other, candidate) / 12)\n }\n if (score > bestScore) [best, bestScore] = [candidate, score]\n }\n if (!best) break\n chosen.push(best)\n }\n if (chosen.length === SLOTS && checkPalette(chosen, mode, surface).ok) {\n result = chosen\n break\n }\n }\n\n const palette = result ?? REFERENCE[mode]\n cache.set(key, palette)\n return palette\n}\n\n/** The chart library draws three distinct families; a fourth, plain look comes from using none of them. */\nconst FAMILY: Record<ChartStyle, ThemeId | null> = {\n linework: \"mono-editorial\",\n instrument: \"neon-instruments\",\n soft: \"airform\",\n flat: null,\n}\n\nfunction tokens(palette: PaletteTokens, mode: Appearance, style: ChartStyle, formality: number, fontFamily: string): Partial<ChartThemeTokens> {\n const mix = (amount: number) => `color-mix(in oklab, ${palette.fg} ${amount}%, ${palette.bg})`\n const series = seriesColors(palette.accent, palette.bg, mode)\n const lead = series[0]\n // Linework charts are drawn in ink: series alternate between solid and dashed\n // strokes, as in print, so the second tone only needs to mark the legend.\n const ink = [palette.fg, palette.muted, palette.fg, palette.muted, palette.fg, palette.muted]\n const round = Math.round((1 - formality) * 9)\n return {\n background: \"transparent\",\n plotBackground: \"transparent\",\n surface: palette.surface,\n text: palette.fg,\n textMuted: palette.muted,\n grid: mix(10),\n axis: mix(28),\n border: \"transparent\",\n borderStrong: style === \"linework\" ? palette.fg : mix(28),\n zeroLine: style === \"linework\" ? palette.fg : mix(40),\n palette: style === \"linework\" ? ink : series,\n positive: style === \"linework\" ? palette.fg : lead,\n negative: style === \"linework\" ? palette.fg : mix(55),\n lineUnderlay: palette.bg,\n areaStart: style === \"linework\" ? palette.fg : `color-mix(in oklab, ${lead} 38%, transparent)`,\n areaEnd: style === \"linework\" ? palette.bg : `color-mix(in oklab, ${lead} 3%, transparent)`,\n pointFill: palette.bg,\n pointStroke: style === \"linework\" ? palette.fg : lead,\n pointHalo: style === \"linework\" ? palette.bg : `color-mix(in oklab, ${lead} 20%, transparent)`,\n markHighlight: style === \"soft\" ? \"rgba(255,255,255,.5)\" : style === \"linework\" ? palette.bg : \"rgba(255,255,255,.14)\",\n markShadow:\n style === \"soft\"\n ? `0 10px 22px color-mix(in oklab, ${palette.fg} ${mode === \"dark\" ? 0 : 16}%, transparent)`\n : \"0 0 0 transparent\",\n tooltipBackground: palette.fg,\n tooltipText: palette.bg,\n tooltipBorder: \"transparent\",\n focusRing: palette.accent,\n fontFamily,\n radius: 0,\n markRadius: style === \"linework\" ? 0 : style === \"soft\" ? Math.max(4, round) : round,\n shadow: \"none\",\n }\n}\n\n/**\n * The chart theme for a page theme: series colours grown from its accent, its\n * typeface, its corner style, and the drawing family that suits its character.\n */\nexport function chartThemeFor(choice: ThemeChoice): ChartTheme {\n const theme = themes[choice.palette]\n const fonts = fontPairings[choice.fonts]\n const family = FAMILY[theme.chart]\n const font = theme.chart === \"linework\" ? fonts.mono : fonts.body\n return createTheme(family ?? \"airform\", {\n // A family's distinctive rendering is keyed on its id; any other id draws plainly.\n id: family ?? `stunning-${choice.palette}`,\n name: theme.name,\n light: tokens(theme.light, \"light\", theme.chart, choice.formality, font),\n dark: tokens(theme.dark, \"dark\", theme.chart, choice.formality, font),\n })\n}\n","/**\n * Colour maths for chart palettes: OKLab/OKLCH conversion, colour-vision\n * deficiency simulation (Machado, Oliveira & Fernandes 2009, severity 1.0),\n * and the checks a categorical palette has to clear.\n */\n\nexport type Oklch = { l: number; c: number; h: number }\n\nconst toLinear = (c: number) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4)\nconst fromLinear = (c: number) => (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055)\n\nfunction linearRgb(hex: string): [number, number, number] {\n const h = hex.replace(/^#/, \"\")\n return [0, 2, 4].map((i) => toLinear(parseInt(h.slice(i, i + 2), 16) / 255)) as [number, number, number]\n}\n\nfunction oklabFromLinear([r, g, b]: [number, number, number]): [number, number, number] {\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b)\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b)\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b)\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ]\n}\n\nexport function toOklch(hex: string): Oklch {\n const [l, a, b] = oklabFromLinear(linearRgb(hex))\n return { l, c: Math.hypot(a, b), h: ((Math.atan2(b, a) * 180) / Math.PI + 360) % 360 }\n}\n\nfunction linearFromOklch({ l, c, h }: Oklch): [number, number, number] {\n const a = c * Math.cos((h * Math.PI) / 180)\n const b = c * Math.sin((h * Math.PI) / 180)\n const l3 = (l + 0.3963377774 * a + 0.2158037573 * b) ** 3\n const m3 = (l - 0.1055613458 * a - 0.0638541728 * b) ** 3\n const s3 = (l - 0.0894841775 * a - 1.291485548 * b) ** 3\n return [\n 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3,\n -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3,\n -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3,\n ]\n}\n\nconst inGamut = (rgb: number[]) => rgb.every((v) => v >= -0.0005 && v <= 1.0005)\n\n/** OKLCH to hex, giving up chroma — never hue or lightness — to stay inside sRGB. */\nexport function fromOklch(color: Oklch): string {\n let { c } = color\n if (!inGamut(linearFromOklch(color))) {\n let low = 0\n let high = c\n for (let i = 0; i < 18; i++) {\n c = (low + high) / 2\n if (inGamut(linearFromOklch({ ...color, c }))) low = c\n else high = c\n }\n c = low\n }\n const channel = (v: number) =>\n Math.round(Math.min(1, Math.max(0, fromLinear(Math.min(1, Math.max(0, v))))) * 255)\n .toString(16)\n .padStart(2, \"0\")\n return `#${linearFromOklch({ ...color, c }).map(channel).join(\"\")}`\n}\n\nconst luminance = (hex: string) => {\n const [r, g, b] = linearRgb(hex)\n return 0.2126 * r + 0.7152 * g + 0.0722 * b\n}\n\n/** WCAG contrast ratio. */\nexport function contrast(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x)\n return (hi + 0.05) / (lo + 0.05)\n}\n\ntype Vision = \"protan\" | \"deutan\"\n\nconst MACHADO: Record<Vision, number[][]> = {\n protan: [\n [0.152286, 1.052583, -0.204868],\n [0.114503, 0.786281, 0.099216],\n [-0.003882, -0.048116, 1.051998],\n ],\n deutan: [\n [0.367322, 0.860646, -0.227968],\n [0.280085, 0.672501, 0.047413],\n [-0.01182, 0.04294, 0.968881],\n ],\n}\n\nfunction simulate(hex: string, vision: Vision): [number, number, number] {\n const rgb = linearRgb(hex)\n return MACHADO[vision].map((row) => Math.min(1, Math.max(0, row[0] * rgb[0] + row[1] * rgb[1] + row[2] * rgb[2]))) as [number, number, number]\n}\n\n/** Distance in OKLab ×100 — as seen with full colour vision, or with a simulated deficiency. */\nexport function deltaE(a: string, b: string, vision?: Vision): number {\n const x = oklabFromLinear(vision ? simulate(a, vision) : linearRgb(a))\n const y = oklabFromLinear(vision ? simulate(b, vision) : linearRgb(b))\n return 100 * Math.hypot(x[0] - y[0], x[1] - y[1], x[2] - y[2])\n}\n\n/** The smaller of the protan and deutan distances: how far apart two colours stay for red-green deficient readers. */\nexport const cvdDistance = (a: string, b: string) => Math.min(deltaE(a, b, \"protan\"), deltaE(a, b, \"deutan\"))\n\nexport const PALETTE_RULES = {\n /** OKLCH lightness a series colour must sit within, per mode. */\n band: { light: [0.43, 0.77], dark: [0.48, 0.67] } as Record<\"light\" | \"dark\", [number, number]>,\n /** Below this chroma a hue reads as grey. */\n chromaFloor: 0.1,\n /** Neighbouring series, simulated red-green deficiency. */\n cvdTarget: 8,\n /** Neighbouring series, full colour vision. */\n normalFloor: 15,\n /** Each mark against the chart surface. */\n contrastMin: 3,\n}\n\nexport type PaletteReport = {\n ok: boolean\n offBand: string[]\n lowChroma: string[]\n worstCvd: number\n worstNormal: number\n lowContrast: string[]\n}\n\n/**\n * Checks a categorical palette, in order: every colour inside the lightness band\n * and above the chroma floor, and each neighbouring pair distinguishable both\n * with full colour vision and under red-green deficiency. Low contrast against\n * the surface is reported but does not fail — charts always offer a table view.\n */\nexport function checkPalette(palette: string[], mode: \"light\" | \"dark\", surface: string): PaletteReport {\n const [lo, hi] = PALETTE_RULES.band[mode]\n const offBand = palette.filter((c) => toOklch(c).l < lo || toOklch(c).l > hi)\n const lowChroma = palette.filter((c) => toOklch(c).c < PALETTE_RULES.chromaFloor)\n let worstCvd = Infinity\n let worstNormal = Infinity\n for (let i = 1; i < palette.length; i++) {\n worstCvd = Math.min(worstCvd, cvdDistance(palette[i - 1], palette[i]))\n worstNormal = Math.min(worstNormal, deltaE(palette[i - 1], palette[i]))\n }\n const lowContrast = palette.filter((c) => contrast(c, surface) < PALETTE_RULES.contrastMin)\n return {\n ok: !offBand.length && !lowChroma.length && worstCvd >= PALETTE_RULES.cvdTarget && worstNormal >= PALETTE_RULES.normalFloor,\n offBand,\n lowChroma,\n worstCvd,\n worstNormal,\n lowContrast,\n }\n}\n","\"use client\"\n\nimport { createContext, useContext, type CSSProperties } from \"react\"\nimport type { ChartTheme } from \"generative-charts\"\nimport type { Appearance, SectionLayout, ThemeChoice, VizKind } from \"../types\"\n\nexport type StunningContext = {\n /** Maps a URL from the markdown to one the browser can load. */\n resolveUrl: (url: string) => string\n appearance: Appearance\n theme: ThemeChoice\n chartTheme: ChartTheme\n /**\n * Popovers, menus and sheets render outside the themed root, so they are\n * handed the theme directly.\n */\n portal: { className: string; style: CSSProperties }\n /** Whether layout and form pickers are shown. */\n controls: boolean\n setLayout: (sectionId: string, layout: SectionLayout) => void\n setViz: (blockId: string, kind: VizKind) => void\n}\n\nconst Context = createContext<StunningContext | null>(null)\n\nexport const StunningProvider = Context.Provider\n\nexport function useStunning(): StunningContext {\n const value = useContext(Context)\n if (!value) throw new Error(\"stunning-md components must be rendered inside <StunningMarkdown>\")\n return value\n}\n","\"use client\"\n\nimport katex from \"katex\"\nimport type { PhrasingContent, RootContent } from \"mdast\"\nimport { Fragment, type ReactNode } from \"react\"\nimport { CodeBlock } from \"./code-block\"\nimport { useStunning } from \"./context\"\n\nconst SAFE_URL = /^(https?:|mailto:|tel:|#|\\/|\\.{0,2}\\/|blob:|data:image\\/)/i\n\n/** Links and images only ever point at ordinary web, mail or in-page targets. */\nexport function safeUrl(url: string): string | undefined {\n const trimmed = url.trim()\n if (SAFE_URL.test(trimmed) || !/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return trimmed\n return undefined\n}\n\nexport function MathView({ value, display }: { value: string; display?: boolean }) {\n const html = katex.renderToString(value, { displayMode: display, throwOnError: false, output: \"htmlAndMathml\" })\n return display ? (\n <div className=\"smd-math-block\" dangerouslySetInnerHTML={{ __html: html }} />\n ) : (\n <span dangerouslySetInnerHTML={{ __html: html }} />\n )\n}\n\nexport function Inline({ nodes }: { nodes: PhrasingContent[] }) {\n const { resolveUrl } = useStunning()\n const render = (node: PhrasingContent, key: number): ReactNode => {\n switch (node.type) {\n case \"text\":\n return node.value\n case \"emphasis\":\n return <em key={key}>{node.children.map(render)}</em>\n case \"strong\":\n return <strong key={key}>{node.children.map(render)}</strong>\n case \"delete\":\n return <del key={key}>{node.children.map(render)}</del>\n case \"inlineCode\":\n return <code key={key}>{node.value}</code>\n case \"break\":\n return <br key={key} />\n case \"link\": {\n const href = safeUrl(node.url)\n const external = !!href && /^https?:/i.test(href)\n return (\n <a key={key} href={href} title={node.title ?? undefined} {...(external ? { target: \"_blank\", rel: \"noreferrer noopener\" } : {})}>\n {node.children.map(render)}\n </a>\n )\n }\n case \"image\": {\n const src = safeUrl(resolveUrl(node.url))\n // eslint-disable-next-line @next/next/no-img-element\n return src ? <img key={key} src={src} alt={node.alt ?? \"\"} title={node.title ?? undefined} loading=\"lazy\" className=\"smd-inline-image\" /> : null\n }\n case \"inlineMath\":\n return <MathView key={key} value={node.value} />\n case \"footnoteReference\":\n return (\n <sup key={key}>\n <a href={`#fn-${node.identifier}`} id={`fnref-${node.identifier}`} aria-label={`Footnote ${node.label ?? node.identifier}`}>\n {node.label ?? node.identifier}\n </a>\n </sup>\n )\n default:\n return null\n }\n }\n return <>{nodes.map(render)}</>\n}\n\n/** Renders ordinary markdown block nodes — the content inside list items, quotes and cards. */\nexport function Flow({ nodes }: { nodes: RootContent[] }) {\n return (\n <>\n {nodes.map((node, index) => (\n <FlowNode key={index} node={node} />\n ))}\n </>\n )\n}\n\nexport function FlowNode({ node }: { node: RootContent }) {\n switch (node.type) {\n case \"paragraph\":\n return (\n <p>\n <Inline nodes={node.children} />\n </p>\n )\n case \"heading\": {\n const Tag = `h${Math.min(6, node.depth + 1)}` as \"h3\"\n return (\n <Tag className=\"smd-subheading\">\n <Inline nodes={node.children} />\n </Tag>\n )\n }\n case \"list\": {\n const Tag = node.ordered ? \"ol\" : \"ul\"\n const task = node.children.some((item) => item.checked != null)\n return (\n <Tag start={node.ordered ? (node.start ?? undefined) : undefined} className={task ? \"smd-tasks\" : undefined}>\n {node.children.map((item, index) => (\n <li key={index} data-checked={item.checked ?? undefined}>\n {item.checked != null && (\n <input type=\"checkbox\" checked={item.checked} readOnly disabled aria-label={item.checked ? \"Done\" : \"Not done\"} />\n )}\n <ItemBody nodes={item.children} />\n </li>\n ))}\n </Tag>\n )\n }\n case \"blockquote\":\n return (\n <blockquote>\n <Flow nodes={node.children} />\n </blockquote>\n )\n case \"code\":\n return <CodeBlock lang={node.lang ?? undefined} value={node.value} />\n case \"math\":\n return <MathView value={node.value} display />\n case \"thematicBreak\":\n return <hr />\n case \"footnoteDefinition\":\n return (\n <div className=\"smd-footnote\" id={`fn-${node.identifier}`}>\n <a href={`#fnref-${node.identifier}`} aria-label=\"Back to reference\">\n {node.label ?? node.identifier}\n </a>\n <div>\n <Flow nodes={node.children} />\n </div>\n </div>\n )\n case \"table\":\n return (\n <div className=\"smd-table-scroll\">\n <table>\n <tbody>\n {node.children.map((row, r) => (\n <tr key={r}>\n {row.children.map((cell, c) => {\n const Cell = r === 0 ? \"th\" : \"td\"\n return (\n <Cell key={c}>\n <Inline nodes={cell.children} />\n </Cell>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n default:\n return null\n }\n}\n\n/** A list item whose only content is one paragraph renders tight, without the paragraph wrapper. */\nexport function ItemBody({ nodes }: { nodes: RootContent[] }) {\n return (\n <>\n {nodes.map((node, index) =>\n node.type === \"paragraph\" ? (\n <Fragment key={index}>\n {index > 0 && <span className=\"smd-item-gap\" />}\n <Inline nodes={node.children} />\n </Fragment>\n ) : (\n <FlowNode key={index} node={node} />\n ),\n )}\n </>\n )\n}\n","\"use client\"\n\nimport type { Element, ElementContent, Root, RootContent } from \"hast\"\nimport { common, createLowlight } from \"lowlight\"\nimport { CheckIcon, CopyIcon } from \"lucide-react\"\nimport { useMemo, useState, type ReactNode } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\n\nconst lowlight = createLowlight(common)\n\nconst ALIASES: Record<string, string> = { sh: \"bash\", shell: \"bash\", zsh: \"bash\", console: \"bash\", yml: \"yaml\", tsx: \"typescript\", jsx: \"javascript\", html: \"xml\", svg: \"xml\", vue: \"xml\" }\n\nfunction toReact(node: RootContent | ElementContent, key: number): ReactNode {\n if (node.type === \"text\") return node.value\n if (node.type !== \"element\") return null\n const element = node as Element\n const className = element.properties?.className\n return (\n <span key={key} className={Array.isArray(className) ? className.join(\" \") : undefined}>\n {element.children.map(toReact)}\n </span>\n )\n}\n\nexport function CopyButton({ text, label, className }: { text: string | (() => string); label: string; className?: string }) {\n const [copied, setCopied] = useState(false)\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(typeof text === \"function\" ? text() : text)\n setCopied(true)\n setTimeout(() => setCopied(false), 1600)\n } catch {\n // Clipboard access can be refused; the content stays selectable.\n }\n }\n return (\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={copy} aria-label={copied ? \"Copied\" : label} title={label} className={cn(\"text-muted-foreground\", className)}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n <span className=\"sr-only\" role=\"status\">\n {copied ? \"Copied\" : \"\"}\n </span>\n </Button>\n )\n}\n\nexport function CodeBlock({ lang, value }: { lang?: string; value: string }) {\n const language = lang ? (ALIASES[lang.toLowerCase()] ?? lang.toLowerCase()) : undefined\n const tree = useMemo<Root | null>(() => {\n if (!language || !lowlight.registered(language)) return null\n try {\n return lowlight.highlight(language, value)\n } catch {\n return null\n }\n }, [language, value])\n\n return (\n <figure className=\"smd-code not-prose\">\n <figcaption>\n <span>{lang ?? \"text\"}</span>\n <CopyButton text={value} label=\"Copy code\" />\n </figcaption>\n <pre tabIndex={0}>\n <code className=\"hljs\">{tree ? tree.children.map(toReact) : value}</code>\n </pre>\n </figure>\n )\n}\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselApi } from \"@/components/ui/carousel\"\nimport { Dialog, DialogContent, DialogTitle } from \"@/components/ui/dialog\"\nimport { cn } from \"@/lib/utils\"\nimport type { ImageRef, MediaVariant } from \"../types\"\nimport { useStunning } from \"./context\"\nimport { safeUrl } from \"./flow\"\n\n/** Alt text doubles as a caption only when it reads like one. */\nexport function captionOf(image: ImageRef): string | undefined {\n if (image.title) return image.title\n const alt = image.alt.trim()\n return alt.split(/\\s+/).length >= 3 && !/\\.(png|jpe?g|gif|webp|svg)$/i.test(alt) ? alt : undefined\n}\n\nexport function Picture({\n image,\n className,\n eager,\n sizes,\n}: {\n image: ImageRef\n className?: string\n eager?: boolean\n sizes?: string\n}) {\n const { resolveUrl } = useStunning()\n const [broken, setBroken] = useState(false)\n const src = safeUrl(resolveUrl(image.src))\n if (!src || broken) {\n return image.alt ? <span className={cn(\"smd-image-missing\", className)}>{image.alt}</span> : null\n }\n return (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={src}\n alt={image.alt}\n width={image.meta?.width}\n height={image.meta?.height}\n loading={eager ? \"eager\" : \"lazy\"}\n decoding=\"async\"\n sizes={sizes}\n onError={() => setBroken(true)}\n className={className}\n />\n )\n}\n\nfunction Lightbox({ image, onClose }: { image: ImageRef | null; onClose: () => void }) {\n const { portal } = useStunning()\n return (\n <Dialog open={!!image} onOpenChange={(open) => !open && onClose()}>\n <DialogContent\n style={portal.style}\n className={cn(portal.className, \"w-auto max-w-[96vw] gap-2 p-2 sm:max-w-[min(96vw,1500px)]\")}\n >\n <DialogTitle className=\"sr-only\">{image?.alt || \"Image\"}</DialogTitle>\n {image && <Picture image={image} eager className=\"max-h-[86svh] w-auto max-w-full rounded-md object-contain\" />}\n {image && captionOf(image) && <p className=\"px-2 pb-1 text-center text-sm text-muted-foreground\">{captionOf(image)}</p>}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction Zoomable({ image, onOpen, className, children }: { image: ImageRef; onOpen: (image: ImageRef) => void; className?: string; children: React.ReactNode }) {\n const href = image.href && safeUrl(image.href)\n if (href) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer noopener\" className={className}>\n {children}\n </a>\n )\n }\n return (\n <button type=\"button\" onClick={() => onOpen(image)} aria-label={`Enlarge image${image.alt ? `: ${image.alt}` : \"\"}`} className={cn(\"cursor-zoom-in\", className)}>\n {children}\n </button>\n )\n}\n\nfunction Slideshow({ images, onOpen }: { images: ImageRef[]; onOpen: (image: ImageRef) => void }) {\n const [api, setApi] = useState<CarouselApi>()\n const [index, setIndex] = useState(0)\n useEffect(() => {\n if (!api) return\n const update = () => setIndex(api.selectedScrollSnap())\n update()\n api.on(\"select\", update)\n return () => {\n api.off(\"select\", update)\n }\n }, [api])\n\n // Photographs fill the frame; small or tall images are shown whole.\n const landscape = images.filter((i) => i.meta && i.meta.width / i.meta.height >= 1.2 && i.meta.width >= 800).length\n const cover = landscape >= images.length * 0.6\n const caption = captionOf(images[index])\n\n return (\n <figure className=\"smd-media\">\n <Carousel setApi={setApi} opts={{ loop: images.length > 2 }} aria-label={`Slideshow of ${images.length} images`}>\n <CarouselContent className=\"ml-0\">\n {images.map((image, i) => (\n <CarouselItem key={i} className=\"pl-0\" aria-label={`${i + 1} of ${images.length}`}>\n <Zoomable image={image} onOpen={onOpen} className=\"block w-full\">\n <span className=\"smd-frame block aspect-[4/3] w-full overflow-hidden sm:aspect-[16/9]\">\n <Picture image={image} eager={i === 0} className={cn(\"size-full\", cover && image.meta && image.meta.width >= 800 ? \"object-cover\" : \"object-contain p-4\")} />\n </span>\n </Zoomable>\n </CarouselItem>\n ))}\n </CarouselContent>\n <CarouselPrevious className=\"left-3 bg-background/85 backdrop-blur\" />\n <CarouselNext className=\"right-3 bg-background/85 backdrop-blur\" />\n </Carousel>\n <figcaption className=\"flex items-start justify-between gap-4\">\n <span aria-live=\"polite\">{caption}</span>\n <span className=\"flex shrink-0 items-center gap-3\">\n <span className=\"flex gap-1.5\" role=\"tablist\" aria-label=\"Choose slide\">\n {images.length <= 12 &&\n images.map((_, i) => (\n <button\n key={i}\n type=\"button\"\n role=\"tab\"\n aria-selected={i === index}\n aria-label={`Slide ${i + 1}`}\n onClick={() => api?.scrollTo(i)}\n className={cn(\"h-1.5 rounded-full transition-all\", i === index ? \"w-5 bg-primary\" : \"w-1.5 bg-foreground/25 hover:bg-foreground/50\")}\n />\n ))}\n </span>\n <span className=\"tabular-nums\">\n {index + 1} / {images.length}\n </span>\n </span>\n </figcaption>\n </figure>\n )\n}\n\nexport function Media({ images, variant }: { images: ImageRef[]; variant: MediaVariant }) {\n const [open, setOpen] = useState<ImageRef | null>(null)\n let body: React.ReactNode\n\n if (variant === \"slideshow\") {\n body = <Slideshow images={images} onOpen={setOpen} />\n } else if (variant === \"pair\") {\n body = (\n <div className=\"smd-media grid gap-4 sm:grid-cols-2\">\n {images.map((image, i) => (\n <figure key={i}>\n <Zoomable image={image} onOpen={setOpen} className=\"block w-full\">\n <span className=\"smd-frame block aspect-[4/3] overflow-hidden\">\n <Picture image={image} className=\"size-full object-cover\" />\n </span>\n </Zoomable>\n {captionOf(image) && <figcaption>{captionOf(image)}</figcaption>}\n </figure>\n ))}\n </div>\n )\n } else {\n const image = images[0]\n const meta = image.meta\n // Small images keep their natural size instead of being blown up.\n const small = !!meta && meta.width < 560\n const tall = !!meta && meta.height > meta.width * 1.15\n body = (\n <figure className={cn(\"smd-media\", (small || tall) && \"mx-auto w-fit\")}>\n <Zoomable image={image} onOpen={setOpen} className=\"block\">\n <Picture\n image={image}\n className={cn(\"smd-frame h-auto max-w-full\", !small && !tall && \"w-full\", tall && \"max-h-[80svh] w-auto\")}\n />\n </Zoomable>\n {captionOf(image) && <figcaption>{captionOf(image)}</figcaption>}\n </figure>\n )\n }\n\n return (\n <>\n {body}\n <Lightbox image={open} onClose={() => setOpen(null)} />\n </>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\ntype CarouselProps = {\n opts?: CarouselOptions\n plugins?: CarouselPlugin\n orientation?: \"horizontal\" | \"vertical\"\n setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\n api: ReturnType<typeof useEmblaCarousel>[1]\n scrollPrev: () => void\n scrollNext: () => void\n canScrollPrev: boolean\n canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext)\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\")\n }\n\n return context\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n )\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\n const [canScrollNext, setCanScrollNext] = React.useState(false)\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return\n setCanScrollPrev(api.canScrollPrev())\n setCanScrollNext(api.canScrollNext())\n }, [])\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev()\n }, [api])\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext()\n }, [api])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n scrollPrev()\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault()\n scrollNext()\n }\n },\n [scrollPrev, scrollNext]\n )\n\n React.useEffect(() => {\n if (!api || !setApi) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing with the carousel engine once it exists\n onSelect(api)\n api.on(\"reInit\", onSelect)\n api.on(\"select\", onSelect)\n\n return () => {\n api?.off(\"select\", onSelect)\n }\n }, [api, onSelect])\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute touch-manipulation rounded-full\",\n orientation === \"horizontal\"\n ? \"inset-y-0 -left-12 my-auto\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ChevronLeftIcon />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute touch-manipulation rounded-full\",\n orientation === \"horizontal\"\n ? \"inset-y-0 -right-12 my-auto\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ChevronRightIcon />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n useCarousel,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\nimport { cn } from \"@/lib/utils\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n \"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close render={<Button variant=\"outline\" />}>\n Close\n </DialogPrimitive.Close>\n )}\n </div>\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\n \"font-heading text-base leading-none font-medium\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n \"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n","\"use client\"\n\nimport type { DocumentPlan } from \"../types\"\nimport { useStunning } from \"./context\"\nimport { Inline, safeUrl } from \"./flow\"\nimport { Picture } from \"./media\"\n\nexport function HeroView({ plan }: { plan: DocumentPlan }) {\n const { resolveUrl } = useStunning()\n const { hero } = plan\n if (!hero.titleText && !hero.lead.length && !hero.image) return null\n\n const sections = plan.sections.filter((s) => s.titleText).length\n const meta = [plan.words >= 150 && `${plan.readingTime} min read`, sections >= 3 && `${sections} sections`].filter(Boolean).join(\" · \")\n\n const badges = hero.badges.length > 0 && (\n <p className=\"smd-badges\">\n {hero.badges.map((badge, index) => {\n const src = safeUrl(resolveUrl(badge.src))\n if (!src) return null\n // eslint-disable-next-line @next/next/no-img-element\n const image = <img src={src} alt={badge.alt} loading=\"lazy\" />\n const href = badge.href && safeUrl(badge.href)\n return href ? (\n <a key={index} href={href} target=\"_blank\" rel=\"noreferrer noopener\">\n {image}\n </a>\n ) : (\n <span key={index}>{image}</span>\n )\n })}\n </p>\n )\n\n const text = (\n <div className=\"smd-hero-text\">\n {hero.variant === \"logo\" && hero.image && <Picture image={hero.image} eager className=\"smd-hero-logo\" />}\n {hero.eyebrow && <p className=\"smd-eyebrow\">{hero.eyebrow}</p>}\n {hero.titleText && (\n <h1 className=\"smd-display\">\n <Inline nodes={hero.title} />\n </h1>\n )}\n {hero.lead.map((paragraph, index) => (\n <p key={index} className=\"smd-lead\">\n <Inline nodes={paragraph} />\n </p>\n ))}\n {meta && <p className=\"smd-hero-meta\">{meta}</p>}\n {badges}\n </div>\n )\n\n return (\n <header className=\"smd-hero\" data-variant={hero.variant} id=\"top\">\n {hero.variant === \"banner\" && hero.image && (\n <>\n <Picture image={hero.image} eager className=\"smd-cover\" />\n <div className=\"smd-scrim\" aria-hidden />\n </>\n )}\n <div className=\"smd-container smd-hero-inner\">\n {text}\n {hero.variant === \"figure\" && hero.image && (\n <div className=\"smd-hero-figure\">\n <Picture image={hero.image} eager className=\"smd-frame h-auto w-full\" />\n </div>\n )}\n </div>\n </header>\n )\n}\n","\"use client\"\n\nimport { CheckIcon, CodeIcon, FileTextIcon, MenuIcon, MoonIcon, PaletteIcon, PanelRightCloseIcon, PanelRightOpenIcon, SparklesIcon, SunIcon } from \"lucide-react\"\nimport { useEffect, useRef, useState } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from \"@/components/ui/sheet\"\nimport { cn } from \"@/lib/utils\"\nimport { themeList } from \"../theme/themes\"\nimport type { Appearance, DocumentPlan, PaletteId, TocEntry } from \"../types\"\nimport { useStunning } from \"./context\"\n\nfunction scrollToId(id: string) {\n const target = document.getElementById(id)\n if (!target) return\n const reduce = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n target.scrollIntoView({ behavior: reduce ? \"auto\" : \"smooth\", block: \"start\" })\n // Move focus with the viewport so keyboard and screen-reader users land there too.\n target.setAttribute(\"tabindex\", \"-1\")\n target.focus({ preventScroll: true })\n history.replaceState(null, \"\", `#${id}`)\n}\n\n/** Tracks which section is being read and how far through the document the reader is. */\nexport function useReadingPosition(ids: string[], root: React.RefObject<HTMLElement | null>) {\n const [active, setActive] = useState<string | null>(null)\n const bar = useRef<HTMLDivElement>(null)\n const key = ids.join(\"|\")\n\n useEffect(() => {\n let frame = 0\n const update = () => {\n frame = 0\n const el = root.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n const span = rect.height - window.innerHeight\n const progress = span > 0 ? Math.min(1, Math.max(0, -rect.top / span)) : 0\n if (bar.current) bar.current.style.transform = `scaleX(${progress})`\n let current: string | null = null\n for (const id of key.split(\"|\")) {\n const node = id && document.getElementById(id)\n if (node && node.getBoundingClientRect().top <= window.innerHeight * 0.3) current = id\n }\n setActive(current)\n }\n const onScroll = () => {\n if (!frame) frame = requestAnimationFrame(update)\n }\n update()\n window.addEventListener(\"scroll\", onScroll, { passive: true })\n window.addEventListener(\"resize\", onScroll)\n return () => {\n cancelAnimationFrame(frame)\n window.removeEventListener(\"scroll\", onScroll)\n window.removeEventListener(\"resize\", onScroll)\n }\n }, [key, root])\n\n return { active, bar }\n}\n\nexport type ReadingPosition = ReturnType<typeof useReadingPosition>\n\n/** How the contents are offered: beside the page when there is room, otherwise in a sheet. */\nexport type SidebarState = { available: boolean; open: boolean; toggle: () => void; id: string }\n\nfunction TocList({ entries, active, onNavigate }: { entries: TocEntry[]; active: string | null; onNavigate: (id: string) => void }) {\n return (\n <ol className=\"smd-toc-list\">\n {entries.map((entry) => (\n <li key={entry.id} data-depth={entry.depth}>\n <a\n href={`#${entry.id}`}\n aria-current={entry.id === active ? \"location\" : undefined}\n onClick={(event) => {\n event.preventDefault()\n onNavigate(entry.id)\n }}\n >\n {entry.text}\n </a>\n </li>\n ))}\n </ol>\n )\n}\n\n/** The contents, pinned beside the document on wide screens. */\nexport function TocSidebar({ plan, active, id }: { plan: DocumentPlan; active: string | null; id: string }) {\n const scroller = useRef<HTMLElement>(null)\n\n // Keep the current entry in view as the reader moves through a long document.\n useEffect(() => {\n const box = scroller.current\n const current = box?.querySelector<HTMLElement>(\"[aria-current]\")\n if (!box || !current) return\n const top = current.offsetTop - box.offsetTop\n if (top < box.scrollTop + 48) box.scrollTop = Math.max(0, top - 48)\n else if (top + current.offsetHeight > box.scrollTop + box.clientHeight - 48) box.scrollTop = top + current.offsetHeight - box.clientHeight + 48\n }, [active])\n\n return (\n <nav ref={scroller} id={id} className=\"smd-sidebar\" aria-label=\"Contents\">\n <p className=\"smd-sidebar-title\">Contents</p>\n <p className=\"smd-sidebar-meta\">\n {plan.readingTime} min read · {plan.sections.filter((s) => s.titleText).length} sections\n </p>\n <TocList entries={plan.toc} active={active} onNavigate={scrollToId} />\n </nav>\n )\n}\n\n/** How the document is shown: its raw text, an ordinary rendering, or the designed page. */\nexport type View = \"source\" | \"plain\" | \"designed\"\n\nconst VIEWS: { id: View; label: string; icon: typeof CodeIcon }[] = [\n { id: \"source\", label: \"Markdown text\", icon: CodeIcon },\n { id: \"plain\", label: \"Plain rendering\", icon: FileTextIcon },\n { id: \"designed\", label: \"Stunning\", icon: SparklesIcon },\n]\n\n/** A three-position switch between the views, with a thumb that slides to the chosen one. */\nfunction ViewSwitch({ view, onView }: { view: View; onView: (view: View) => void }) {\n const group = useRef<HTMLDivElement>(null)\n const index = VIEWS.findIndex((item) => item.id === view)\n const move = (step: number) => {\n const next = Math.min(VIEWS.length - 1, Math.max(0, index + step))\n onView(VIEWS[next].id)\n group.current?.querySelectorAll(\"button\")[next]?.focus()\n }\n return (\n <div ref={group} role=\"radiogroup\" aria-label=\"View\" className=\"smd-view-switch\" style={{ \"--smd-view-index\": index } as React.CSSProperties}>\n <span className=\"smd-view-thumb\" aria-hidden />\n {VIEWS.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={item.id === view}\n aria-label={item.label}\n title={item.label}\n tabIndex={item.id === view ? 0 : -1}\n onClick={() => onView(item.id)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") move(1)\n else if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") move(-1)\n else return\n event.preventDefault()\n }}\n >\n <item.icon aria-hidden />\n </button>\n ))}\n </div>\n )\n}\n\nexport function Nav({\n plan,\n root,\n position,\n sidebar,\n view,\n onView,\n onPalette,\n onAppearance,\n}: {\n plan: DocumentPlan\n root: React.RefObject<HTMLElement | null>\n position: ReadingPosition\n sidebar: SidebarState\n view: View\n onView: (view: View) => void\n onPalette: (palette: PaletteId) => void\n onAppearance: (appearance: Appearance) => void\n}) {\n const { portal, theme, appearance, controls } = useStunning()\n const [open, setOpen] = useState(false)\n const { active, bar } = position\n // The raw text has no headings to jump to.\n const hasToc = plan.showToc && view !== \"source\"\n const activeTop = plan.toc.find((entry) => entry.id === active)\n const current = activeTop ? (plan.toc.slice(0, plan.toc.indexOf(activeTop) + 1).findLast((e) => e.depth === 0) ?? activeTop) : null\n\n if (!plan.showToc && !controls) return null\n\n return (\n <nav className=\"smd-nav\" aria-label=\"Document\" data-sidebar={(sidebar.available && sidebar.open) || undefined}>\n <div className=\"smd-container flex h-12 items-center gap-2\">\n {plan.hero.titleText && (\n <a\n href=\"#top\"\n onClick={(event) => {\n event.preventDefault()\n window.scrollTo({ top: (root.current?.getBoundingClientRect().top ?? 0) + window.scrollY, behavior: \"smooth\" })\n }}\n className=\"smd-nav-title min-w-0 truncate\"\n >\n {plan.hero.titleText}\n </a>\n )}\n {current && (\n <span className={cn(\"min-w-0 truncate text-sm text-muted-foreground\", plan.hero.titleText && \"hidden sm:inline\")} aria-hidden>\n {plan.hero.titleText && <span className=\"mx-1.5 opacity-50\">/</span>}\n {current.text}\n </span>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-0.5\">\n {controls && <ViewSwitch view={view} onView={onView} />}\n {controls && (\n <DropdownMenu>\n <DropdownMenuTrigger render={<Button variant=\"ghost\" size=\"icon\" aria-label=\"Choose theme\" title=\"Theme\" />}>\n <PaletteIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"w-52\")}>\n <DropdownMenuGroup>\n <DropdownMenuLabel>Theme</DropdownMenuLabel>\n {themeList.map((item) => (\n <DropdownMenuItem key={item.id} onClick={() => onPalette(item.id)}>\n <span\n aria-hidden\n className=\"size-4 shrink-0 rounded-full ring-1 ring-foreground/15\"\n style={{ background: `linear-gradient(135deg, ${item[appearance].bg} 50%, ${item[appearance].accent} 50%)` }}\n />\n {item.name}\n {item.id === theme.palette && <CheckIcon className=\"ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => onAppearance(appearance === \"dark\" ? \"light\" : \"dark\")}\n aria-label={appearance === \"dark\" ? \"Switch to light mode\" : \"Switch to dark mode\"}\n title={appearance === \"dark\" ? \"Light mode\" : \"Dark mode\"}\n >\n {appearance === \"dark\" ? <SunIcon /> : <MoonIcon />}\n </Button>\n {sidebar.available && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 px-2.5\"\n onClick={sidebar.toggle}\n aria-expanded={sidebar.open}\n aria-controls={sidebar.id}\n aria-label={sidebar.open ? \"Hide table of contents\" : \"Show table of contents\"}\n >\n {sidebar.open ? <PanelRightCloseIcon /> : <PanelRightOpenIcon />}\n <span>Contents</span>\n </Button>\n )}\n {hasToc && !sidebar.available && (\n <Sheet open={open} onOpenChange={setOpen}>\n <SheetTrigger render={<Button variant=\"ghost\" size=\"sm\" className=\"h-8 gap-1.5 px-2.5\" aria-label=\"Open table of contents\" />}>\n <MenuIcon />\n <span className=\"hidden sm:inline\">Contents</span>\n </SheetTrigger>\n <SheetContent style={portal.style} className={cn(portal.className, \"smd-toc gap-0\")}>\n <SheetHeader>\n <SheetTitle>Contents</SheetTitle>\n <SheetDescription>\n {plan.readingTime} min read · {plan.sections.filter((s) => s.titleText).length} sections\n </SheetDescription>\n </SheetHeader>\n <TocList\n entries={plan.toc}\n active={active}\n onNavigate={(id) => {\n setOpen(false)\n // Wait for the sheet to release its scroll lock.\n setTimeout(() => scrollToId(id), 60)\n }}\n />\n </SheetContent>\n </Sheet>\n )}\n </div>\n </div>\n <div className=\"smd-progress\" aria-hidden>\n <div ref={bar} />\n </div>\n </nav>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\"z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\"w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n inset,\n ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n inset,\n ...props\n}: MenuPrimitive.RadioItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\nimport { cn } from \"@/lib/utils\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/10 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\n \"fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-3 right-3\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-0.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\n \"font-heading text-base font-medium text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\"\n\nimport type { Root, Table } from \"mdast\"\nimport { toText } from \"../analyze/text\"\nimport type { TocEntry } from \"../types\"\nimport { CopyButton } from \"./code-block\"\nimport { FlowNode, Inline } from \"./flow\"\n\nfunction PlainTable({ node }: { node: Table }) {\n const [head, ...body] = node.children\n const align = (index: number) => node.align?.[index] ?? undefined\n return (\n <div className=\"smd-plain-table\">\n <table>\n {head && (\n <thead>\n <tr>\n {head.children.map((cell, c) => (\n <th key={c} scope=\"col\" style={{ textAlign: align(c) }}>\n <Inline nodes={cell.children} />\n </th>\n ))}\n </tr>\n </thead>\n )}\n <tbody>\n {body.map((row, r) => (\n <tr key={r}>\n {row.children.map((cell, c) => (\n <td key={c} style={{ textAlign: align(c) }}>\n <Inline nodes={cell.children} />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * The document as an ordinary markdown renderer would show it: one column,\n * headings as written, tables as tables, images where they fall. Headings keep\n * the ids used by the contents list, so navigation works in either view.\n */\nexport function PlainDocument({ root, toc }: { root: Root; toc: TocEntry[] }) {\n const remaining = [...toc]\n return (\n <main className=\"smd-plain\">\n {root.children.map((node, index) => {\n if (node.type === \"heading\") {\n const text = toText(node).trim()\n const match = remaining.findIndex((entry) => entry.text.trim() === text)\n const id = match >= 0 ? remaining.splice(0, match + 1)[match].id : undefined\n const Tag = `h${node.depth}` as \"h1\"\n return (\n <Tag key={index} id={id}>\n <Inline nodes={node.children} />\n </Tag>\n )\n }\n if (node.type === \"table\") return <PlainTable key={index} node={node} />\n return <FlowNode key={index} node={node} />\n })}\n </main>\n )\n}\n\n/**\n * The markdown exactly as written — and, when `onChange` is given, editable in\n * place. The field grows with its content: a hidden copy of the text sizes the\n * box and the textarea is laid over it.\n */\nexport function SourceView({ value, onChange }: { value: string; onChange?: (value: string) => void }) {\n return (\n <main className=\"smd-source\">\n <div className=\"smd-source-tools\">\n {onChange && <p>Edit the text, then switch view to see it rendered.</p>}\n <CopyButton text={() => value} label=\"Copy markdown\" />\n </div>\n {onChange ? (\n <div className=\"smd-source-edit\" data-value={value}>\n <textarea\n value={value}\n onChange={(event) => onChange(event.target.value)}\n aria-label=\"Edit markdown\"\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n />\n </div>\n ) : (\n <pre tabIndex={0}>{value}</pre>\n )}\n </main>\n )\n}\n","\"use client\"\n\nimport { CheckIcon, EllipsisIcon } from \"lucide-react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { cn } from \"@/lib/utils\"\nimport type { Section, SectionLayout } from \"../types\"\nimport { Blocks } from \"./blocks\"\nimport { useStunning } from \"./context\"\nimport { Inline } from \"./flow\"\nimport { captionOf, Picture } from \"./media\"\n\nexport const LAYOUT_LABEL: Record<SectionLayout, { name: string; hint: string }> = {\n prose: { name: \"Article\", hint: \"Heading beside a reading column\" },\n statement: { name: \"Statement\", hint: \"Large, centred, room to breathe\" },\n split: { name: \"Side by side\", hint: \"Text next to the image\" },\n fullbleed: { name: \"Full-screen image\", hint: \"Text over the image\" },\n cards: { name: \"Cards\", hint: \"Sub-sections as a grid\" },\n showcase: { name: \"Showcase\", hint: \"Images lead, text follows\" },\n quote: { name: \"Quotation\", hint: \"One highlighted quote\" },\n}\n\nfunction LayoutMenu({ section }: { section: Section }) {\n const { portal, setLayout } = useStunning()\n return (\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"smd-section-menu\"\n aria-label={`Change layout of ${section.titleText || \"this section\"}`}\n title=\"Change layout\"\n />\n }\n >\n <EllipsisIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"w-64\")}>\n <DropdownMenuGroup>\n <DropdownMenuLabel>Section layout</DropdownMenuLabel>\n {section.alternatives.map((layout) => (\n <DropdownMenuItem key={layout} onClick={() => setLayout(section.id, layout)} className=\"items-start\">\n <span className=\"flex flex-col\">\n <span className=\"font-medium\">{LAYOUT_LABEL[layout].name}</span>\n <span className=\"text-xs text-muted-foreground\">{LAYOUT_LABEL[layout].hint}</span>\n </span>\n {layout === section.layout && <CheckIcon className=\"mt-0.5 ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nexport function SectionView({ section }: { section: Section }) {\n const { controls } = useStunning()\n const headingId = `${section.id}-title`\n const heading = section.titleText ? (\n <h2 id={headingId} className=\"smd-h2\">\n <Inline nodes={section.title} />\n </h2>\n ) : null\n const flow = section.blocks.length > 0 && (\n <div className=\"smd-flow\">\n <Blocks blocks={section.blocks} />\n </div>\n )\n\n let body: React.ReactNode\n switch (section.layout) {\n case \"statement\":\n case \"quote\":\n body = (\n <div className=\"smd-container smd-center\">\n {heading}\n {flow}\n </div>\n )\n break\n case \"split\":\n body = (\n <div className=\"smd-container smd-split\" data-flip={section.flip || undefined}>\n <div className=\"smd-split-text\">\n {heading}\n {flow}\n </div>\n {section.feature && (\n <figure className=\"smd-split-media\">\n <Picture image={section.feature} className=\"smd-frame h-auto w-full\" />\n {captionOf(section.feature) && <figcaption>{captionOf(section.feature)}</figcaption>}\n </figure>\n )}\n </div>\n )\n break\n case \"fullbleed\":\n body = (\n <>\n {section.feature && <Picture image={section.feature} className=\"smd-cover\" />}\n <div className=\"smd-scrim\" aria-hidden />\n <div className=\"smd-container smd-over\">\n {heading}\n {flow}\n </div>\n </>\n )\n break\n case \"cards\":\n case \"showcase\":\n body = (\n <div className=\"smd-container smd-stack\">\n {heading}\n {flow}\n </div>\n )\n break\n default:\n body = (\n <div className={cn(\"smd-container\", heading ? \"smd-prose-grid\" : \"smd-prose-solo\")}>\n {heading && <header>{heading}</header>}\n {flow}\n </div>\n )\n }\n\n return (\n <section\n id={section.id}\n aria-labelledby={heading ? headingId : undefined}\n aria-label={heading ? undefined : \"Introduction\"}\n className=\"smd-section\"\n data-layout={section.layout}\n data-tone={section.tone}\n data-intro={heading ? undefined : \"\"}\n >\n {controls && section.alternatives.length > 1 && <LayoutMenu section={section} />}\n {body}\n </section>\n )\n}\n","\"use client\"\n\nimport { AlertTriangleIcon, InfoIcon, LightbulbIcon, OctagonAlertIcon, MessageSquareWarningIcon } from \"lucide-react\"\nimport type { Block } from \"../types\"\nimport { CodeBlock } from \"./code-block\"\nimport { DataBlock } from \"./data-block\"\nimport { Flow, FlowNode, Inline, ItemBody } from \"./flow\"\nimport { Media } from \"./media\"\n\nconst CALLOUTS: Record<string, { label: string; icon: typeof InfoIcon }> = {\n note: { label: \"Note\", icon: InfoIcon },\n tip: { label: \"Tip\", icon: LightbulbIcon },\n important: { label: \"Important\", icon: MessageSquareWarningIcon },\n warning: { label: \"Warning\", icon: AlertTriangleIcon },\n caution: { label: \"Caution\", icon: OctagonAlertIcon },\n}\n\nfunction BlockView({ block }: { block: Block }) {\n switch (block.kind) {\n case \"content\":\n return <FlowNode node={block.node} />\n case \"heading\": {\n const Tag = `h${Math.min(6, block.depth + 2)}` as \"h3\"\n return (\n <Tag id={block.id} className=\"smd-subheading\" data-depth={block.depth}>\n <Inline nodes={block.children} />\n </Tag>\n )\n }\n case \"list\": {\n if (block.variant !== \"feature\") return <FlowNode node={block.node} />\n const Tag = block.node.ordered ? \"ol\" : \"ul\"\n return (\n <Tag className=\"smd-list-feature\" data-columns={block.columns} start={block.node.ordered ? (block.node.start ?? undefined) : undefined}>\n {block.node.children.map((item, index) => (\n <li key={index}>\n <span className=\"smd-list-marker\" aria-hidden>\n {block.node.ordered ? String((block.node.start ?? 1) + index).padStart(2, \"0\") : \"\"}\n </span>\n <div>\n <ItemBody nodes={item.children} />\n </div>\n </li>\n ))}\n </Tag>\n )\n }\n case \"quote\": {\n if (block.variant === \"callout\") {\n const callout = CALLOUTS[block.calloutType ?? \"note\"] ?? CALLOUTS.note\n return (\n <aside className=\"smd-callout\" data-type={block.calloutType}>\n <p className=\"smd-callout-label\">\n <callout.icon aria-hidden />\n {callout.label}\n </p>\n <Flow nodes={block.children} />\n </aside>\n )\n }\n return (\n <figure className={block.variant === \"pull\" ? \"smd-pull\" : \"smd-aside\"}>\n <blockquote>\n <Flow nodes={block.children} />\n </blockquote>\n {block.attribution && <figcaption>{block.attribution}</figcaption>}\n </figure>\n )\n }\n case \"code\":\n return <CodeBlock lang={block.lang} value={block.value} />\n case \"media\":\n return <Media images={block.images} variant={block.variant} />\n case \"data\":\n return <DataBlock id={block.id} table={block.table} viz={block.viz} />\n case \"cards\":\n return (\n <div className=\"smd-cards\" data-count={block.items.length}>\n {block.items.map((item, index) => (\n <article key={item.id} id={item.id} className=\"smd-card\">\n <span className=\"smd-card-index\" aria-hidden>\n {String(index + 1).padStart(2, \"0\")}\n </span>\n <h3>\n <Inline nodes={item.title} />\n </h3>\n <div className=\"smd-flow\">\n <Blocks blocks={item.blocks} />\n </div>\n </article>\n ))}\n </div>\n )\n case \"rule\":\n return <hr className=\"smd-rule\" />\n }\n}\n\nexport function Blocks({ blocks }: { blocks: Block[] }) {\n return (\n <>\n {blocks.map((block, index) => (\n <BlockView key={index} block={block} />\n ))}\n </>\n )\n}\n","\"use client\"\n\nimport { AreaChart, BarChart, LineChart, PieChart, ScatterChart, type Series } from \"generative-charts\"\nimport { ChartNoAxesColumnIcon, CheckIcon, Table2Icon } from \"lucide-react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\"\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"@/components/ui/table\"\nimport { cn } from \"@/lib/utils\"\nimport { formatValue } from \"../analyze/tables\"\nimport type { ChartSpec, TableModel, VizKind, VizPlan } from \"../types\"\nimport { CopyButton } from \"./code-block\"\nimport { useStunning } from \"./context\"\nimport { Inline } from \"./flow\"\n\nconst VIZ_LABEL: Record<VizKind, string> = {\n table: \"Table\",\n bar: \"Bar chart\",\n line: \"Line chart\",\n area: \"Area chart\",\n donut: \"Donut chart\",\n scatter: \"Scatter plot\",\n stats: \"Key figures\",\n timeline: \"Timeline\",\n facts: \"Fact sheet\",\n}\n\n/** Tab-separated text — pastes straight into a spreadsheet. */\nexport function toTsv(table: TableModel): string {\n const clean = (text: string) => text.replace(/[\\t\\n\\r]+/g, \" \").trim()\n return [\n table.columns.map((c) => clean(c.label)).join(\"\\t\"),\n ...table.rows.map((row) => table.columns.map((c) => clean(row.text[c.key])).join(\"\\t\")),\n ].join(\"\\n\")\n}\n\nexport function DataTable({ table, dense }: { table: TableModel; dense?: boolean }) {\n // Give each column room in proportion to its content, so a narrow screen scrolls instead of crushing prose.\n const minWidth = (key: string) => {\n const longest = Math.max(0, ...table.rows.map((row) => row.text[key].length))\n return `${Math.min(24, Math.max(3, Math.round(longest * 0.55)))}ch`\n }\n const alignClass = (align: string) => (align === \"right\" ? \"text-right tabular-nums\" : align === \"center\" ? \"text-center\" : \"text-left\")\n return (\n <Table className={cn(\"smd-table\", dense && \"text-[0.8125rem]\")}>\n <TableHeader>\n <TableRow>\n {table.columns.map((column) => (\n <TableHead key={column.key} scope=\"col\" className={alignClass(column.align)}>\n {column.label}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {table.rows.map((row, r) => (\n <TableRow key={r}>\n {table.columns.map((column, c) => (\n <TableCell key={column.key} className={cn(alignClass(column.align), \"whitespace-normal\")} style={r === 0 ? { minWidth: minWidth(column.key) } : undefined}>\n <Inline nodes={row.cells[c]} />\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )\n}\n\nfunction Chart({ table, viz, spec, titled }: { table: TableModel; viz: VizPlan; spec: ChartSpec; titled: boolean }) {\n const { chartTheme, appearance } = useStunning()\n const columnOf = (key: string) => table.columns.find((c) => c.key === key)!\n const labelColumn = viz.labelKey ? columnOf(viz.labelKey) : undefined\n const series: Series[] = spec.seriesKeys.map((key) => ({ dataKey: key, label: columnOf(key).label }))\n const data = viz.rowIndices.map((r) => {\n const row = table.rows[r]\n const datum: Record<string, unknown> = { label: labelColumn ? row.text[labelColumn.key] : String(r + 1) }\n for (const key of spec.seriesKeys) datum[key] = row.value[key]\n if (viz.kind === \"scatter\" && labelColumn) datum.x = row.value[labelColumn.key]\n return datum\n })\n const names = series.map((s) => s.label).join(\", \")\n const common = {\n data,\n theme: chartTheme,\n appearance,\n title: titled ? names : undefined,\n figureLabel: \"\",\n ariaLabel: `${VIZ_LABEL[viz.kind]} of ${names}${labelColumn ? ` by ${labelColumn.label}` : \"\"}`,\n valueFormatter: (value: number) => formatValue(value, spec.unit),\n showLegend: series.length > 1,\n }\n\n switch (viz.kind) {\n case \"line\":\n return <LineChart {...common} xKey=\"label\" series={series} showPoints={data.length <= 24} height={340} />\n case \"area\":\n return <AreaChart {...common} xKey=\"label\" series={series} height={340} />\n case \"donut\":\n return <PieChart {...common} showLegend nameKey=\"label\" valueKey={spec.seriesKeys[0]} variant=\"donut\" height={340} />\n case \"scatter\":\n return <ScatterChart {...common} xKey=\"x\" series={series} height={360} />\n default:\n return (\n <BarChart\n {...common}\n categoryKey=\"label\"\n series={series}\n variant={viz.horizontal ? \"horizontal\" : \"vertical\"}\n height={viz.horizontal ? Math.max(260, data.length * 34 + 90) : 340}\n />\n )\n }\n}\n\nfunction Stats({ table, viz }: { table: TableModel; viz: VizPlan }) {\n const keys = viz.charts[0]?.seriesKeys ?? []\n const tiles =\n table.rows.length === 1\n ? keys.map((key) => ({ label: table.columns.find((c) => c.key === key)!.label, value: table.rows[0].text[key] }))\n : viz.rowIndices.map((r) => ({ label: table.rows[r].text[viz.labelKey ?? \"\"], value: table.rows[r].text[keys[0]] }))\n return (\n <dl className=\"smd-stats\">\n {tiles.map((tile, i) => (\n <div key={i}>\n <dd>{tile.value}</dd>\n <dt>{tile.label}</dt>\n </div>\n ))}\n </dl>\n )\n}\n\nfunction Timeline({ table, viz }: { table: TableModel; viz: VizPlan }) {\n const dateIndex = table.columns.findIndex((c) => c.key === viz.labelKey)\n const rest = table.columns.map((column, index) => ({ column, index })).filter(({ index }) => index !== dateIndex)\n return (\n <ol className=\"smd-timeline\">\n {viz.rowIndices.map((r) => {\n const row = table.rows[r]\n const filled = rest.filter(({ column }) => row.text[column.key])\n // The first descriptive column names the event; figures and the rest are details.\n const head = filled.find(({ column }) => column.type === \"text\") ?? filled[0]\n const details = filled.filter((entry) => entry !== head)\n return (\n <li key={r}>\n <time>{row.text[table.columns[dateIndex].key]}</time>\n <div>\n {head && (\n <p className=\"smd-timeline-title\">\n <Inline nodes={row.cells[head.index]} />\n </p>\n )}\n {details.map(({ column, index }) => (\n <p key={column.key}>\n {(details.length > 1 || column.type !== \"text\") && <span className=\"smd-timeline-key\">{column.label}: </span>}\n <Inline nodes={row.cells[index]} />\n </p>\n ))}\n </div>\n </li>\n )\n })}\n </ol>\n )\n}\n\nfunction Facts({ table }: { table: TableModel }) {\n return (\n <dl className=\"smd-facts\">\n {table.rows.map((row, r) => (\n <div key={r}>\n <dt>\n <Inline nodes={row.cells[0]} />\n </dt>\n <dd>\n <Inline nodes={row.cells[1]} />\n </dd>\n </div>\n ))}\n </dl>\n )\n}\n\nexport function DataBlock({ id, table, viz }: { id: string; table: TableModel; viz: VizPlan }) {\n const { portal, controls, setViz } = useStunning()\n const isTable = viz.kind === \"table\"\n const multiple = viz.charts.length > 1\n\n let body: React.ReactNode\n if (isTable) body = <div className=\"smd-table-scroll\">{<DataTable table={table} />}</div>\n else if (viz.kind === \"stats\") body = <Stats table={table} viz={viz} />\n else if (viz.kind === \"timeline\") body = <Timeline table={table} viz={viz} />\n else if (viz.kind === \"facts\") body = <Facts table={table} />\n else {\n body = (\n <div className={cn(\"grid gap-6\", multiple && \"xl:grid-cols-2\")}>\n {viz.charts.map((spec) => (\n <div key={spec.seriesKeys.join()} className=\"smd-chart min-w-0\" data-multi={spec.seriesKeys.length > 1 || undefined}>\n <Chart table={table} viz={viz} spec={spec} titled={multiple} />\n </div>\n ))}\n </div>\n )\n }\n\n return (\n <figure className=\"smd-data\" data-viz={viz.kind} data-block-id={id}>\n <div className=\"smd-data-tools\">\n {controls && viz.candidates.length > 1 && (\n <DropdownMenu>\n <DropdownMenuTrigger render={<Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground\" aria-label=\"Change how this data is shown\" title=\"Change form\" />}>\n <ChartNoAxesColumnIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"w-44\")}>\n <DropdownMenuGroup>\n <DropdownMenuLabel>Show as</DropdownMenuLabel>\n {viz.candidates.map((kind) => (\n <DropdownMenuItem key={kind} onClick={() => setViz(id, kind)}>\n {VIZ_LABEL[kind]}\n {kind === viz.kind && <CheckIcon className=\"ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {!isTable && (\n <Popover>\n <PopoverTrigger render={<Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground\" aria-label=\"View the underlying data table\" title=\"View data\" />}>\n <Table2Icon />\n </PopoverTrigger>\n <PopoverContent align=\"end\" style={portal.style} className={cn(portal.className, \"max-h-[70svh] w-[min(92vw,44rem)] overflow-auto p-0\")}>\n <div className=\"sticky top-0 z-10 flex items-center justify-between border-b bg-popover px-3 py-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {table.rows.length} rows × {table.columns.length} columns\n </span>\n <CopyButton text={() => toTsv(table)} label=\"Copy table for spreadsheets\" />\n </div>\n <DataTable table={table} dense />\n </PopoverContent>\n </Popover>\n )}\n {isTable && <CopyButton text={() => toTsv(table)} label=\"Copy table for spreadsheets\" />}\n </div>\n {body}\n </figure>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n \"z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-0.5 text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\n return (\n <PopoverPrimitive.Title\n data-slot=\"popover-title\"\n className={cn(\"font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: PopoverPrimitive.Description.Props) {\n return (\n <PopoverPrimitive.Description\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\n return (\n <div\n data-slot=\"table-container\"\n className=\"relative w-full overflow-x-auto\"\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\"[&_tr]:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<\"th\">) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<\"td\">) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n"],"mappings":";;;AAEA,SAAS,eAAAA,cAAa,aAAAC,YAAW,OAAO,WAAAC,UAAS,UAAAC,SAAQ,YAAAC,WAAU,4BAA4B;;;ACF/F,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ACFA,IAAM,QAAQ,oBAAI,IAAuC;AAEzD,SAAS,MAAM,KAAa,WAA8C;AACxE,QAAM,MAAM,MAAM,IAAI,GAAG;AACzB,MAAI,IAAK,QAAO;AAChB,QAAM,UAAU,IAAI,QAA0B,CAAC,YAAY;AACzD,UAAM,QAAQ,IAAI,MAAM;AACxB,UAAM,QAAQ,WAAW,MAAM,QAAQ,IAAI,GAAG,SAAS;AACvD,UAAM,SAAS,MAAM;AACnB,mBAAa,KAAK;AAElB,cAAQ,MAAM,eAAe,IAAI,EAAE,OAAO,MAAM,cAAc,QAAQ,MAAM,cAAc,IAAI,IAAI;AAAA,IACpG;AACA,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,cAAQ,IAAI;AAAA,IACd;AACA,UAAM,MAAM;AAAA,EACd,CAAC;AACD,QAAM,IAAI,KAAK,OAAO;AACtB,SAAO;AACT;AAMA,eAAsB,YAAY,MAAgB,YAAqC,YAAY,MAA6B;AAC9H,QAAM,UAAU,MAAM,QAAQ,IAAI,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,MAAM,MAAM,WAAW,GAAG,GAAG,SAAS,CAAC,CAAU,CAAC;AAClH,SAAO,OAAO,YAAY,OAAO;AACnC;;;AC9BO,SAAS,OAAO,MAA2C;AAChE,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO,KAAK,IAAI,MAAM,EAAE,KAAK,EAAE;AACxD,MAAI,KAAK,SAAS,UAAU,KAAK,SAAS,gBAAgB,KAAK,SAAS,OAAQ,QAAO,KAAK;AAC5F,MAAI,KAAK,SAAS,QAAS,QAAO;AAClC,MAAI,KAAK,SAAS,QAAS,QAAO;AAClC,MAAI,cAAc,MAAM;AACtB,UAAM,YAAY,KAAK,SAAS,eAAe,KAAK,SAAS,aAAa,KAAK,SAAS,aAAa,MAAM;AAC3G,WAAQ,KAAK,SAAqB,IAAI,MAAM,EAAE,KAAK,SAAS;AAAA,EAC9D;AACA,SAAO;AACT;AAGO,SAAS,QAAQ,MAAqB;AAC3C,MAAI,KAAK,SAAS,aAAa,KAAK,SAAS,UAAU,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU,KAAK,SAAS,OAAQ,QAAO;AACrI,MAAI,KAAK,SAAS,YAAa,QAAO,OAAO,IAAI;AACjD,MAAI,cAAc,KAAM,QAAQ,KAAK,SAAqB,IAAI,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC/F,SAAO;AACT;AAEO,SAAS,WAAW,MAAsB;AAC/C,QAAM,UAAU,KAAK,KAAK;AAC1B,SAAO,UAAU,QAAQ,MAAM,KAAK,EAAE,SAAS;AACjD;AAEO,SAAS,QAAQ,MAA2C;AACjE,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO,KAAK,OAAO,CAAC,KAAK,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AACnF,MAAI,KAAK,SAAS,OAAQ,QAAO;AACjC,MAAI,cAAc,QAAQ,KAAK,SAAS,eAAe,KAAK,SAAS,WAAW;AAC9E,WAAQ,KAAK,SAAqB,OAAO,CAAC,KAAK,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAAA,EAClF;AACA,SAAO,WAAW,OAAO,IAAI,CAAC;AAChC;AAEO,SAAS,QAAQ,MAAc,OAA4B;AAChE,QAAM,OACJ,KACG,YAAY,EACZ,UAAU,MAAM,EAChB,QAAQ,UAAU,EAAE,EACpB,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,MAAM,GAAG,EAAE,KAAK;AACrB,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG,IAAK,QAAO,GAAG,IAAI,IAAI,CAAC;AACzD,QAAM,IAAI,IAAI;AACd,SAAO;AACT;AAGO,SAAS,WAAW,UAAuE;AAChG,QAAM,QAA2C,CAAC;AAClD,aAAW,SAAS,UAAU;AAC5B,QAAI,MAAM,SAAS,QAAS,OAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,aAC9C,MAAM,SAAS,UAAU,MAAM,SAAS,WAAW,KAAK,MAAM,SAAS,CAAC,EAAE,SAAS,SAAS;AACnG,YAAM,KAAK,EAAE,OAAO,MAAM,SAAS,CAAC,GAAG,MAAM,MAAM,IAAI,CAAC;AAAA,IAC1D,WAAW,MAAM,SAAS,WAAY,MAAM,SAAS,UAAU,CAAC,MAAM,MAAM,KAAK,EAAI;AAAA,QAChF,QAAO;AAAA,EACd;AACA,SAAO,MAAM,SAAS,QAAQ;AAChC;;;AC1DA,IAAM,UAAU;AAChB,IAAM,WAAW;AACjB,IAAM,SAAS,IAAI;AAAA,EACjB,sCAA4B,QAAQ;AAEtC;AACA,IAAM,YAAoC;AAAA,EACxC,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,UAAU;AAAA,EAC1B,GAAG;AAAA,EAAK,GAAG;AAAA,EAAK,IAAI;AAAA,EAAK,SAAS;AAAA,EAClC,GAAG;AAAA,EAAK,IAAI;AAAA,EAAK,SAAS;AAAA,EAC1B,GAAG;AAAA,EAAM,UAAU;AACrB;AAEO,SAAS,YAAY,KAAkC;AAC5D,QAAM,OAAO,IAAI,KAAK;AACtB,QAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,CAAC,EAAE,MAAM,OAAO,WAAW,IAAI,OAAO,QAAQ,WAAW,YAAY,IAAI,KAAK,IAAI;AACxF,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,WAAW;AAEb,QAAI,cAAc,OAAO,CAAC,SAAU,UAAS,IAAI,MAAM;AAAA,QAClD,SAAQ,UAAU,SAAS;AAAA,EAClC;AACA,QAAM,QAAQ,OAAO,OAAO,QAAQ,UAAU,EAAE,CAAC,IAAI;AACrD,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,QAAM,WAAY,QAAQ,SAAU,QAAQ,KAAK,QAAQ,KAAK;AAC9D,SAAO,EAAE,OAAO,WAAW,CAAC,QAAQ,OAAO,QAAQ,SAAS,KAAK,GAAG,OAAO;AAC7E;AAEA,IAAM,SAAS,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAClG,IAAM,aAAa,CAAC,SAAiB,OAAO,QAAQ,KAAK,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC;AAClF,IAAM,aAAa;AACnB,IAAM,WAAW,CAAC,MAAe,EAAE,WAAW,IAAI,MAAO,OAAO,CAAC,IAAI,OAAO,CAAC;AAC7E,IAAM,YAAY,CAAC,MAAc,KAAK,OAAQ,KAAK;AAG5C,SAAS,UAAU,KAA4B;AACpD,QAAM,OAAO,IAAI,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAC3C,MAAI;AACJ,MAAK,IAAI,YAAY,KAAK,IAAI,EAAI,QAAO,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,IAAI;AACpF,MAAK,IAAI,+DAA+D,KAAK,IAAI,GAAI;AACnF,WAAO,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI;AAAA,EAChF;AACA,MAAK,IAAI,gCAAgC,KAAK,IAAI,EAAI,QAAO,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC;AAC1F,MAAK,IAAI,+BAA+B,KAAK,IAAI,EAAI,QAAO,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC;AACvG,MAAK,IAAI,+BAA+B,KAAK,IAAI,EAAI,QAAO,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC;AACvG,MAAK,IAAI,8BAA8B,KAAK,IAAI,EAAI,QAAO,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC;AACtG,MAAK,IAAI,IAAI,OAAO,IAAI,UAAU,KAAK,GAAG,EAAE,KAAK,IAAI,EAAI,QAAO,KAAK,IAAI,KAAM,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC;AAClG,MAAK,IAAI,IAAI,OAAO,IAAI,UAAU,uBAAuB,GAAG,EAAE,KAAK,IAAI,GAAI;AACzE,WAAO,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC;AAAA,EACrD;AACA,MAAK,IAAI,IAAI,OAAO,IAAI,UAAU,2CAA2C,GAAG,EAAE,KAAK,IAAI,GAAI;AAC7F,WAAO,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAAA,EAChD;AACA,MAAK,IAAI,IAAI,OAAO,+BAA+B,UAAU,gBAAgB,GAAG,EAAE,KAAK,IAAI,GAAI;AAC7F,WAAO,KAAK,IAAI,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAAA,EAChD;AACA,MAAK,IAAI,4CAA4C,KAAK,IAAI,GAAI;AAChE,UAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC5B,UAAM,CAAC,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5C,WAAO,SAAS,KAAK,SAAS,MAAM,OAAO,KAAK,KAAK,IAAI,SAAS,EAAE,CAAC,CAAC,GAAG,QAAQ,GAAG,GAAG,IAAI;AAAA,EAC7F;AACA,SAAO;AACT;AAEA,IAAM,YAAY;AAClB,IAAM,cAAc;AACpB,IAAM,eAAe;AACrB,IAAM,gBAAgB;AAGtB,SAAS,eAAe,OAAiC;AACvD,QAAM,QAAQ,oCAAoC,KAAK,KAAK;AAC5D,MAAI,CAAC,MAAO,QAAO,MAAM,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,QAAQ,IAAI,QAAQ,IAAI,IAAI;AAC9E,QAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,QAAM,WAAW,IAAI,OAAO,KAAK,QAAQ,GAAG,EAAE,KAAK,IAAI;AACvD,MAAI,SAAU,QAAO,EAAE,QAAQ,SAAS,CAAC,GAAG,QAAQ,KAAK,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;AAC1F,MAAI,QAAQ,KAAK,IAAI,EAAG,QAAO,EAAE,QAAQ,IAAI,QAAQ,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG;AACzE,SAAO,EAAE,QAAQ,IAAI,QAAQ,SAAS,MAAM,MAAM,IAAI,IAAI,GAAG;AAC/D;AAEA,IAAM,aAAa,CAAC,WAAqB;AACvC,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,KAAK,OAAQ,QAAO,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC;AAC9D,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AACtE;AAEO,SAAS,gBAAgB,MAAyB;AACvD,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI,KAAK;AAC7B,QAAM,WAAW,MAAM,YAAY,CAAC,GAAG,IAAI,CAAC,SAAS,OAAO,IAAI,EAAE,KAAK,CAAC;AACxE,QAAM,QAAQ,KAAK,IAAI,QAAQ,QAAQ,GAAG,KAAK,IAAI,CAAC,QAAQ,IAAI,SAAS,MAAM,CAAC;AAChF,QAAM,WAAW,KAAK,IAAI,CAAC,QAAQ,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAM,OAAO,IAAI,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAE1G,QAAM,UAAyB,CAAC;AAChC,QAAM,SAAuC,KAAK,IAAI,MAAM,CAAC,CAAC;AAE9D,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,QAAQ,QAAQ,CAAC,KAAK;AAC5B,UAAM,QAAQ,SAAS,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;AAC1C,UAAM,UAAU,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC;AAC1D,UAAM,UAAU,MAAM,IAAI,CAAC,SAAU,QAAQ,KAAK,IAAI,IAAI,OAAO,YAAY,IAAI,CAAE;AACnF,UAAM,QAAQ,MAAM,IAAI,CAAC,SAAU,QAAQ,KAAK,IAAI,IAAI,OAAO,UAAU,IAAI,CAAE;AAC/E,UAAM,eAAe,QAAQ,OAAO,OAAO,EAAE;AAC7C,UAAM,YAAY,MAAM,OAAO,CAAC,MAAM,KAAK,IAAI,EAAE;AACjD,UAAM,SAAS,CAAC,UAAkB,QAAQ,SAAS,KAAK,SAAS,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,SAAS,GAAG,CAAC;AAE5G,UAAM,WAAW,OAAO,SAAS,KAAK,QAAQ,MAAM,CAAC,SAAS,UAAU,KAAK,IAAI,CAAC;AAClF,QAAI,OAAmB;AAEvB,QAAI,OAAO,SAAS,MAAM,CAAC,YAAY,MAAM,KAAK,YAAY,KAAK,KAAK,GAAI,QAAO;AAAA,aAC1E,OAAO,YAAY,KAAK,CAAC,UAAU,KAAK,KAAK,EAAG,QAAO;AAEhE,QAAI;AACJ,QAAI,SAAS,UAAU;AACrB,YAAM,QAAQ,QAAQ,OAAO,CAAC,MAAyB,KAAK,IAAI;AAChE,YAAM,SAAS,WAAW,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACpD,YAAM,SAAS,WAAW,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACpD,aAAO,UAAU,SAAS,EAAE,QAAQ,OAAO,IAAI,eAAe,KAAK;AAAA,IACrE;AAEA,UAAM,QAAQ,KAAK,QAAQ,CAAC,MAAM,SAAS,WAAW,UAAU;AAChE,YAAQ,KAAK,EAAE,KAAK,IAAI,CAAC,IAAI,OAAO,SAAS,UAAU,IAAI,CAAC,IAAI,MAAM,MAAM,MAAM,CAAC;AACnF,aAAS,QAAQ,CAAC,KAAK,MAAM;AAC3B,aAAO,CAAC,EAAE,CAAC,IAAI,SAAS,WAAY,QAAQ,CAAC,GAAG,SAAS,OAAQ,SAAS,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC;AAAA,IACrG,CAAC;AAAA,EACH;AAEA,QAAM,OAAmB,KAAK,IAAI,CAAC,KAAK,OAAO;AAAA,IAC7C,MAAM,OAAO,YAAY,QAAQ,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAAA,IAC3E,OAAO,OAAO,YAAY,QAAQ,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAAA,IAC1E,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAAO,IAAI,SAAS,CAAC,GAAG,YAAY,CAAC,CAAuB;AAAA,EACvG,EAAE;AAEF,SAAO,EAAE,MAAM,SAAS,KAAK;AAC/B;AAEA,IAAM,UAAU,CAAC,SAAgB,GAAG,MAAM,UAAU,EAAE,IAAI,MAAM,UAAU,EAAE;AAM5E,SAAS,YAAY,OAAmB,SAAwB,YAAmC;AACjG,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,QAAQ,OAAO,IAAI;AAC/B,WAAO,IAAI,KAAK,CAAC,GAAI,OAAO,IAAI,GAAG,KAAK,CAAC,GAAI,MAAM,CAAC;AAAA,EACtD;AACA,QAAM,SAAsB,CAAC;AAC7B,aAAW,SAAS,OAAO,OAAO,GAAG;AACnC,UAAM,OAAO,CAAC,WACZ,KAAK,IAAI,GAAG,GAAG,WAAW,IAAI,CAAC,MAAM,KAAK,IAAK,MAAM,KAAK,CAAC,EAAE,MAAM,OAAO,GAAG,KAAuB,CAAC,CAAC,CAAC;AACzG,UAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;AAC1D,QAAI,UAAyB,CAAC;AAC9B,eAAW,UAAU,QAAQ;AAC3B,UAAI,QAAQ,UAAU,KAAK,QAAQ,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI;AAC1D,eAAO,KAAK,EAAE,YAAY,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC;AAC5E,kBAAU,CAAC;AAAA,MACb;AACA,cAAQ,KAAK,MAAM;AAAA,IACrB;AACA,QAAI,QAAQ,OAAQ,QAAO,KAAK,EAAE,YAAY,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC;AAAA,EAClG;AAEA,QAAM,QAAQ,CAAC,QAAgB,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG;AAC3E,aAAW,SAAS,OAAQ,OAAM,WAAW,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC;AAC/E,SAAO,OAAO,KAAK,CAAC,GAAG,MAAM,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9E;AAGO,SAAS,QAAQ,OAA4B;AAClD,QAAM,EAAE,SAAS,KAAK,IAAI;AAC1B,QAAM,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC;AAChC,QAAM,QAAQ,CAAC,QAAgB,aAAwB,CAAC,OAAgB;AAAA,IACtE,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,YAAY;AAAA,IACZ,YAAY,CAAC,SAAS,GAAG,UAAU;AAAA,IACnC;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,EAAG,QAAO,MAAM,wBAAwB;AAElF,MAAI,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AACvD,QAAM,aAAa,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACxD,QAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AACrD,MAAI,QAAiC,cAAc,MAAM,CAAC;AAE1D,MAAI,UAAU;AACd,MAAI,CAAC,SAAS,KAAK,UAAU,KAAK,QAAQ,UAAU,KAAK,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG;AAClF,UAAM,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ,CAAC,EAAE,GAAG,CAAkB;AAC1E,QAAI,MAAM,MAAM,CAAC,GAAG,MAAM,KAAK,SAAS,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,EAAG,GAAG;AACtE,cAAQ,QAAQ,CAAC;AACjB,gBAAU,QAAQ,MAAM,CAAC;AACzB,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,aAAa,MAAM,OAAO,CAAC,MAAM,MAAM,KAAK;AAClD,QAAM,YAAY,CAAC,WACjB,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,KAAK,OAAO,GAAG,EAAE,QAAQ,CAAC,IAAI,KAAK;AAGzE,MAAI,KAAK,WAAW,KAAK,QAAQ,UAAU,KAAK,QAAQ,UAAU,GAAG;AACnE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,OAAO;AAAA,MACjB,QAAQ,CAAC,EAAE,YAAY,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;AAAA,MAClD,YAAY;AAAA,MACZ,YAAY,CAAC,SAAS,OAAO;AAAA,MAC7B,QAAQ;AAAA,IACV;AAAA,EACF;AACA,MAAI,KAAK,SAAS,EAAG,QAAO,MAAM,YAAY;AAE9C,MAAI,QAAQ,WAAW,GAAG;AACxB,QAAI,cAAc,WAAW,UAAU,MAAM,SAAS,KAAM,IAAI,IAAI,MAAM,WAAW,KAAK,KAAK,UAAU,GAAG;AAC1G,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,WAAW;AAAA,QACrB,QAAQ,CAAC;AAAA,QACT,YAAY;AAAA,QACZ,YAAY,CAAC,YAAY,OAAO;AAAA,QAChC,QAAQ;AAAA,MACV;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,KAAK,KAAK,UAAU,MAAM,UAAU,QAAQ,CAAC,CAAC,KAAK,IAAI;AAC5E,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,QAAQ,CAAC,EAAE;AAAA,QACrB,QAAQ,CAAC;AAAA,QACT,YAAY;AAAA,QACZ,YAAY,CAAC,SAAS,OAAO;AAAA,QAC7B,QAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO,MAAM,oBAAoB;AAAA,EACnC;AAEA,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,UAAU,KAAK,KAAK,UAAU,GAAG;AAC3C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,QAAQ,CAAC,EAAE;AAAA,QACrB,QAAQ,CAAC,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC;AAAA,QAChE,YAAY;AAAA,QACZ,YAAY,CAAC,WAAW,OAAO;AAAA,QAC/B,QAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO,MAAM,iBAAiB;AAAA,EAChC;AAGA,MAAI,WAAW,UAAU,QAAQ,UAAU,WAAW,KAAK,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG;AAEpF,QAAI,cAAc,KAAK,UAAU,KAAK,QAAQ,UAAU,GAAG;AACzD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,WAAW;AAAA,QACrB,QAAQ,CAAC;AAAA,QACT,YAAY;AAAA,QACZ,YAAY,CAAC,YAAY,OAAO;AAAA,QAChC,QAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO,MAAM,wCAAwC,aAAa,CAAC,UAAU,IAAI,CAAC,CAAC;AAAA,EACrF;AAEA,QAAM,SAAS,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK,MAAM,GAAG,CAAC;AACpD,MAAI,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,KAAK,SAAS,KAAK,cAAc,KAAK,OAAO,CAAC,CAAC,EAAE;AACtF,MAAI,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,WAAW,QAAQ;AACtE,WAAO,MAAM,0DAAqD;AAAA,EACpE;AACA,MAAI,WAAW,SAAS,EAAG,QAAO,MAAM,cAAc;AAEtD,QAAM,SAAS,YAAY,OAAO,SAAS,UAAU;AACrD,MAAI,OAAO,SAAS,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC,GAAG;AACpE,WAAO,MAAM,+BAA+B,CAAC,KAAK,CAAC;AAAA,EACrD;AACA,QAAM,SAAS,OAAO,WAAW,KAAK,OAAO,CAAC,EAAE,WAAW,WAAW;AACtE,QAAM,QAAQ,WAAW;AAEzB,MAAI,MAAM,SAAS,UAAU,SAAS;AACpC,UAAM,OAAO,MAAM;AACnB,UAAM,QAAQ,WAAW,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,IAAI,CAAW;AACjE,QAAI,MAAM,CAAC,IAAI,MAAM,MAAM,SAAS,CAAC,EAAG,cAAa,CAAC,GAAG,UAAU,EAAE,QAAQ;AAE7E,UAAM,QAAQ,OAAO,MAAM,CAAC,UAAU,MAAM,WAAW,WAAW,CAAC;AACnE,UAAM,OAAgB,QAAS,SAAS,IAAI,SAAS,QAAS,SAAS,IAAI,SAAS;AACpF,WAAO;AAAA,MACL;AAAA,MACA,UAAU,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA,YAAY,CAAC,GAAG,oBAAI,IAAa,CAAC,MAAM,QAAQ,OAAO,QAAQ,OAAO,CAAC,CAAC;AAAA,MACxE,QAAQ,GAAG,KAAK,IAAI,UAAU,UAAU,SAAS,SAAM,QAAQ,MAAM;AAAA,IACvE;AAAA,EACF;AAEA,MAAI,QAAQ,GAAI,QAAO,MAAM,4CAA4C,CAAC,KAAK,CAAC;AAEhF,MAAI,QAAQ;AACV,UAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;AACpE,UAAM,SAAS,WAAW,IAAI,CAAC,MAAO,KAAK,CAAC,EAAE,MAAM,OAAO,GAAG,KAAuB,CAAC;AACtF,QAAI,SAAS,KAAK,WAAW,WAAW,GAAG;AACzC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,YAAY,CAAC,SAAS,OAAO,OAAO;AAAA,QACpC,QAAQ;AAAA,MACV;AAAA,IACF;AACA,UAAM,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAC5C,UAAM,aAAa,OAAO,MAAM,WAAW,OAAO,MAAM,MAAM,MAAM;AACpE,QAAI,SAAS,KAAK,SAAS,KAAK,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,MAAM,cAAc,aAAa,KAAK,OAAO,KAAK,IAAI;AAC9G,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA,YAAY,CAAC,SAAS,OAAO,OAAO;AAAA,QACpC,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,QAAQ;AAC9B,MAAI,CAAC,UAAU,QAAQ,GAAI,QAAO,MAAM,sBAAsB,CAAC,KAAK,CAAC;AACrE,QAAM,UAAU,KAAK,IAAI,GAAG,WAAW,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,MAAM,CAAC;AACnE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,YAAY,WAAW,QAAQ,KAAK,UAAU;AAAA,IAC9C;AAAA,IACA,YAAY,UAAU,SAAS,IAAI,CAAC,OAAO,SAAS,SAAS,OAAO,IAAI,CAAC,OAAO,OAAO;AAAA,IACvF,QAAQ,GAAG,KAAK,oBAAiB,QAAQ,MAAM;AAAA,EACjD;AACF;AAGO,SAAS,YAAY,MAAe,OAAmB,MAAwB;AACpF,MAAI,SAAS,KAAK,QAAQ,CAAC,KAAK,WAAW,SAAS,IAAI,EAAG,QAAO;AAClE,QAAM,OAAgB,EAAE,GAAG,MAAM,MAAM,QAAQ,GAAG,KAAK,MAAM,yBAAoB,IAAI,GAAG;AACxF,MAAI,SAAS,YAAY;AACvB,SAAK,WAAW,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG,OAAO,KAAK;AAC1E,SAAK,aAAa,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC;AAAA,EAC9C;AACA,MAAI,SAAS,SAAS,KAAK,OAAO,WAAW,GAAG;AAC9C,UAAM,UAAU,MAAM,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC/D,UAAM,QAAQ,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC3D,QAAI,CAAC,QAAQ,UAAU,CAAC,MAAO,QAAO;AACtC,SAAK,WAAW,MAAM;AACtB,SAAK,SAAS,YAAY,OAAO,SAAS,KAAK,UAAU;AAAA,EAC3D;AACA,MAAI,SAAS,OAAO;AAClB,UAAM,UAAU,KAAK,IAAI,GAAG,KAAK,WAAW,IAAI,CAAC,MAAM,MAAM,KAAK,CAAC,EAAE,KAAK,KAAK,YAAY,EAAE,GAAG,UAAU,CAAC,CAAC;AAC5G,UAAM,SAAS,KAAK,OAAO,WAAW,KAAK,KAAK,OAAO,CAAC,EAAE,WAAW,WAAW;AAChF,SAAK,aAAa,WAAW,KAAK,WAAW,SAAS,KAAK,UAAU;AAAA,EACvE;AACA,SAAO;AACT;AAGO,SAAS,YAAY,OAAe,MAAqB;AAC9D,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,OACJ,OAAO,MACH,IAAI,KAAK,aAAa,MAAM,EAAE,UAAU,WAAW,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,IAC3F,IAAI,KAAK,aAAa,MAAM,EAAE,uBAAuB,MAAM,KAAK,IAAI,MAAM,MAAM,IAAI,EAAE,CAAC,EAAE,OAAO,KAAK;AAC3G,QAAM,OAAO,KAAK,WAAW,GAAG,IAAI,WAAM;AAC1C,SAAO,GAAG,IAAI,GAAG,MAAM,UAAU,EAAE,GAAG,KAAK,QAAQ,MAAM,EAAE,CAAC,GAAG,MAAM,UAAU,EAAE;AACnF;;;ACpWA,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,cAAc;AAGb,SAAS,iBAAiB,MAAsB;AACrD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAQ,CAAC,SAAkB;AAC/B,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,WAAW,EAAE,IAAK,MAAK,IAAI,EAAE,GAAG;AAC/C,MAAE,UAAU,QAAQ,KAAK;AAAA,EAC3B;AACA,QAAM,IAAI;AACV,SAAO,CAAC,GAAG,IAAI;AACjB;AAEA,SAAS,QAAQ,OAA0B;AACzC,MAAI,UAAU,KAAK,MAAM,GAAG,EAAG,QAAO;AACtC,SAAO,CAAC,CAAC,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM,MAAM,KAAK,SAAS;AACxE;AAEA,SAAS,kBAAkB,OAAyC;AAClE,QAAM,OAAO,MAAM;AAEnB,MAAI,CAAC,QAAQ,KAAK,QAAQ,GAAI,QAAO;AACrC,QAAM,SAAS,KAAK,QAAQ,KAAK;AACjC,QAAM,OAAO,GAAG,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,MAAM,GAAG;AACvD,QAAM,SAAS,UAAU,KAAK,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC;AACxD,MAAI,UAAU,KAAK,IAAI,KAAK,EAAE,KAAK,SAAS,QAAQ,UAAU,KAAM,QAAO;AAC3E,MAAI,KAAK,SAAS,QAAQ,UAAU,OAAO,CAAC,OAAQ,QAAO;AAC3D,MAAI,YAAY,KAAK,IAAI,KAAK,KAAK,SAAS,OAAO,UAAU,IAAK,QAAO;AACzE,MAAI,UAAU,KAAK,IAAI,KAAK,OAAO,KAAK,MAAM,KAAK,IAAK,QAAO;AAC/D,SAAO;AACT;AAWA,SAAS,SAAS,OAA8F,KAAwB;AACtI,SAAO;AAAA,IACL,KAAK,MAAM,MAAM;AAAA,IACjB,KAAK,MAAM,MAAM,OAAO;AAAA,IACxB,OAAO,MAAM,MAAM,SAAS;AAAA,IAC5B,MAAM,MAAM;AAAA,IACZ,MAAM,IAAI,OAAO,MAAM,MAAM,GAAG,KAAK;AAAA,EACvC;AACF;AAEA,SAAS,SAAS,MAAsD;AACtE,QAAM,QAAQ,KAAK;AACnB,MAAI,MAAM,KAAK,CAAC,SAAS,KAAK,WAAW,IAAI,EAAG,QAAO,EAAE,SAAS,aAAa,SAAS,EAAE;AAC1F,QAAM,SAAS,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,KAAK,CAAC,UAAU,MAAM,SAAS,UAAU,MAAM,SAAS,MAAM,CAAC;AACjH,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS,QAAQ,IAAI,CAAC;AAC/C,QAAM,QAAQ,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAC7C,QAAM,UAAU,KAAK,IAAI,GAAG,GAAG,KAAK;AAEpC,MAAI,CAAC,UAAU,MAAM,UAAU,KAAK,MAAM,UAAU,KAAK,WAAW,MAAM,SAAS,KAAK;AACtF,WAAO,EAAE,SAAS,WAAW,SAAS,MAAM,UAAU,KAAK,WAAW,KAAK,IAAI,EAAE;AAAA,EACnF;AACA,SAAO,EAAE,SAAS,QAAQ,SAAS,EAAE;AACvC;AAEA,IAAM,cAAc;AAEpB,SAAS,UAAU,MAAqD;AACtE,MAAI,WAAW,KAAK;AACpB,QAAM,QAAQ,SAAS,CAAC;AAGxB,MAAI,OAAO,SAAS,eAAe,MAAM,SAAS,CAAC,GAAG,SAAS,QAAQ;AACrE,UAAM,QAAQ,iDAAiD,KAAK,MAAM,SAAS,CAAC,EAAE,KAAK;AAC3F,QAAI,OAAO;AACT,YAAM,OAA0B;AAAA,QAC9B,EAAE,MAAM,QAAQ,OAAO,MAAM,SAAS,CAAC,EAAE,MAAM,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE;AAAA,QACtE,GAAG,MAAM,SAAS,MAAM,CAAC;AAAA,MAC3B;AACA,YAAM,OAAO,KAAK,KAAK,CAAC,UAAU,OAAO,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,UAAU,KAAK,CAAC,IAAI,CAAC;AAC5F,aAAO,EAAE,MAAM,SAAS,SAAS,WAAW,aAAa,MAAM,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC,GAAG,MAAM,GAAG,SAAS,MAAM,CAAC,CAAC,EAAE;AAAA,IAC7H;AAAA,EACF;AAEA,MAAI;AACJ,QAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,MAAI,MAAM,SAAS,aAAa;AAC9B,UAAM,QAAQ,YAAY,KAAK,OAAO,IAAI,CAAC;AAC3C,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,oBAAc,MAAM,CAAC,EAAE,KAAK;AAC5B,iBAAW,SAAS,MAAM,GAAG,EAAE;AAAA,IACjC,OAAO;AAEL,YAAM,UAAU,KAAK,SAAS,cAAc,CAAC,UAAU,MAAM,SAAS,OAAO;AAC7E,YAAM,OAAO,WAAW,IAAI,KAAK,SAAS,MAAM,UAAU,CAAC,IAAI,CAAC;AAChE,YAAM,YAAY,KAAK,SAAS,YAAY,KAAK,OAAO,IAAI,CAAC,IAAI,iCAAiC,KAAK,OAAO,IAAI,CAAC;AACnH,UAAI,aAAa,WAAW,GAAG;AAC7B,sBAAc,UAAU,CAAC,EAAE,KAAK;AAChC,mBAAW,CAAC,GAAG,SAAS,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,UAAU,KAAK,SAAS,MAAM,GAAG,OAAO,EAAE,CAAC;AAAA,MAC9F,WAAW,aAAa,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,CAAC,EAAE,SAAS,QAAQ;AACtF,sBAAc,UAAU,CAAC,EAAE,KAAK;AAChC,cAAM,QAAQ,KAAK,SAAS,CAAC,EAAE,MAAM,QAAQ,gCAAgC,EAAE;AAC/E,mBAAW,CAAC,GAAG,SAAS,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,UAAU,CAAC,EAAE,MAAM,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,MACxF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,QAAQ;AAC9B,QAAM,SAAS,SAAS,MAAM,CAAC,UAAU,MAAM,SAAS,WAAW;AACnE,SAAO,EAAE,MAAM,SAAS,SAAS,UAAU,SAAS,KAAK,SAAS,SAAS,UAAU,YAAY;AACnG;AAEA,SAAS,YAAY,OAAsB,KAAc,WAA4B;AACnF,QAAM,SAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO;AACxB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,IAAI,YAAY;AAAA,UAChD,IAAI,QAAQ,OAAO,IAAI,GAAG,IAAI,KAAK;AAAA,UACnC,UAAU,KAAK;AAAA,QACjB,CAAC;AACD;AAAA,MACF,KAAK,aAAa;AAChB,cAAM,QAAQ,WAAW,KAAK,QAAQ;AACtC,cAAM,OAAO,OAAO,IAAI,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAC/C,YAAI,QAAQ,CAAC,KAAK,MAAM,OAAO,GAAG;AAChC,gBAAM,WAAW,OAAO,OAAO,SAAS,CAAC;AACzC,gBAAM,SAAS,UAAU,SAAS,UAAU,CAAC,GAAG,SAAS,QAAQ,GAAG,IAAI,IAAI;AAC5E,gBAAM,QAAe;AAAA,YACnB,MAAM;AAAA,YACN;AAAA,YACA,SAAS,OAAO,UAAU,IAAI,cAAc,OAAO,WAAW,IAAI,SAAS;AAAA,UAC7E;AACA,cAAI,UAAU,SAAS,QAAS,QAAO,OAAO,SAAS,CAAC,IAAI;AAAA,cACvD,QAAO,KAAK,KAAK;AAAA,QACxB,MAAO,QAAO,KAAK,EAAE,MAAM,WAAW,KAAK,CAAC;AAC5C;AAAA,MACF;AAAA,MACA,KAAK;AACH,eAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,GAAG,SAAS,IAAI,EAAE,CAAC;AACrD;AAAA,MACF,KAAK;AACH,eAAO,KAAK,UAAU,IAAI,CAAC;AAC3B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,QAAQ,QAAW,OAAO,KAAK,MAAM,CAAC;AAC7E;AAAA,MACF,KAAK,SAAS;AACZ,cAAM,KAAK,GAAG,SAAS,SAAS,EAAE,IAAI,SAAS;AAC/C,cAAM,QAAQ,gBAAgB,IAAI;AAClC,cAAM,MAAM,QAAQ,KAAK;AACzB,cAAM,SAAS,IAAI,WAAW,MAAM,EAAE;AACtC,eAAO,KAAK,EAAE,MAAM,QAAQ,IAAI,OAAO,KAAK,SAAS,YAAY,KAAK,OAAO,MAAM,IAAI,IAAI,CAAC;AAC5F;AAAA,MACF;AAAA,MACA,KAAK;AACH,eAAO,KAAK,EAAE,MAAM,OAAO,CAAC;AAC5B;AAAA,MACF;AACE,eAAO,KAAK,EAAE,MAAM,WAAW,KAAK,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAaA,SAAS,QAAQ,KAAiB,KAAqB;AACrD,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,SAAS,MAAM;AAAA,IAAQ,CAAC,SAC5B,KAAK,SAAS,eAAe,WAAW,KAAK,QAAQ,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;AAAA,EAC3H;AACA,QAAM,QAAQ,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW,KAAK,SAAS,MAAM;AAClF,QAAM,QAAQ,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,WAAW,KAAK,SAAS,UAAU,KAAK,SAAS,MAAM;AACxG,QAAM,SAAS,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,YAAY;AAChE,QAAM,YACJ,OAAO,WAAW,KAClB,CAAC,SACD,OAAO,WAAW,KAClB,QAAQ,OAAO,CAAC,CAAC,KAAK,MACtB,QAAQ,MAAM,OAAO,CAAC,SAAS,SAAS,OAAO,CAAC,CAAC,CAAC,KAAK,MACvD,CAAC,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC;AAGvC,QAAM,WAAW,IAAI,eAAe;AACpC,QAAM,WAAW,MAAM,UAAU,CAAC,SAAS,KAAK,SAAS,aAAa,KAAK,UAAU,QAAQ;AAC7F,MAAI,QAAwB;AAC5B,MAAI,YAAY,KAAK,CAAC,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,aAAa,KAAK,QAAQ,QAAQ,GAAG;AAC5F,UAAM,SAAuD,CAAC;AAC9D,eAAW,QAAQ,MAAM,MAAM,QAAQ,GAAG;AACxC,UAAI,KAAK,SAAS,UAAW,QAAO,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC,EAAE,CAAC;AAAA,UAChE,QAAO,OAAO,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI;AAAA,IAChD;AACA,UAAM,QAAQ,CAAC,UACb,MAAM,MAAM,SAAS,KACrB,QAAQ,MAAM,KAAK,KAAK,MACxB,MAAM,MAAM;AAAA,MACV,CAAC,SAAS,KAAK,SAAS,eAAgB,KAAK,SAAS,UAAU,KAAK,SAAS,UAAU,KAAK,QAAQ,IAAI,KAAK;AAAA,IAChH,KACA,MAAM,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,eAAe,WAAW,KAAK,QAAQ,CAAC,EAAE,UAAU;AACjG,QAAI,OAAO,UAAU,KAAK,OAAO,UAAU,MAAM,OAAO,MAAM,KAAK,EAAG,SAAQ;AAAA,EAChF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,KAAK;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,YAAY,IAAI,MAAM,MAAM,GAAG,QAAQ,IAAI;AAAA,EACxD;AACF;AAGA,SAAS,YAAY,KAAiB,OAA4D;AAChG,QAAM,EAAE,OAAO,QAAQ,MAAM,IAAI;AACjC,QAAM,UAA2B,CAAC;AAClC,MAAI,SAAS;AACb,QAAM,OAAO,CAAC,QAAuB,QAAgB;AACnD,QAAI,CAAC,QAAQ,OAAQ,UAAS;AAC9B,QAAI,CAAC,QAAQ,SAAS,MAAM,EAAG,SAAQ,KAAK,MAAM;AAAA,EACpD;AACA,QAAM,OAAO,OAAO,CAAC,GAAG;AACxB,QAAM,SAAS,OAAO,KAAK,QAAQ,KAAK,SAAS;AACjD,QAAM,SAAS,CAAC,SAAS,CAAC,MAAM;AAEhC,MAAI,MAAM,UAAW,MAAK,SAAS,0BAA0B;AAC7D,MAAI,UAAU,OAAO,WAAW,KAAK,QAAQ,KAAK,SAAS,QAAQ,UAAU,OAAO,SAAS,IAAI;AAC/F,SAAK,aAAa,SAAS,KAAK,KAAK,OAAI,KAAK,MAAM,eAAe,KAAK,QAAQ;AAAA,EAClF;AACA,MAAI,UAAU,OAAO,WAAW,KAAK,QAAQ,KAAK,SAAS,OAAO,SAAS,MAAM,SAAS,KAAK;AAC7F,SAAK,SAAS,oBAAoB,KAAK,QAAQ;AAAA,EACjD;AAEA,QAAM,YAAY,CAAC,CAAC,MAAM,UAAU,QAAQ,MAAM,SAAS,KAAK,MAAM,MAAM,MAAM,UAAU;AAC5F,MAAI,UAAW,MAAK,SAAS,GAAG,MAAM,MAAO,MAAM,qBAAqB;AACxE,MAAI,CAAC,SAAS,OAAO,UAAU,KAAK,SAAS,GAAI,MAAK,YAAY,GAAG,OAAO,MAAM,sBAAsB;AAGxG,MAAI,UAAU,IAAI,WAAW,OAAO,WAAW,KAAK,SAAS,MAAM,IAAI,MAAM,UAAU,GAAG;AACxF,SAAK,aAAa,QAAQ,KAAK,4BAAuB;AAAA,EACxD;AACA,OAAK,SAAS,MAAM;AAGpB,MAAI,MAAM,MAAO,MAAK,SAAS,EAAE;AACjC,MAAI,UAAU,OAAO,UAAU,KAAK,QAAQ,KAAK,SAAS,OAAQ,UAAU,OAAO,SAAS,IAAK,MAAK,aAAa,EAAE;AACrH,MAAI,UAAU,OAAO,UAAU,KAAK,QAAQ,SAAS,KAAK,SAAS,IAAK,MAAK,SAAS,EAAE;AACxF,MAAI,CAAC,SAAS,OAAO,UAAU,KAAK,SAAS,IAAK,MAAK,YAAY,EAAE;AACrE,MAAI,UAAU,OAAO,WAAW,KAAK,QAAQ,KAAK,SAAS,OAAO,IAAI,MAAM,UAAU,EAAG,MAAK,aAAa,EAAE;AAC7G,SAAO,EAAE,SAAS,OAAO;AAC3B;AAEA,SAAS,aAAa,KAAiB,KAAc,OAAwB;AAC3E,QAAM,YAAY,IAAI,UAAU,OAAO,IAAI,OAAO,EAAE,KAAK,IAAI;AAC7D,QAAM,KAAK,IAAI,UAAU,QAAQ,WAAW,IAAI,KAAK,IAAI,QAAQ,gBAAgB,IAAI,KAAK;AAC1F,QAAM,QAAQ,QAAQ,KAAK,GAAG;AAC9B,QAAM,EAAE,SAAS,OAAO,IAAI,YAAY,KAAK,KAAK;AAClD,QAAM,SAAS,IAAI,WAAW,UAAU,EAAE;AAC1C,QAAM,SAAS,UAAU,QAAQ,SAAS,MAAM,IAAI,SAAS,QAAQ,CAAC;AAEtE,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,WAAW,WAAW,MAAM,OAAO;AACrC,aAAS;AAAA,MACP,GAAG,YAAY,MAAM,WAAW,KAAK,EAAE;AAAA,MACvC;AAAA,QACE,MAAM;AAAA,QACN,OAAO,MAAM,MAAM,IAAI,CAAC,UAAU;AAAA,UAChC,IAAI,QAAQ,OAAO,KAAK,OAAO,GAAG,IAAI,KAAK;AAAA,UAC3C,OAAO,KAAK,QAAQ;AAAA,UACpB,QAAQ,YAAY,KAAK,OAAO,KAAK,EAAE;AAAA,QACzC,EAAE;AAAA,MACJ;AAAA,IACF;AAAA,EACF,WAAW,WAAW,WAAW,WAAW,aAAa;AACvD,cAAU,MAAM,OAAO,CAAC;AAExB,QAAI,QAAQ;AACZ,UAAM,OAAO,IAAI,MAAM,OAAO,CAAC,SAAS;AACtC,UAAI,SAAS,KAAK,SAAS,YAAa,QAAO;AAC/C,YAAM,QAAQ,WAAW,KAAK,QAAQ;AACtC,UAAI,OAAO,WAAW,KAAK,MAAM,CAAC,EAAE,MAAM,QAAQ,QAAS,IAAK,QAAO,EAAE,QAAQ;AACjF,aAAO;AAAA,IACT,CAAC;AACD,aAAS,YAAY,MAAM,KAAK,EAAE;AAClC,QAAI,WAAW,QAAS,QAAO,IAAI,eAAe,MAAM;AAAA,EAC1D,OAAO;AACL,aAAS,YAAY,IAAI,OAAO,KAAK,EAAE;AAAA,EACzC;AAEA,QAAM,OAAO,WAAW,UAAU,WAAW,WAAW,cAAc,SAAS;AAC/E,SAAO;AAAA,IACL;AAAA,IACA,OAAO,IAAI,SAAS,YAAY,CAAC;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM;AAAA,IACb,QAAQ,UAAU,WAAW,SAAS,WAAW,MAAM,KAAK,GAAG,MAAM,GAAG,UAAU,KAAK,CAAC,IAAI,UAAU,oBAAoB,EAAE;AAAA,IAC5H,cAAc;AAAA,EAChB;AACF;AAEA,IAAM,WAAW,CAAC,UAAoB,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AAM1F,SAAS,aAAa,OAAgC;AAC3D,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,cAAc,MAAM,eAAe,CAAC;AAC1C,QAAM,QAAQ,KAAK;AACnB,QAAM,WAAW,MAAM,OAAO,CAAC,SAA0B,KAAK,SAAS,SAAS;AAGhF,QAAM,YAAY,SAAS,CAAC,GAAG,UAAU,IAAI,SAAS,CAAC,IAAI;AAC3D,QAAM,kBAAkB,SAAS,OAAO,CAAC,MAAM,MAAM,SAAS;AAC9D,QAAM,eAAe,gBAAgB,SAAS,KAAK,IAAI,GAAG,gBAAgB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI;AAEjG,QAAM,MAAe;AAAA,IACnB,QAAQ,MAAM,UAAU,CAAC;AAAA,IACzB,YAAY,MAAM,cAAc,CAAC;AAAA,IACjC,OAAO,oBAAI,IAAI,CAAC,KAAK,CAAC;AAAA,IACtB;AAAA,IACA,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAEA,QAAM,eAAe,MAAM,UAAU,CAAC,SAAS,KAAK,SAAS,aAAa,SAAS,aAAa,KAAK,UAAU,YAAY;AAC3H,QAAM,YAAY,gBAAgB,IAAI,MAAM,MAAM,GAAG,YAAY,IAAI,OAAO,OAAO,CAAC,SAAS,SAAS,SAAS;AAC/G,QAAM,OAAO,gBAAgB,IAAI,MAAM,MAAM,YAAY,IAAI,CAAC;AAG9D,QAAM,SAAqB,CAAC;AAC5B,QAAM,OAA4B,CAAC;AACnC,MAAI;AACJ,MAAI,cAA+B;AACnC,QAAM,QAAuB,CAAC;AAC9B,MAAI,WAAW;AACf,MAAI,YAAY;AAEhB,QAAM,WAAW,SAAS,YAAY,KAAK,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,YAAY,MAAM;AAC1G,MAAI,UAAU;AACZ,UAAM,YAAsB,EAAE,KAAK,UAAU,KAAK,IAAI,MAAM,IAAI,OAAO,QAAQ,KAAK,OAAU;AAC9F,UAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAI,QAAS,EAAC,WAAW,WAAW,IAAI,CAAC,WAAW,OAAO;AAAA,EAC7D;AAEA,aAAW,QAAQ,UAAU;AAC3B,QAAI,KAAK,SAAS,aAAa;AAC7B,YAAM,QAAQ,WAAW,KAAK,QAAQ;AACtC,UAAI,OAAO;AACT,cAAM,OAAO,MAAM,IAAI,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAC9C,YAAI,KAAK,MAAM,OAAO,GAAG;AACvB,iBAAO,KAAK,GAAG,IAAI;AACnB;AAAA,QACF;AACA,YAAI,CAAC,aAAa,KAAK,WAAW,KAAK,IAAI,WAAW,oBAAoB,OAAO;AAC/E,gBAAM,UAAU,kBAAkB,KAAK,CAAC,CAAC;AACzC,cAAI,SAAS;AACX;AAAC,aAAC,WAAW,WAAW,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO;AAC7C;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,YAAY,KAAK,SAAS,GAAG;AACtC,cAAMC,SAAQ,WAAW,OAAO,IAAI,CAAC;AACrC,YAAI,YAAYA,UAAS,IAAI;AAC3B,eAAK,KAAM,KAAmB,QAAQ;AACtC,uBAAaA;AACb;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,EAAE,KAAK,SAAS,eAAe,WAAW,KAAK,QAAQ,GAAI,YAAW;AAC1E,UAAM,KAAK,IAAI;AAAA,EACjB;AAIA,QAAM,aAAa,SAAS,YAAY,KAAK;AAC7C,QAAM,UAAU,CAAC,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC,CAAC;AACjD,MAAI,CAAC,SAAS;AACZ,UAAM,OAAO,GAAG,MAAM,QAAQ,GAAG,QAAQ;AACzC,SAAK,SAAS;AACd,WAAO,SAAS;AAChB,gBAAY;AAAA,EACd;AAEA,QAAM,cAAc,SAAS,YAAY,WAAW,KAAK,SAAS,YAAY,QAAQ,KAAK,SAAS,YAAY,OAAO;AACvH,MAAI,WAAW,eAAe,CAAC,KAAK,OAAQ,MAAK,KAAK,CAAC,EAAE,MAAM,QAAQ,OAAO,YAAY,CAAC,CAAC;AAE5F,QAAM,QAA2B,WAAW,aAAa,aAAa,CAAC,EAAE,MAAM,QAAQ,OAAO,WAAW,CAAC,IAAI,CAAC;AAC/G,QAAM,eAAe,CAAC,SAAS,YAAY,QAAQ,GAAG,SAAS,YAAY,MAAM,CAAC;AAClF,QAAM,OAAO,YAAY;AACzB,MAAI,gBAAgB,KAAM,cAAa,KAAK,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,WAClE,SAAS,IAAI,EAAG,cAAa,KAAK,SAAS,IAAI,CAAC;AAEzD,QAAM,OAAa;AAAA,IACjB,SAAS,YAAY,cAAc;AAAA,IACnC;AAAA,IACA,WAAW,OAAO,KAAK,EAAE,KAAK;AAAA,IAC9B;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,SAAU,WAAW,aAAa,OAAO,OAAO,EAAE,KAAK,QAAK,KAAM;AAAA,EACpE;AAGA,QAAM,OAAqB,CAAC;AAC5B,MAAI,MAAM,OAAQ,MAAK,KAAK,EAAE,OAAO,MAAM,CAAC;AAC5C,aAAW,QAAQ,MAAM;AACvB,QAAI,KAAK,SAAS,aAAa,KAAK,UAAU,aAAc,MAAK,KAAK,EAAE,SAAS,MAAM,OAAO,CAAC,EAAE,CAAC;AAAA,QAC7F,MAAK,KAAK,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI;AAAA,EAC5C;AACA,QAAM,WAAW,KAAK,IAAI,CAAC,KAAK,UAAU,aAAa,KAAK,KAAK,KAAK,CAAC;AAGvE,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,QAAI,SAAS,CAAC,EAAE,SAAS,UAAU,SAAS,IAAI,CAAC,EAAE,SAAS,OAAQ,UAAS,CAAC,EAAE,OAAO;AAAA,EACzF;AAGA,QAAM,MAAkB,CAAC;AACzB,aAAW,WAAW,UAAU;AAC9B,QAAI,CAAC,QAAQ,UAAW;AACxB,QAAI,KAAK,EAAE,IAAI,QAAQ,IAAI,MAAM,QAAQ,WAAW,OAAO,EAAE,CAAC;AAC9D,UAAM,OAAuC,CAAC;AAC9C,eAAW,SAAS,QAAQ,QAAQ;AAClC,UAAI,MAAM,SAAS,aAAa,MAAM,UAAU,EAAG,MAAK,KAAK,EAAE,IAAI,MAAM,IAAI,MAAM,OAAO,MAAM,QAAQ,EAAE,CAAC;AAC3G,UAAI,MAAM,SAAS,QAAS,YAAW,QAAQ,MAAM,MAAO,MAAK,KAAK,EAAE,IAAI,KAAK,IAAI,MAAM,OAAO,KAAK,KAAK,EAAE,CAAC;AAAA,IACjH;AACA,eAAW,OAAO,KAAM,KAAI,KAAK,EAAE,GAAG,KAAK,OAAO,EAAE,CAAC;AAAA,EACvD;AACA,QAAM,SAAS,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AACnD,QAAM,QAAQ,SAAS,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC,IAAI;AAE9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,KAAK,IAAI,SAAS,KAAK,IAAI,OAAO,CAAC,UAAU,MAAM,UAAU,CAAC,IAAI;AAAA,IAClE,SAAS,UAAU;AAAA,IACnB;AAAA,IACA,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,GAAG,CAAC;AAAA,EAClD;AACF;;;ACpcA,IAAM,SAAS,CAAC,IAAY,SAAiB,IAAY,OAAe,QAAgB,QAAgB,cAAqC;AAAA,EAC3I;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,SAAmC;AAAA,EAC9C,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,KAAK;AAAA,IACH,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,IACzF,MAAM,OAAO,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC1F;AACF;AAEO,IAAM,YAAY,OAAO,OAAO,MAAM;AAiB7C,IAAM,OAAO;AACb,IAAM,cAAc;AACpB,IAAM,OAAO;AACb,IAAM,QAAQ;AAEP,IAAM,eAAmD;AAAA,EAC9D,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,eAAe,KAAK;AAAA,IAC7B,MAAM,iBAAiB,KAAK;AAAA,IAC5B,MAAM;AAAA,IACN,QAAQ,CAAC,sCAAsC,+DAA+D,WAAW;AAAA,IACzH,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,2BAA2B,IAAI;AAAA,IACxC,MAAM,YAAY,IAAI;AAAA,IACtB,MAAM;AAAA,IACN,QAAQ,CAAC,6BAA6B,uBAAuB,WAAW;AAAA,IACxE,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,oBAAoB,IAAI;AAAA,IACjC,MAAM,oBAAoB,IAAI;AAAA,IAC9B,MAAM;AAAA,IACN,QAAQ,CAAC,+BAA+B,mDAAmD,WAAW;AAAA,IACtG,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,uBAAuB,KAAK;AAAA,IACrC,MAAM,oBAAoB,IAAI;AAAA,IAC9B,MAAM;AAAA,IACN,QAAQ,CAAC,oDAAoD,iDAAiD,WAAW;AAAA,IACzH,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,0BAA0B,IAAI;AAAA,IACvC,MAAM,cAAc,IAAI;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ,CAAC,iDAAiD,4DAA4D,WAAW;AAAA,IACjI,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,eAAe,KAAK;AAAA,IAC7B,MAAM,kBAAkB,IAAI;AAAA,IAC5B,MAAM;AAAA,IACN,QAAQ,CAAC,0DAA0D,+CAA+C,WAAW;AAAA,IAC7H,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,kBAAkB,KAAK;AAAA,IAChC,MAAM,kBAAkB,KAAK;AAAA,IAC7B,MAAM;AAAA,IACN,QAAQ,CAAC,+CAA+C,WAAW;AAAA,IACnE,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,WAAW,IAAI;AAAA,IACxB,MAAM,cAAc,IAAI;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ,CAAC,sBAAsB,yBAAyB,WAAW;AAAA,IACnE,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,yBAAyB,KAAK;AAAA,IACvC,MAAM,WAAW,IAAI;AAAA,IACrB,MAAM;AAAA,IACN,QAAQ,CAAC,8DAA8D,0CAA0C,WAAW;AAAA,IAC5H,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,aAAa,IAAI;AAAA,IAC1B,MAAM,kBAAkB,IAAI;AAAA,IAC5B,MAAM;AAAA,IACN,QAAQ,CAAC,mCAAmC,iDAAiD,WAAW;AAAA,IACxG,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,uBAAuB,KAAK;AAAA,IACrC,MAAM,qBAAqB,IAAI;AAAA,IAC/B,MAAM;AAAA,IACN,QAAQ,CAAC,6BAA6B,0DAA0D,WAAW;AAAA,IAC3G,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,iBAAiB,KAAK;AAAA,IAC/B,MAAM,gBAAgB,IAAI;AAAA,IAC1B,MAAM;AAAA,IACN,QAAQ,CAAC,sDAAsD,+CAA+C,WAAW;AAAA,IACzH,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,+BAA+B,IAAI;AAAA,IAC5C,MAAM,cAAc,IAAI;AAAA,IACxB,MAAM;AAAA,IACN,QAAQ,CAAC,iBAAiB,mDAAmD,WAAW;AAAA,IACxF,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM,oBAAoB,IAAI;AAAA,IAC9B,MAAM;AAAA,IACN,QAAQ,CAAC,uCAAuC,iDAAiD;AAAA,IACjG,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,kBAAkB,OAAO,OAAO,YAAY;AAElD,SAAS,eAAe,SAA8B;AAC3D,SAAO,qCAAqC,QAAQ,OAAO,IAAI,CAAC,WAAW,UAAU,MAAM,EAAE,EAAE,KAAK,GAAG,CAAC;AAC1G;AAQO,SAAS,cAAc,OAAsB;AAClD,SAAO,GAAG,MAAM,WAAW,KAAK,MAAM,IAAI,KAAK,aAAa,MAAM,KAAK,EAAE,IAAI;AAC/E;AAGO,SAAS,YAAY,IAA4B;AACtD,QAAM,QAAQ,OAAO,EAAE;AACvB,SAAO,EAAE,SAAS,IAAI,OAAO,MAAM,OAAO,WAAW,MAAM,UAAU;AACvE;AAMO,SAAS,WAAW,MAAc,OAAiE;AACxG,QAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,EAAE,MAAM;AACpD,MAAI,OAAyB;AAC7B,MAAI,YAAY;AAChB,aAAW,SAAS,WAAW;AAC7B,QAAI,SAAU,KAAK,MAAM,MAAM,QAAQ,KAAK,CAAC,GAAG,SAAS,QAAS;AAElE,QAAI,MAAM,OAAO,WAAY,UAAS,KAAK,IAAI,GAAG,MAAM,aAAa,IAAI;AACzE,QAAI,MAAM,OAAO,WAAW,QAAQ,EAAG,UAAS,KAAK,IAAI,KAAK,MAAM,SAAS,IAAI;AACjF,QAAI,QAAQ,UAAW,EAAC,MAAM,SAAS,IAAI,CAAC,MAAM,IAAI,KAAK;AAAA,EAC7D;AACA,SAAO;AACT;AAMO,SAAS,WAAW,MAAc,OAA4D;AACnG,SAAO,YAAY,WAAW,MAAM,KAAK,KAAK,OAAO;AACvD;AAMO,SAAS,UAAU,QAAqB,YAAuC;AACpF,QAAMC,UAAS,OAAO,OAAO,OAAO,EAAE,UAAU;AAChD,QAAM,QAAQ,aAAa,OAAO,KAAK;AACvC,QAAM,SAAS,QAAQ,IAAI,OAAO,aAAa;AAC/C,QAAM,OAAO,uBAAuBA,QAAO,MAAM,SAASA,QAAO,EAAE;AACnE,QAAM,OAA+B;AAAA,IACnC,gBAAgBA,QAAO;AAAA,IACvB,gBAAgBA,QAAO;AAAA,IACvB,UAAUA,QAAO;AAAA,IACjB,qBAAqBA,QAAO;AAAA,IAC5B,aAAa,eAAe,SAASA,QAAO,UAAUA,QAAO;AAAA,IAC7D,wBAAwBA,QAAO;AAAA,IAC/B,aAAaA,QAAO;AAAA,IACpB,wBAAwBA,QAAO;AAAA,IAC/B,eAAeA,QAAO;AAAA,IACtB,0BAA0BA,QAAO;AAAA,IACjC,WAAWA,QAAO;AAAA,IAClB,sBAAsBA,QAAO;AAAA,IAC7B,YAAY;AAAA,IACZ,uBAAuBA,QAAO;AAAA,IAC9B,YAAYA,QAAO;AAAA,IACnB,WAAWA,QAAO;AAAA,IAClB,UAAUA,QAAO;AAAA,IACjB,YAAY,GAAG,OAAO,QAAQ,CAAC,CAAC;AAAA,IAChC,cAAc;AAAA,IACd,YAAYA,QAAO;AAAA,IACnB,YAAYA,QAAO;AAAA,IACnB,iBAAiBA,QAAO;AAAA,IACxB,gBAAgBA,QAAO;AAAA,IACvB,sBAAsB,MAAM;AAAA,IAC5B,mBAAmB,MAAM;AAAA,IACzB,mBAAmB,MAAM;AAAA,IACzB,wBAAwB,OAAO,MAAM,aAAa;AAAA,IAClD,kBAAkB,GAAG,MAAM,QAAQ;AAAA,IACnC,aAAa;AAAA,EACf;AACA,SAAO;AACT;;;ACliBA,IAAMC,SAAQ,oBAAI,IAAwC;AAOnD,SAAS,iBAAiB,SAA2E;AAC1G,SAAO,CAAC,YAAY;AAElB,UAAM,MAAM,GAAG,QAAQ,QAAQ;AAAA,EAAK,KAAK,UAAU,OAAO,CAAC;AAC3D,UAAM,MAAMA,OAAM,IAAI,GAAG;AACzB,QAAI,IAAK,QAAO;AAChB,UAAM,UAAU,MAAM,QAAQ,UAAU;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,QAAQ,QAAQ;AAAA,MAClE,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B,CAAC,EAAE,KAAK,OAAO,aAAa;AAC1B,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,wBAAwB,SAAS,MAAM,EAAE;AAC3E,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,UAAI,CAAC,KAAK,QAAS,OAAM,IAAI,MAAM,oCAAoC;AACvE,aAAO,KAAK;AAAA,IACd,CAAC;AACD,IAAAA,OAAM,IAAI,KAAK,OAAO;AACtB,YAAQ,MAAM,MAAMA,OAAM,OAAO,GAAG,CAAC;AACrC,WAAO;AAAA,EACT;AACF;AAGA,IAAM,cAAyB,CAAC,OAAO,QAAQ,QAAQ,SAAS,WAAW,OAAO;AAElF,IAAM,mBAAuC;AAAA,EAC3C,MAAM;AAAA,EACN,UAAU;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAEA,IAAM,iBAAqC;AAAA,EACzC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAMO,SAAS,eAAe,MAAoB,OAAuB;AACxE,QAAM,WAAW,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,OAAO,EAAE,MAAM,GAAG,EAAE;AAClF,SAAO;AAAA,IACL,KAAK,KAAK,aAAa,UAAU,KAAK,KAAK,SAAS;AAAA,IACpD,SAAS,UAAU,aAAa,SAAS,KAAK,KAAK,CAAC;AAAA,IACpD,YAAY,MAAM,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,EACtD,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AACd;AAGA,IAAM,cAAc;AA8BpB,eAAsB,cACpB,MACA,OACA,UACA,UAAwB,CAAC,GACJ;AACrB,QAAM,YAAY,QAAQ,cAAc;AACxC,QAAM,aAAyB,CAAC;AAGhC,QAAM,QAAiC,CAAC;AACxC,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,SAAS,MACb,QAAQ,aAAa,EAAE,YAAY,EAAE,GAAG,YAAY,KAAK,WAAW,OAAO,EAAE,GAAG,WAAW,IAAI,EAAE,GAAG,SAAS,CAAC,GAAG,OAAO,EAAE,CAAC;AAC7H,QAAM,UAAU,CAAC,KAAa,SAA4B,UAAgD;AACxG,YAAQ,IAAI,GAAG;AACf,UAAM;AAAA,MAAK,MACT,SAAS,SAAS,QAAQ,MAAM,EAC7B,KAAK,OAAO,MAAM,MAAS,EAC3B,KAAK,MAAM;AACV,gBAAQ,OAAO,GAAG;AAClB,YAAI,CAAC,QAAQ,QAAQ,QAAS,QAAO;AAAA,MACvC,CAAC;AAAA,IACL;AAAA,EACF;AAIA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO,eAAe,MAAM,KAAK;AAAA,MACjC,WAAW,EAAE,OAAO,EAAE,MAAM,UAAU,UAAU,OAAO,YAAY,UAAU,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE;AAAA,IACvH;AAAA,IACA,CAAC,EAAE,MAAM,MAAM;AACb,UAAI,OAAO,SAAS,SAAU;AAG9B,YAAM,OAA+B,MAAM,iBAAiB,EAAE,CAAC,MAAM,MAAM,GAAG,MAAM,WAAW;AAC/F,UAAI,OAAO;AACX,UAAI,YAAY;AAChB,iBAAW,MAAM,OAAO,KAAK,IAAI,GAAG;AAClC,cAAM,QAAQ,KAAK,EAAE,KAAK,OAAO,QAAQ,YAAY,cAAc;AACnE,YAAI,MAAM,UAAU,QAAQ,UAAW,EAAC,MAAM,SAAS,IAAI,CAAC,IAAI,KAAK;AAAA,MACvE;AACA,UAAI,CAAC,QAAQ,YAAY,UAAW;AACpC,YAAM,SAAS,OAAO,IAAiB;AACvC,iBAAW,QAAQ,EAAE,SAAS,OAAO,IAAI,OAAO,OAAO,OAAO,WAAW,OAAO,UAAU;AAAA,IAC5F;AAAA,EACF;AAEA,QAAM,QAAQ,KAAK,KAAK;AACxB,MAAI,OAAO;AACT;AAAA,MACE;AAAA,MACA;AAAA,QACE,OAAO;AAAA,UACL,aAAa,KAAK,KAAK,SAAS;AAAA,UAChC,iCAA4B,MAAM,GAAG,YAAY,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC;AAAA,UAC5F,MAAM,QAAQ,SAAS,MAAM,KAAK,KAAK,OAAI,MAAM,KAAK,MAAM;AAAA,UAC5D,wBAAwB,OAAO,KAAK,KAAK,KAAK,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,QACrE,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,QACZ,WAAW;AAAA,UACT,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,UAAU;AAAA,cACR,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,CAAC,EAAE,KAAK,MAAM;AAEZ,YAAI,MAAM,SAAS,UAAU,KAAK,OAAO,IAAK,YAAW,kBAAkB;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,SACjB;AAAA,IAAQ,CAAC,YACR,QAAQ,OACL,QAAQ,CAAC,UAAW,MAAM,SAAS,UAAU,MAAM,MAAM,QAAQ,CAAC,SAAS,KAAK,MAAM,IAAI,CAAC,KAAK,CAAE,EAClG,QAAQ,CAAC,UAAW,MAAM,SAAS,SAAS,CAAC,EAAE,SAAS,MAAM,CAAC,IAAI,CAAC,CAAE;AAAA,EAC3E,EACC,OAAO,CAAC,EAAE,MAAM,MAAM,MAAM,IAAI,WAAW,SAAS,CAAC,EACrD,MAAM,GAAG,QAAQ,aAAa,CAAC;AAElC,aAAW,EAAE,SAAS,MAAM,KAAK,QAAQ;AACvC,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM;AAChC,UAAM,EAAE,IAAI,IAAI;AAChB,QAAI,CAAC,YAAY,SAAS,IAAI,IAAI,EAAG;AACrC,UAAM,QAAQ;AAAA,MACZ,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK;AAAA,MACtC,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,IAAI,CAAC,QAAQ,QAAQ,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC;AAAA,IACnF;AAGA,UAAM,gBAAgB,IAAI,WAAW,SAAS,OAAO,KAAK,IAAI,WAAW,UAAU;AACnF;AAAA,MACE,MAAM;AAAA,MACN;AAAA,QACE,OAAO,YAAY,QAAQ,aAAa,KAAK,KAAK,SAAS;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC;AAAA,QAChF,WAAW,EAAE,SAAS,kBAAkB,GAAI,gBAAgB,EAAE,OAAO,eAAe,IAAI,CAAC,EAAG;AAAA,MAC9F;AAAA,MACA,CAAC,EAAE,SAAS,MAAM,MAAM;AACtB,cAAM,MAAM,CAAC,UAAoB,WAAW,QAAQ,CAAC,GAAG,MAAM,EAAE,IAAI;AACpE,YAAI,SAAS,SAAS,UAAU,QAAQ,OAAO,KAAM,QAAO,IAAI,OAAO;AACvE,YAAI,OAAO,SAAS,OAAQ;AAC5B,YAAI,MAAM,QAAQ,OAAO,IAAI,SAAS,QAAS,KAAI,OAAO;AAAA,iBACjD,MAAM,QAAQ,QAAQ,IAAI,SAAS,QAAS,KAAI,KAAK;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,YAAY;AACzB,aAAS,OAAO,MAAM,MAAM,GAAG,MAAM,OAAO,MAAM,MAAM,GAAG;AACzD,UAAI,QAAQ,QAAQ,QAAS;AAC7B,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACA,SAAO;AAGP,QAAM,MAAM,MAAM,IAAI;AACtB,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,QAAQ,eAAe,EAAE,GAAG,MAAM,CAAC;AAC1E,SAAO;AACT;;;AC1PA,OAAO,uBAAuB;AAC9B,OAAO,eAAe;AACtB,OAAO,gBAAgB;AACvB,OAAO,iBAAiB;AACxB,SAAS,eAAe;AACxB,SAAS,SAAS,iBAAiB;AASnC,IAAM,YAAY,QAAQ,EAAE,IAAI,WAAW,EAAE,IAAI,SAAS,EAAE,IAAI,UAAU,EAAE,IAAI,mBAAmB,CAAC,MAAM,CAAC;AAE3G,IAAM,OAAO,CAAC,KAAa,SACzB,IAAI,OAAO,MAAM,IAAI,6CAA6C,GAAG,EAAE,KAAK,GAAG,GAAG,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI;AAElH,IAAM,iBAAiB,CAAC,SACtB,KACG,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG;AAM1B,SAAS,eAAe,MAAiC;AACvD,QAAM,MAAyB,CAAC;AAChC,QAAM,kBAAkB,KAAK,QAAQ,oBAAoB,EAAE,EAAE,QAAQ,mCAAmC,EAAE;AAC1G,QAAMC,UAAS,gBAAgB,MAAM,YAAY;AACjD,MAAI;AACJ,aAAW,SAASA,SAAQ;AAC1B,QAAI,CAAC,MAAO;AACZ,QAAI,MAAM,WAAW,GAAG,GAAG;AACzB,UAAI,WAAW,KAAK,KAAK,GAAG;AAC1B,cAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,YAAI,CAAC,IAAK;AACV,cAAM,QAAe,EAAE,MAAM,SAAS,KAAK,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,OAAO,OAAO,KAAK,KAAK;AACnH,YAAI,KAAK,OAAO,EAAE,MAAM,QAAQ,KAAK,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,KAAK;AAAA,MACxE,WAAW,UAAU,KAAK,KAAK,GAAG;AAChC,YAAI,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,MAC5B,WAAW,SAAS,KAAK,KAAK,GAAG;AAC/B,eAAO,KAAK,OAAO,MAAM;AAAA,MAC3B,WAAW,SAAS,KAAK,KAAK,GAAG;AAC/B,eAAO;AAAA,MACT;AACA;AAAA,IACF;AACA,UAAM,OAAO,eAAe,KAAK,EAAE,QAAQ,QAAQ,GAAG;AACtD,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI,KAAK,OAAO,EAAE,MAAM,QAAQ,KAAK,MAAM,UAAU,CAAC,EAAE,MAAM,QAAQ,OAAO,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,EACxH;AACA,SAAO;AACT;AAIA,SAAS,mBAAmB,OAAsB,OAAoB,oBAAI,IAAI,GAAgB;AAC5F,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,aAAc,MAAK,IAAI,KAAK,YAAY,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,aACrF,cAAc,KAAM,oBAAmB,KAAK,UAA2B,IAAI;AAAA,EACtF;AACA,SAAO;AACT;AAEA,SAAS,cAAc,UAA6B,MAAsC;AACxF,SAAO,SAAS,QAAQ,CAAC,OAAO,UAA6B;AAG3D,QAAI,MAAM,SAAS,cAAc;AAC/B,YAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,YAAM,aAAa,MAAM,SAAS,UAAU,MAAM,KAAK,KAAK,KAAK;AACjE,UAAI,UAAU,KAAK,MAAM,KAAK,KAAK,WAAY,QAAO,CAAC,EAAE,MAAM,QAAQ,OAAO,IAAI,MAAM,KAAK,IAAI,CAAC;AAAA,IACpG;AACA,QAAI,MAAM,SAAS,OAAQ,QAAO,eAAe,MAAM,KAAK;AAE5D,QAAI,MAAM,SAAS,kBAAkB;AACnC,YAAM,MAAM,KAAK,IAAI,MAAM,UAAU;AACrC,aAAO,MAAM,CAAC,EAAE,MAAM,SAAS,KAAK,IAAI,KAAK,KAAK,MAAM,OAAO,IAAI,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC;AAAA,IAC5F;AACA,QAAI,MAAM,SAAS,iBAAiB;AAClC,YAAM,MAAM,KAAK,IAAI,MAAM,UAAU;AACrC,YAAM,QAAQ,cAAc,MAAM,UAAU,IAAI;AAChD,aAAO,MAAM,CAAC,EAAE,MAAM,QAAQ,KAAK,IAAI,KAAK,OAAO,IAAI,OAAO,UAAU,MAAM,CAAoB,IAAI;AAAA,IACxG;AACA,QAAI,cAAc,OAAO;AACvB,aAAO,CAAC,EAAE,GAAG,OAAO,UAAU,cAAc,MAAM,UAA+B,IAAI,EAAE,CAAoB;AAAA,IAC7G;AACA,WAAO,CAAC,KAAK;AAAA,EACf,CAAC;AACH;AAEA,SAAS,YAAY,OAAsB,MAAkC;AAC3E,SAAO,MAAM,QAAQ,CAAC,SAAwB;AAC5C,QAAI,KAAK,SAAS,QAAQ;AAExB,YAAM,UAAU,8CAA8C,KAAK,KAAK,KAAK;AAC7E,UAAI,SAAS;AACX,cAAMC,YAAW,eAAe,QAAQ,CAAC,CAAC;AAC1C,eAAOA,UAAS,SAAS,CAAC,EAAE,MAAM,WAAW,OAAO,OAAO,QAAQ,CAAC,CAAC,GAAQ,UAAAA,UAAS,CAAC,IAAI,CAAC;AAAA,MAC9F;AACA,YAAM,WAAW,eAAe,KAAK,KAAK;AAC1C,aAAO,SAAS,SAAS,CAAC,EAAE,MAAM,aAAa,SAAS,CAAqB,IAAI,CAAC;AAAA,IACpF;AACA,QAAI,KAAK,SAAS,UAAU,KAAK,SAAS,aAAc,QAAO,CAAC;AAChE,QAAI,KAAK,SAAS,eAAe,KAAK,SAAS,WAAW;AACxD,YAAM,WAAW,cAAc,KAAK,UAAU,IAAI;AAClD,aAAO,SAAS,SAAS,CAAC,EAAE,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC;AAAA,IACtD;AACA,QAAI,KAAK,SAAS,YAAa,QAAO,CAAC,EAAE,GAAG,MAAM,UAAU,cAAc,KAAK,UAAU,IAAI,EAAE,CAAC;AAChG,QAAI,cAAc,MAAM;AACtB,aAAO,CAAC,EAAE,GAAG,MAAM,UAAU,YAAY,KAAK,UAA2B,IAAI,EAAE,CAAgB;AAAA,IACjG;AACA,WAAO,CAAC,IAAI;AAAA,EACd,CAAC;AACH;AAEO,SAAS,cAAc,UAAkC;AAC9D,QAAM,OAAO,UAAU,MAAM,QAAQ;AACrC,MAAI,cAA2B,CAAC;AAChC,QAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,MAAI,OAAO,SAAS,QAAQ;AAC1B,QAAI;AACF,YAAM,OAAO,UAAU,MAAM,KAAK;AAClC,UAAI,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,EAAG,eAAc;AAAA,IAC9E,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,YAAY,KAAK,UAAU,mBAAmB,KAAK,QAAQ,CAAC,EAAE,GAAG,YAAY;AACnH;;;ACzIA,SAAS,mBAAyE;;;ACQlF,IAAM,WAAW,CAAC,MAAe,KAAK,UAAU,IAAI,UAAU,IAAI,SAAS,UAAU;AACrF,IAAM,aAAa,CAAC,MAAe,KAAK,WAAY,QAAQ,IAAI,QAAQ,MAAM,IAAI,OAAO;AAEzF,SAAS,UAAU,KAAuC;AACxD,QAAM,IAAI,IAAI,QAAQ,MAAM,EAAE;AAC9B,SAAO,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,SAAS,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC;AAC7E;AAEA,SAAS,gBAAgB,CAAC,GAAG,GAAG,CAAC,GAAuD;AACtF,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,QAAM,IAAI,KAAK,KAAK,eAAe,IAAI,eAAe,IAAI,eAAe,CAAC;AAC1E,SAAO;AAAA,IACL,eAAe,IAAI,cAAc,IAAI,eAAe;AAAA,IACpD,eAAe,IAAI,cAAc,IAAI,eAAe;AAAA,IACpD,eAAe,IAAI,eAAe,IAAI,cAAc;AAAA,EACtD;AACF;AAEO,SAAS,QAAQ,KAAoB;AAC1C,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,gBAAgB,UAAU,GAAG,CAAC;AAChD,SAAO,EAAE,GAAG,GAAG,KAAK,MAAM,GAAG,CAAC,GAAG,IAAK,KAAK,MAAM,GAAG,CAAC,IAAI,MAAO,KAAK,KAAK,OAAO,IAAI;AACvF;AAEA,SAAS,gBAAgB,EAAE,GAAG,GAAG,EAAE,GAAoC;AACrE,QAAM,IAAI,IAAI,KAAK,IAAK,IAAI,KAAK,KAAM,GAAG;AAC1C,QAAM,IAAI,IAAI,KAAK,IAAK,IAAI,KAAK,KAAM,GAAG;AAC1C,QAAM,MAAM,IAAI,eAAe,IAAI,eAAe,MAAM;AACxD,QAAM,MAAM,IAAI,eAAe,IAAI,eAAe,MAAM;AACxD,QAAM,MAAM,IAAI,eAAe,IAAI,cAAc,MAAM;AACvD,SAAO;AAAA,IACL,eAAe,KAAK,eAAe,KAAK,eAAe;AAAA,IACvD,gBAAgB,KAAK,eAAe,KAAK,eAAe;AAAA,IACxD,gBAAgB,KAAK,eAAe,KAAK,cAAc;AAAA,EACzD;AACF;AAEA,IAAM,UAAU,CAAC,QAAkB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAW,KAAK,MAAM;AAGxE,SAAS,UAAU,OAAsB;AAC9C,MAAI,EAAE,EAAE,IAAI;AACZ,MAAI,CAAC,QAAQ,gBAAgB,KAAK,CAAC,GAAG;AACpC,QAAI,MAAM;AACV,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,WAAK,MAAM,QAAQ;AACnB,UAAI,QAAQ,gBAAgB,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,EAAG,OAAM;AAAA,UAChD,QAAO;AAAA,IACd;AACA,QAAI;AAAA,EACN;AACA,QAAM,UAAU,CAAC,MACf,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAC/E,SAAS,EAAE,EACX,SAAS,GAAG,GAAG;AACpB,SAAO,IAAI,gBAAgB,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;AACnE;AAEA,IAAM,YAAY,CAAC,QAAgB;AACjC,QAAM,CAAC,GAAG,GAAG,CAAC,IAAI,UAAU,GAAG;AAC/B,SAAO,SAAS,IAAI,SAAS,IAAI,SAAS;AAC5C;AAGO,SAAS,SAAS,GAAW,GAAmB;AACrD,QAAM,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAClE,UAAQ,KAAK,SAAS,KAAK;AAC7B;AAIA,IAAM,UAAsC;AAAA,EAC1C,QAAQ;AAAA,IACN,CAAC,UAAU,UAAU,SAAS;AAAA,IAC9B,CAAC,UAAU,UAAU,QAAQ;AAAA,IAC7B,CAAC,UAAW,WAAW,QAAQ;AAAA,EACjC;AAAA,EACA,QAAQ;AAAA,IACN,CAAC,UAAU,UAAU,SAAS;AAAA,IAC9B,CAAC,UAAU,UAAU,QAAQ;AAAA,IAC7B,CAAC,UAAU,SAAS,QAAQ;AAAA,EAC9B;AACF;AAEA,SAAS,SAAS,KAAa,QAA0C;AACvE,QAAM,MAAM,UAAU,GAAG;AACzB,SAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AACnH;AAGO,SAAS,OAAO,GAAW,GAAW,QAAyB;AACpE,QAAM,IAAI,gBAAgB,SAAS,SAAS,GAAG,MAAM,IAAI,UAAU,CAAC,CAAC;AACrE,QAAM,IAAI,gBAAgB,SAAS,SAAS,GAAG,MAAM,IAAI,UAAU,CAAC,CAAC;AACrE,SAAO,MAAM,KAAK,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/D;AAGO,IAAM,cAAc,CAAC,GAAW,MAAc,KAAK,IAAI,OAAO,GAAG,GAAG,QAAQ,GAAG,OAAO,GAAG,GAAG,QAAQ,CAAC;AAErG,IAAM,gBAAgB;AAAA;AAAA,EAE3B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE;AAAA;AAAA,EAEhD,aAAa;AAAA;AAAA,EAEb,WAAW;AAAA;AAAA,EAEX,aAAa;AAAA;AAAA,EAEb,aAAa;AACf;AAiBO,SAAS,aAAa,SAAmB,MAAwB,SAAgC;AACtG,QAAM,CAAC,IAAI,EAAE,IAAI,cAAc,KAAK,IAAI;AACxC,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,QAAQ,CAAC,EAAE,IAAI,MAAM,QAAQ,CAAC,EAAE,IAAI,EAAE;AAC5E,QAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,QAAQ,CAAC,EAAE,IAAI,cAAc,WAAW;AAChF,MAAI,WAAW;AACf,MAAI,cAAc;AAClB,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,eAAW,KAAK,IAAI,UAAU,YAAY,QAAQ,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;AACrE,kBAAc,KAAK,IAAI,aAAa,OAAO,QAAQ,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;AAAA,EACxE;AACA,QAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,SAAS,GAAG,OAAO,IAAI,cAAc,WAAW;AAC1F,SAAO;AAAA,IACL,IAAI,CAAC,QAAQ,UAAU,CAAC,UAAU,UAAU,YAAY,cAAc,aAAa,eAAe,cAAc;AAAA,IAChH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADjJA,IAAM,YAAY;AAAA,EAChB,OAAO,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC9F,MAAM,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAC/F;AAEA,IAAM,QAAQ;AACd,IAAMC,SAAQ,oBAAI,IAAsB;AAUjC,SAAS,aAAa,QAAgB,SAAiB,MAA4B;AACxF,QAAM,MAAM,GAAG,MAAM,IAAI,OAAO,IAAI,IAAI;AACxC,QAAM,MAAMA,OAAM,IAAI,GAAG;AACzB,MAAI,IAAK,QAAO;AAEhB,QAAM,CAAC,IAAI,EAAE,IAAI,cAAc,KAAK,IAAI;AACxC,QAAM,UAAU,CAAC,QAAgB,SAAS,KAAK,OAAO,KAAK,cAAc;AACzE,QAAM,SAAS,QAAQ,MAAM;AAE7B,QAAM,MAAM,OAAO,IAAI,OAAO,MAAM,OAAO;AAK3C,MAAI,SAAS;AACb,MAAI,UAAU;AACd,WAAS,QAAQ,GAAG,SAAS,IAAI,SAAS,GAAG;AAC3C,eAAW,KAAK,QAAQ,CAAC,MAAM,OAAO,MAAM,KAAK,IAAI,CAAC,GAAG,GAAG;AAC1D,eAAS,IAAI,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM;AACjD,cAAM,MAAM,UAAU,EAAE,GAAG,GAAG,KAAK,IAAI,OAAO,GAAG,IAAI,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC;AAC5E,YAAI,QAAQ,GAAG,EAAE,IAAI,cAAc,cAAc,QAAS,CAAC,QAAQ,GAAG,EAAG;AACzE,cAAM,WAAW,KAAK,IAAI,IAAI,OAAO,CAAC,IAAI,IAAI,QAAQ;AACtD,YAAI,WAAW,QAAS,EAAC,QAAQ,OAAO,IAAI,CAAC,KAAK,QAAQ;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,UAAU,CAAC,MAAM,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,MAAM,IAAI;AAC7E,QAAM,YAAY,KAAK,IAAI,MAAM,KAAK,IAAI,OAAO,QAAQ,UAAU,MAAM,EAAE,CAAC,CAAC;AAE7E,MAAI,SAA0B;AAC9B,aAAW,UAAU,CAAC,WAAW,YAAY,MAAM,YAAY,MAAM,IAAI,GAAG;AAC1E,QAAI,CAAC,OAAQ;AACb,UAAM,aAAuB,CAAC;AAC9B,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK,IAAI;AAChC,iBAAW,KAAK,QAAQ;AACtB,cAAM,MAAM,UAAU,EAAE,GAAG,GAAG,QAAQ,EAAE,CAAC;AACzC,YAAI,QAAQ,GAAG,EAAE,KAAK,cAAc,cAAc,QAAS,QAAQ,GAAG,EAAG,YAAW,KAAK,GAAG;AAAA,MAC9F;AAAA,IACF;AACA,UAAM,SAAS,CAAC,MAAM;AACtB,WAAO,OAAO,SAAS,OAAO;AAC5B,YAAM,WAAW,OAAO,OAAO,SAAS,CAAC;AACzC,UAAI,OAAO;AACX,UAAI,YAAY;AAChB,iBAAW,aAAa,YAAY;AAClC,YAAI,OAAO,SAAS,SAAS,EAAG;AAEhC,YAAI,QAAQ,KAAK,IAAI,YAAY,UAAU,SAAS,IAAI,cAAc,WAAW,OAAO,UAAU,SAAS,IAAI,cAAc,WAAW;AACxI,mBAAW,SAAS,QAAQ;AAC1B,kBAAQ,KAAK,IAAI,OAAO,YAAY,OAAO,SAAS,IAAI,GAAG,OAAO,OAAO,SAAS,IAAI,EAAE;AAAA,QAC1F;AACA,YAAI,QAAQ,UAAW,EAAC,MAAM,SAAS,IAAI,CAAC,WAAW,KAAK;AAAA,MAC9D;AACA,UAAI,CAAC,KAAM;AACX,aAAO,KAAK,IAAI;AAAA,IAClB;AACA,QAAI,OAAO,WAAW,SAAS,aAAa,QAAQ,MAAM,OAAO,EAAE,IAAI;AACrE,eAAS;AACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,UAAU,UAAU,IAAI;AACxC,EAAAA,OAAM,IAAI,KAAK,OAAO;AACtB,SAAO;AACT;AAGA,IAAM,SAA6C;AAAA,EACjD,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AACR;AAEA,SAASC,QAAO,SAAwB,MAAkB,OAAmB,WAAmB,YAA+C;AAC7I,QAAM,MAAM,CAAC,WAAmB,uBAAuB,QAAQ,EAAE,IAAI,MAAM,MAAM,QAAQ,EAAE;AAC3F,QAAM,SAAS,aAAa,QAAQ,QAAQ,QAAQ,IAAI,IAAI;AAC5D,QAAM,OAAO,OAAO,CAAC;AAGrB,QAAM,MAAM,CAAC,QAAQ,IAAI,QAAQ,OAAO,QAAQ,IAAI,QAAQ,OAAO,QAAQ,IAAI,QAAQ,KAAK;AAC5F,QAAM,QAAQ,KAAK,OAAO,IAAI,aAAa,CAAC;AAC5C,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,SAAS,QAAQ;AAAA,IACjB,MAAM,QAAQ;AAAA,IACd,WAAW,QAAQ;AAAA,IACnB,MAAM,IAAI,EAAE;AAAA,IACZ,MAAM,IAAI,EAAE;AAAA,IACZ,QAAQ;AAAA,IACR,cAAc,UAAU,aAAa,QAAQ,KAAK,IAAI,EAAE;AAAA,IACxD,UAAU,UAAU,aAAa,QAAQ,KAAK,IAAI,EAAE;AAAA,IACpD,SAAS,UAAU,aAAa,MAAM;AAAA,IACtC,UAAU,UAAU,aAAa,QAAQ,KAAK;AAAA,IAC9C,UAAU,UAAU,aAAa,QAAQ,KAAK,IAAI,EAAE;AAAA,IACpD,cAAc,QAAQ;AAAA,IACtB,WAAW,UAAU,aAAa,QAAQ,KAAK,uBAAuB,IAAI;AAAA,IAC1E,SAAS,UAAU,aAAa,QAAQ,KAAK,uBAAuB,IAAI;AAAA,IACxE,WAAW,QAAQ;AAAA,IACnB,aAAa,UAAU,aAAa,QAAQ,KAAK;AAAA,IACjD,WAAW,UAAU,aAAa,QAAQ,KAAK,uBAAuB,IAAI;AAAA,IAC1E,eAAe,UAAU,SAAS,yBAAyB,UAAU,aAAa,QAAQ,KAAK;AAAA,IAC/F,YACE,UAAU,SACN,mCAAmC,QAAQ,EAAE,IAAI,SAAS,SAAS,IAAI,EAAE,oBACzE;AAAA,IACN,mBAAmB,QAAQ;AAAA,IAC3B,aAAa,QAAQ;AAAA,IACrB,eAAe;AAAA,IACf,WAAW,QAAQ;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,IACR,YAAY,UAAU,aAAa,IAAI,UAAU,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI;AAAA,IAC/E,QAAQ;AAAA,EACV;AACF;AAMO,SAAS,cAAc,QAAiC;AAC7D,QAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAM,QAAQ,aAAa,OAAO,KAAK;AACvC,QAAM,SAAS,OAAO,MAAM,KAAK;AACjC,QAAM,OAAO,MAAM,UAAU,aAAa,MAAM,OAAO,MAAM;AAC7D,SAAO,YAAY,UAAU,WAAW;AAAA;AAAA,IAEtC,IAAI,UAAU,YAAY,OAAO,OAAO;AAAA,IACxC,MAAM,MAAM;AAAA,IACZ,OAAOA,QAAO,MAAM,OAAO,SAAS,MAAM,OAAO,OAAO,WAAW,IAAI;AAAA,IACvE,MAAMA,QAAO,MAAM,MAAM,QAAQ,MAAM,OAAO,OAAO,WAAW,IAAI;AAAA,EACtE,CAAC;AACH;;;AEhKA,SAAS,eAAe,kBAAsC;AAqB9D,IAAM,UAAU,cAAsC,IAAI;AAEnD,IAAM,mBAAmB,QAAQ;AAEjC,SAAS,cAA+B;AAC7C,QAAM,QAAQ,WAAW,OAAO;AAChC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,mEAAmE;AAC/F,SAAO;AACT;;;AC7BA,OAAO,WAAW;AAElB,SAAS,gBAAgC;;;ACDzC,SAAS,QAAQ,sBAAsB;AACvC,SAAS,WAAW,gBAAgB;AACpC,SAAS,SAAS,gBAAgC;;;ACLlD,SAAS,UAAU,uBAAuB;AAC1C,SAAS,WAA8B;AA+CnC;AA5CJ,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SACE;AAAA,QACF,WACE;AAAA,QACF,OACE;AAAA,QACF,aACE;AAAA,QACF,MAAM;AAAA,MACR;AAAA,MACA,MAAM;AAAA,QACJ,SACE;AAAA,QACF,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,WACE;AAAA,QACF,WACE;AAAA,QACF,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,OAAO;AAAA,EACd;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAgE;AAC9D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,eAAe,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,MACzD,GAAG;AAAA;AAAA,EACN;AAEJ;;;ADnCI,gBAAAC,MAkBA,YAlBA;AAVJ,IAAM,WAAW,eAAe,MAAM;AAEtC,IAAM,UAAkC,EAAE,IAAI,QAAQ,OAAO,QAAQ,KAAK,QAAQ,SAAS,QAAQ,KAAK,QAAQ,KAAK,cAAc,KAAK,cAAc,MAAM,OAAO,KAAK,OAAO,KAAK,MAAM;AAE1L,SAAS,QAAQ,MAAoC,KAAwB;AAC3E,MAAI,KAAK,SAAS,OAAQ,QAAO,KAAK;AACtC,MAAI,KAAK,SAAS,UAAW,QAAO;AACpC,QAAM,UAAU;AAChB,QAAM,YAAY,QAAQ,YAAY;AACtC,SACE,gBAAAA,KAAC,UAAe,WAAW,MAAM,QAAQ,SAAS,IAAI,UAAU,KAAK,GAAG,IAAI,QACzE,kBAAQ,SAAS,IAAI,OAAO,KADpB,GAEX;AAEJ;AAEO,SAAS,WAAW,EAAE,MAAM,OAAO,UAAU,GAAyE;AAC3H,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,OAAO,YAAY;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,OAAO,SAAS,aAAa,KAAK,IAAI,IAAI;AAC9E,gBAAU,IAAI;AACd,iBAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAAA,IACzC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SACE,qBAAC,UAAO,SAAQ,SAAQ,MAAK,WAAU,SAAS,MAAM,cAAY,SAAS,WAAW,OAAO,OAAO,OAAO,WAAW,GAAG,yBAAyB,SAAS,GACxJ;AAAA,aAAS,gBAAAA,KAAC,aAAU,IAAK,gBAAAA,KAAC,YAAS;AAAA,IACpC,gBAAAA,KAAC,UAAK,WAAU,WAAU,MAAK,UAC5B,mBAAS,WAAW,IACvB;AAAA,KACF;AAEJ;AAEO,SAAS,UAAU,EAAE,MAAM,MAAM,GAAqC;AAC3E,QAAM,WAAW,OAAQ,QAAQ,KAAK,YAAY,CAAC,KAAK,KAAK,YAAY,IAAK;AAC9E,QAAM,OAAO,QAAqB,MAAM;AACtC,QAAI,CAAC,YAAY,CAAC,SAAS,WAAW,QAAQ,EAAG,QAAO;AACxD,QAAI;AACF,aAAO,SAAS,UAAU,UAAU,KAAK;AAAA,IAC3C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,UAAU,KAAK,CAAC;AAEpB,SACE,qBAAC,YAAO,WAAU,sBAChB;AAAA,yBAAC,gBACC;AAAA,sBAAAA,KAAC,UAAM,kBAAQ,QAAO;AAAA,MACtB,gBAAAA,KAAC,cAAW,MAAM,OAAO,OAAM,aAAY;AAAA,OAC7C;AAAA,IACA,gBAAAA,KAAC,SAAI,UAAU,GACb,0BAAAA,KAAC,UAAK,WAAU,QAAQ,iBAAO,KAAK,SAAS,IAAI,OAAO,IAAI,OAAM,GACpE;AAAA,KACF;AAEJ;;;ADhDI,SAkDK,YAAAC,WAlDL,OAAAC,MAsFQ,QAAAC,aAtFR;AAZJ,IAAM,WAAW;AAGV,SAAS,QAAQ,KAAiC;AACvD,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,SAAS,KAAK,OAAO,KAAK,CAAC,uBAAuB,KAAK,OAAO,EAAG,QAAO;AAC5E,SAAO;AACT;AAEO,SAAS,SAAS,EAAE,OAAO,QAAQ,GAAyC;AACjF,QAAM,OAAO,MAAM,eAAe,OAAO,EAAE,aAAa,SAAS,cAAc,OAAO,QAAQ,gBAAgB,CAAC;AAC/G,SAAO,UACL,gBAAAD,KAAC,SAAI,WAAU,kBAAiB,yBAAyB,EAAE,QAAQ,KAAK,GAAG,IAE3E,gBAAAA,KAAC,UAAK,yBAAyB,EAAE,QAAQ,KAAK,GAAG;AAErD;AAEO,SAAS,OAAO,EAAE,MAAM,GAAiC;AAC9D,QAAM,EAAE,WAAW,IAAI,YAAY;AACnC,QAAM,SAAS,CAAC,MAAuB,QAA2B;AAChE,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,KAAK;AAAA,MACd,KAAK;AACH,eAAO,gBAAAA,KAAC,QAAc,eAAK,SAAS,IAAI,MAAM,KAA9B,GAAgC;AAAA,MAClD,KAAK;AACH,eAAO,gBAAAA,KAAC,YAAkB,eAAK,SAAS,IAAI,MAAM,KAA9B,GAAgC;AAAA,MACtD,KAAK;AACH,eAAO,gBAAAA,KAAC,SAAe,eAAK,SAAS,IAAI,MAAM,KAA9B,GAAgC;AAAA,MACnD,KAAK;AACH,eAAO,gBAAAA,KAAC,UAAgB,eAAK,SAAX,GAAiB;AAAA,MACrC,KAAK;AACH,eAAO,gBAAAA,KAAC,UAAQ,GAAK;AAAA,MACvB,KAAK,QAAQ;AACX,cAAM,OAAO,QAAQ,KAAK,GAAG;AAC7B,cAAM,WAAW,CAAC,CAAC,QAAQ,YAAY,KAAK,IAAI;AAChD,eACE,gBAAAA,KAAC,OAAY,MAAY,OAAO,KAAK,SAAS,QAAY,GAAI,WAAW,EAAE,QAAQ,UAAU,KAAK,sBAAsB,IAAI,CAAC,GAC1H,eAAK,SAAS,IAAI,MAAM,KADnB,GAER;AAAA,MAEJ;AAAA,MACA,KAAK,SAAS;AACZ,cAAM,MAAM,QAAQ,WAAW,KAAK,GAAG,CAAC;AAExC,eAAO,MAAM,gBAAAA,KAAC,SAAc,KAAU,KAAK,KAAK,OAAO,IAAI,OAAO,KAAK,SAAS,QAAW,SAAQ,QAAO,WAAU,sBAA7F,GAAgH,IAAK;AAAA,MAC9I;AAAA,MACA,KAAK;AACH,eAAO,gBAAAA,KAAC,YAAmB,OAAO,KAAK,SAAjB,GAAwB;AAAA,MAChD,KAAK;AACH,eACE,gBAAAA,KAAC,SACC,0BAAAA,KAAC,OAAE,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI,SAAS,KAAK,UAAU,IAAI,cAAY,YAAY,KAAK,SAAS,KAAK,UAAU,IACrH,eAAK,SAAS,KAAK,YACtB,KAHQ,GAIV;AAAA,MAEJ;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACA,SAAO,gBAAAA,KAAAD,WAAA,EAAG,gBAAM,IAAI,MAAM,GAAE;AAC9B;AAGO,SAAS,KAAK,EAAE,MAAM,GAA6B;AACxD,SACE,gBAAAC,KAAAD,WAAA,EACG,gBAAM,IAAI,CAAC,MAAM,UAChB,gBAAAC,KAAC,YAAqB,QAAP,KAAmB,CACnC,GACH;AAEJ;AAEO,SAAS,SAAS,EAAE,KAAK,GAA0B;AACxD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aACE,gBAAAA,KAAC,OACC,0BAAAA,KAAC,UAAO,OAAO,KAAK,UAAU,GAChC;AAAA,IAEJ,KAAK,WAAW;AACd,YAAM,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,QAAQ,CAAC,CAAC;AAC3C,aACE,gBAAAA,KAAC,OAAI,WAAU,kBACb,0BAAAA,KAAC,UAAO,OAAO,KAAK,UAAU,GAChC;AAAA,IAEJ;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,MAAM,KAAK,UAAU,OAAO;AAClC,YAAM,OAAO,KAAK,SAAS,KAAK,CAAC,SAAS,KAAK,WAAW,IAAI;AAC9D,aACE,gBAAAA,KAAC,OAAI,OAAO,KAAK,UAAW,KAAK,SAAS,SAAa,QAAW,WAAW,OAAO,cAAc,QAC/F,eAAK,SAAS,IAAI,CAAC,MAAM,UACxB,gBAAAC,MAAC,QAAe,gBAAc,KAAK,WAAW,QAC3C;AAAA,aAAK,WAAW,QACf,gBAAAD,KAAC,WAAM,MAAK,YAAW,SAAS,KAAK,SAAS,UAAQ,MAAC,UAAQ,MAAC,cAAY,KAAK,UAAU,SAAS,YAAY;AAAA,QAElH,gBAAAA,KAAC,YAAS,OAAO,KAAK,UAAU;AAAA,WAJzB,KAKT,CACD,GACH;AAAA,IAEJ;AAAA,IACA,KAAK;AACH,aACE,gBAAAA,KAAC,gBACC,0BAAAA,KAAC,QAAK,OAAO,KAAK,UAAU,GAC9B;AAAA,IAEJ,KAAK;AACH,aAAO,gBAAAA,KAAC,aAAU,MAAM,KAAK,QAAQ,QAAW,OAAO,KAAK,OAAO;AAAA,IACrE,KAAK;AACH,aAAO,gBAAAA,KAAC,YAAS,OAAO,KAAK,OAAO,SAAO,MAAC;AAAA,IAC9C,KAAK;AACH,aAAO,gBAAAA,KAAC,QAAG;AAAA,IACb,KAAK;AACH,aACE,gBAAAC,MAAC,SAAI,WAAU,gBAAe,IAAI,MAAM,KAAK,UAAU,IACrD;AAAA,wBAAAD,KAAC,OAAE,MAAM,UAAU,KAAK,UAAU,IAAI,cAAW,qBAC9C,eAAK,SAAS,KAAK,YACtB;AAAA,QACA,gBAAAA,KAAC,SACC,0BAAAA,KAAC,QAAK,OAAO,KAAK,UAAU,GAC9B;AAAA,SACF;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA,KAAC,SAAI,WAAU,oBACb,0BAAAA,KAAC,WACC,0BAAAA,KAAC,WACE,eAAK,SAAS,IAAI,CAAC,KAAK,MACvB,gBAAAA,KAAC,QACE,cAAI,SAAS,IAAI,CAAC,MAAM,MAAM;AAC7B,cAAM,OAAO,MAAM,IAAI,OAAO;AAC9B,eACE,gBAAAA,KAAC,QACC,0BAAAA,KAAC,UAAO,OAAO,KAAK,UAAU,KADrB,CAEX;AAAA,MAEJ,CAAC,KARM,CAST,CACD,GACH,GACF,GACF;AAAA,IAEJ;AACE,aAAO;AAAA,EACX;AACF;AAGO,SAAS,SAAS,EAAE,MAAM,GAA6B;AAC5D,SACE,gBAAAA,KAAAD,WAAA,EACG,gBAAM;AAAA,IAAI,CAAC,MAAM,UAChB,KAAK,SAAS,cACZ,gBAAAE,MAAC,YACE;AAAA,cAAQ,KAAK,gBAAAD,KAAC,UAAK,WAAU,gBAAe;AAAA,MAC7C,gBAAAA,KAAC,UAAO,OAAO,KAAK,UAAU;AAAA,SAFjB,KAGf,IAEA,gBAAAA,KAAC,YAAqB,QAAP,KAAmB;AAAA,EAEtC,GACF;AAEJ;;;AGnLA,SAAS,aAAAE,YAAW,YAAAC,iBAAgB;;;ACApC,YAAY,WAAW;AAEvB,OAAO,sBAEA;AAGP,SAAS,iBAAiB,wBAAwB;AAgH5C,gBAAAC,MA8DF,QAAAC,aA9DE;AAzFN,IAAM,kBAAwB,oBAA2C,IAAI;AAE7E,SAAS,cAAc;AACrB,QAAM,UAAgB,iBAAW,eAAe;AAEhD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,SAAO;AACT;AAEA,SAAS,SAAS;AAAA,EAChB,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAgD;AAC9C,QAAM,CAAC,aAAa,GAAG,IAAI;AAAA,IACzB;AAAA,MACE,GAAG;AAAA,MACH,MAAM,gBAAgB,eAAe,MAAM;AAAA,IAC7C;AAAA,IACA;AAAA,EACF;AACA,QAAM,CAAC,eAAe,gBAAgB,IAAU,eAAS,KAAK;AAC9D,QAAM,CAAC,eAAe,gBAAgB,IAAU,eAAS,KAAK;AAE9D,QAAM,WAAiB,kBAAY,CAACC,SAAqB;AACvD,QAAI,CAACA,KAAK;AACV,qBAAiBA,KAAI,cAAc,CAAC;AACpC,qBAAiBA,KAAI,cAAc,CAAC;AAAA,EACtC,GAAG,CAAC,CAAC;AAEL,QAAM,aAAmB,kBAAY,MAAM;AACzC,SAAK,WAAW;AAAA,EAClB,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,aAAmB,kBAAY,MAAM;AACzC,SAAK,WAAW;AAAA,EAClB,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,gBAAsB;AAAA,IAC1B,CAAC,UAA+C;AAC9C,UAAI,MAAM,QAAQ,aAAa;AAC7B,cAAM,eAAe;AACrB,mBAAW;AAAA,MACb,WAAW,MAAM,QAAQ,cAAc;AACrC,cAAM,eAAe;AACrB,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,CAAC,YAAY,UAAU;AAAA,EACzB;AAEA,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,OAAO,CAAC,OAAQ;AACrB,WAAO,GAAG;AAAA,EACZ,GAAG,CAAC,KAAK,MAAM,CAAC;AAEhB,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,IAAK;AAEV,aAAS,GAAG;AACZ,QAAI,GAAG,UAAU,QAAQ;AACzB,QAAI,GAAG,UAAU,QAAQ;AAEzB,WAAO,MAAM;AACX,WAAK,IAAI,UAAU,QAAQ;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,KAAK,QAAQ,CAAC;AAElB,SACE,gBAAAF;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,aACE,gBAAgB,MAAM,SAAS,MAAM,aAAa;AAAA,QACpD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,kBAAkB;AAAA,UAClB,WAAW,GAAG,YAAY,SAAS;AAAA,UACnC,MAAK;AAAA,UACL,wBAAqB;AAAA,UACrB,aAAU;AAAA,UACT,GAAG;AAAA,UAEH;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC7E,QAAM,EAAE,aAAa,YAAY,IAAI,YAAY;AAEjD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAU;AAAA,MACV,aAAU;AAAA,MAEV,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,gBAAgB,eAAe,UAAU;AAAA,YACzC;AAAA,UACF;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC1E,QAAM,EAAE,YAAY,IAAI,YAAY;AAEpC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,wBAAqB;AAAA,MACrB,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA,gBAAgB,eAAe,SAAS;AAAA,QACxC;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAwC;AACtC,QAAM,EAAE,aAAa,YAAY,cAAc,IAAI,YAAY;AAE/D,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,gBAAgB,eACZ,+BACA;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC;AAAA,MACX,SAAS;AAAA,MACR,GAAG;AAAA,MAEJ;AAAA,wBAAAD,KAAC,mBAAgB;AAAA,QACjB,gBAAAA,KAAC,UAAK,WAAU,WAAU,4BAAc;AAAA;AAAA;AAAA,EAC1C;AAEJ;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAwC;AACtC,QAAM,EAAE,aAAa,YAAY,cAAc,IAAI,YAAY;AAE/D,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,gBAAgB,eACZ,gCACA;AAAA,QACJ;AAAA,MACF;AAAA,MACA,UAAU,CAAC;AAAA,MACX,SAAS;AAAA,MACR,GAAG;AAAA,MAEJ;AAAA,wBAAAD,KAAC,oBAAiB;AAAA,QAClB,gBAAAA,KAAC,UAAK,WAAU,WAAU,wBAAU;AAAA;AAAA;AAAA,EACtC;AAEJ;;;ACrOA,SAAS,UAAU,uBAAuB;AAI1C,SAAS,aAAa;AAGb,gBAAAG,MAoDC,QAAAC,aApDD;AADT,SAAS,OAAO,EAAE,GAAG,MAAM,GAA+B;AACxD,SAAO,gBAAAD,KAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAMA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAiC;AAChE,SAAO,gBAAAE,KAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAMA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA,GAAG;AACL,GAAmC;AACjC,SACE,gBAAAC;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,GAAG;AACL,GAEG;AACD,SACE,gBAAAC,MAAC,gBACC;AAAA,oBAAAD,KAAC,iBAAc;AAAA,IACf,gBAAAC;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,mBACC,gBAAAA;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,aAAU;AAAA,cACV,QACE,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,MAAK;AAAA;AAAA,cACP;AAAA,cAGF;AAAA,gCAAAA;AAAA,kBAAC;AAAA;AAAA,gBACD;AAAA,gBACA,gBAAAA,KAAC,UAAK,WAAU,WAAU,mBAAK;AAAA;AAAA;AAAA,UACjC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAuCA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAgC;AACzE,SACE,gBAAAE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AFlGuB,SAwJnB,YAAAC,WAxJmB,OAAAC,MAsBjB,QAAAC,aAtBiB;AArBhB,SAAS,UAAU,OAAqC;AAC7D,MAAI,MAAM,MAAO,QAAO,MAAM;AAC9B,QAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,SAAO,IAAI,MAAM,KAAK,EAAE,UAAU,KAAK,CAAC,+BAA+B,KAAK,GAAG,IAAI,MAAM;AAC3F;AAEO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,EAAE,WAAW,IAAI,YAAY;AACnC,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,MAAM,QAAQ,WAAW,MAAM,GAAG,CAAC;AACzC,MAAI,CAAC,OAAO,QAAQ;AAClB,WAAO,MAAM,MAAM,gBAAAF,KAAC,UAAK,WAAW,GAAG,qBAAqB,SAAS,GAAI,gBAAM,KAAI,IAAU;AAAA,EAC/F;AACA;AAAA;AAAA,IAEE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,KAAK,MAAM;AAAA,QACX,OAAO,MAAM,MAAM;AAAA,QACnB,QAAQ,MAAM,MAAM;AAAA,QACpB,SAAS,QAAQ,UAAU;AAAA,QAC3B,UAAS;AAAA,QACT;AAAA,QACA,SAAS,MAAM,UAAU,IAAI;AAAA,QAC7B;AAAA;AAAA,IACF;AAAA;AAEJ;AAEA,SAAS,SAAS,EAAE,OAAO,QAAQ,GAAoD;AACrF,QAAM,EAAE,OAAO,IAAI,YAAY;AAC/B,SACE,gBAAAA,KAAC,UAAO,MAAM,CAAC,CAAC,OAAO,cAAc,CAAC,SAAS,CAAC,QAAQ,QAAQ,GAC9D,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,OAAO;AAAA,MACd,WAAW,GAAG,OAAO,WAAW,2DAA2D;AAAA,MAE3F;AAAA,wBAAAD,KAAC,eAAY,WAAU,WAAW,iBAAO,OAAO,SAAQ;AAAA,QACvD,SAAS,gBAAAA,KAAC,WAAQ,OAAc,OAAK,MAAC,WAAU,6DAA4D;AAAA,QAC5G,SAAS,UAAU,KAAK,KAAK,gBAAAA,KAAC,OAAE,WAAU,uDAAuD,oBAAU,KAAK,GAAE;AAAA;AAAA;AAAA,EACrH,GACF;AAEJ;AAEA,SAAS,SAAS,EAAE,OAAO,QAAQ,WAAW,SAAS,GAA0G;AAC/J,QAAM,OAAO,MAAM,QAAQ,QAAQ,MAAM,IAAI;AAC7C,MAAI,MAAM;AACR,WACE,gBAAAA,KAAC,OAAE,MAAY,QAAO,UAAS,KAAI,uBAAsB,WACtD,UACH;AAAA,EAEJ;AACA,SACE,gBAAAA,KAAC,YAAO,MAAK,UAAS,SAAS,MAAM,OAAO,KAAK,GAAG,cAAY,gBAAgB,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,EAAE,IAAI,WAAW,GAAG,kBAAkB,SAAS,GAC3J,UACH;AAEJ;AAEA,SAAS,UAAU,EAAE,QAAQ,OAAO,GAA8D;AAChG,QAAM,CAAC,KAAK,MAAM,IAAIE,UAAsB;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,CAAC;AACpC,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,IAAK;AACV,UAAM,SAAS,MAAM,SAAS,IAAI,mBAAmB,CAAC;AACtD,WAAO;AACP,QAAI,GAAG,UAAU,MAAM;AACvB,WAAO,MAAM;AACX,UAAI,IAAI,UAAU,MAAM;AAAA,IAC1B;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAGR,QAAM,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,OAAO,EAAE,KAAK,SAAS,GAAG,EAAE;AAC7G,QAAM,QAAQ,aAAa,OAAO,SAAS;AAC3C,QAAM,UAAU,UAAU,OAAO,KAAK,CAAC;AAEvC,SACE,gBAAAF,MAAC,YAAO,WAAU,aAChB;AAAA,oBAAAA,MAAC,YAAS,QAAgB,MAAM,EAAE,MAAM,OAAO,SAAS,EAAE,GAAG,cAAY,gBAAgB,OAAO,MAAM,WACpG;AAAA,sBAAAD,KAAC,mBAAgB,WAAU,QACxB,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAA,KAAC,gBAAqB,WAAU,QAAO,cAAY,GAAG,IAAI,CAAC,OAAO,OAAO,MAAM,IAC7E,0BAAAA,KAAC,YAAS,OAAc,QAAgB,WAAU,gBAChD,0BAAAA,KAAC,UAAK,WAAU,wEACd,0BAAAA,KAAC,WAAQ,OAAc,OAAO,MAAM,GAAG,WAAW,GAAG,aAAa,SAAS,MAAM,QAAQ,MAAM,KAAK,SAAS,MAAM,iBAAiB,oBAAoB,GAAG,GAC7J,GACF,KALiB,CAMnB,CACD,GACH;AAAA,MACA,gBAAAA,KAAC,oBAAiB,WAAU,yCAAwC;AAAA,MACpE,gBAAAA,KAAC,gBAAa,WAAU,0CAAyC;AAAA,OACnE;AAAA,IACA,gBAAAC,MAAC,gBAAW,WAAU,0CACpB;AAAA,sBAAAD,KAAC,UAAK,aAAU,UAAU,mBAAQ;AAAA,MAClC,gBAAAC,MAAC,UAAK,WAAU,oCACd;AAAA,wBAAAD,KAAC,UAAK,WAAU,gBAAe,MAAK,WAAU,cAAW,gBACtD,iBAAO,UAAU,MAChB,OAAO,IAAI,CAAC,GAAG,MACb,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,iBAAe,MAAM;AAAA,YACrB,cAAY,SAAS,IAAI,CAAC;AAAA,YAC1B,SAAS,MAAM,KAAK,SAAS,CAAC;AAAA,YAC9B,WAAW,GAAG,qCAAqC,MAAM,QAAQ,mBAAmB,+CAA+C;AAAA;AAAA,UAN9H;AAAA,QAOP,CACD,GACL;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,gBACb;AAAA,kBAAQ;AAAA,UAAE;AAAA,UAAI,OAAO;AAAA,WACxB;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEJ;AAEO,SAAS,MAAM,EAAE,QAAQ,QAAQ,GAAkD;AACxF,QAAM,CAAC,MAAM,OAAO,IAAIC,UAA0B,IAAI;AACtD,MAAI;AAEJ,MAAI,YAAY,aAAa;AAC3B,WAAO,gBAAAF,KAAC,aAAU,QAAgB,QAAQ,SAAS;AAAA,EACrD,WAAW,YAAY,QAAQ;AAC7B,WACE,gBAAAA,KAAC,SAAI,WAAU,uCACZ,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAC,MAAC,YACC;AAAA,sBAAAD,KAAC,YAAS,OAAc,QAAQ,SAAS,WAAU,gBACjD,0BAAAA,KAAC,UAAK,WAAU,gDACd,0BAAAA,KAAC,WAAQ,OAAc,WAAU,0BAAyB,GAC5D,GACF;AAAA,MACC,UAAU,KAAK,KAAK,gBAAAA,KAAC,gBAAY,oBAAU,KAAK,GAAE;AAAA,SANxC,CAOb,CACD,GACH;AAAA,EAEJ,OAAO;AACL,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,OAAO,MAAM;AAEnB,UAAM,QAAQ,CAAC,CAAC,QAAQ,KAAK,QAAQ;AACrC,UAAM,OAAO,CAAC,CAAC,QAAQ,KAAK,SAAS,KAAK,QAAQ;AAClD,WACE,gBAAAC,MAAC,YAAO,WAAW,GAAG,cAAc,SAAS,SAAS,eAAe,GACnE;AAAA,sBAAAD,KAAC,YAAS,OAAc,QAAQ,SAAS,WAAU,SACjD,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,GAAG,+BAA+B,CAAC,SAAS,CAAC,QAAQ,UAAU,QAAQ,sBAAsB;AAAA;AAAA,MAC1G,GACF;AAAA,MACC,UAAU,KAAK,KAAK,gBAAAA,KAAC,gBAAY,oBAAU,KAAK,GAAE;AAAA,OACrD;AAAA,EAEJ;AAEA,SACE,gBAAAC,MAAAF,WAAA,EACG;AAAA;AAAA,IACD,gBAAAC,KAAC,YAAS,OAAO,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAG;AAAA,KACvD;AAEJ;;;AGxKsB,SAmCd,YAAAI,WAnCc,OAAAC,MAclB,QAAAC,aAdkB;AAdf,SAAS,SAAS,EAAE,KAAK,GAA2B;AACzD,QAAM,EAAE,WAAW,IAAI,YAAY;AACnC,QAAM,EAAE,KAAK,IAAI;AACjB,MAAI,CAAC,KAAK,aAAa,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,MAAO,QAAO;AAEhE,QAAM,WAAW,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AAC1D,QAAM,OAAO,CAAC,KAAK,SAAS,OAAO,GAAG,KAAK,WAAW,aAAa,YAAY,KAAK,GAAG,QAAQ,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK;AAEtI,QAAM,SAAS,KAAK,OAAO,SAAS,KAClC,gBAAAD,KAAC,OAAE,WAAU,cACV,eAAK,OAAO,IAAI,CAAC,OAAO,UAAU;AACjC,UAAM,MAAM,QAAQ,WAAW,MAAM,GAAG,CAAC;AACzC,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,QAAQ,gBAAAA,KAAC,SAAI,KAAU,KAAK,MAAM,KAAK,SAAQ,QAAO;AAC5D,UAAM,OAAO,MAAM,QAAQ,QAAQ,MAAM,IAAI;AAC7C,WAAO,OACL,gBAAAA,KAAC,OAAc,MAAY,QAAO,UAAS,KAAI,uBAC5C,mBADK,KAER,IAEA,gBAAAA,KAAC,UAAkB,mBAAR,KAAc;AAAA,EAE7B,CAAC,GACH;AAGF,QAAM,OACJ,gBAAAC,MAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,YAAY,UAAU,KAAK,SAAS,gBAAAD,KAAC,WAAQ,OAAO,KAAK,OAAO,OAAK,MAAC,WAAU,iBAAgB;AAAA,IACrG,KAAK,WAAW,gBAAAA,KAAC,OAAE,WAAU,eAAe,eAAK,SAAQ;AAAA,IACzD,KAAK,aACJ,gBAAAA,KAAC,QAAG,WAAU,eACZ,0BAAAA,KAAC,UAAO,OAAO,KAAK,OAAO,GAC7B;AAAA,IAED,KAAK,KAAK,IAAI,CAAC,WAAW,UACzB,gBAAAA,KAAC,OAAc,WAAU,YACvB,0BAAAA,KAAC,UAAO,OAAO,WAAW,KADpB,KAER,CACD;AAAA,IACA,QAAQ,gBAAAA,KAAC,OAAE,WAAU,iBAAiB,gBAAK;AAAA,IAC3C;AAAA,KACH;AAGF,SACE,gBAAAC,MAAC,YAAO,WAAU,YAAW,gBAAc,KAAK,SAAS,IAAG,OACzD;AAAA,SAAK,YAAY,YAAY,KAAK,SACjC,gBAAAA,MAAAF,WAAA,EACE;AAAA,sBAAAC,KAAC,WAAQ,OAAO,KAAK,OAAO,OAAK,MAAC,WAAU,aAAY;AAAA,MACxD,gBAAAA,KAAC,SAAI,WAAU,aAAY,eAAW,MAAC;AAAA,OACzC;AAAA,IAEF,gBAAAC,MAAC,SAAI,WAAU,gCACZ;AAAA;AAAA,MACA,KAAK,YAAY,YAAY,KAAK,SACjC,gBAAAD,KAAC,SAAI,WAAU,mBACb,0BAAAA,KAAC,WAAQ,OAAO,KAAK,OAAO,OAAK,MAAC,WAAU,2BAA0B,GACxE;AAAA,OAEJ;AAAA,KACF;AAEJ;;;ACrEA,SAAS,aAAAE,YAAW,UAAU,cAAc,UAAU,UAAU,aAAa,qBAAqB,oBAAoB,cAAc,eAAe;AACnJ,SAAS,aAAAC,YAAW,QAAQ,YAAAC,iBAAgB;;;ACA5C,SAAS,QAAQ,qBAAqB;AAEtC,SAAS,oBAAAC,mBAAkB,aAAAC,kBAAiB;AAGnC,gBAAAC,MAsGL,QAAAC,aAtGK;AADT,SAAS,aAAa,EAAE,GAAG,MAAM,GAA6B;AAC5D,SAAO,gBAAAD,KAAC,cAAc,MAAd,EAAmB,aAAU,iBAAiB,GAAG,OAAO;AAClE;AAMA,SAAS,oBAAoB,EAAE,GAAG,MAAM,GAAgC;AACtE,SAAO,gBAAAE,KAAC,cAAc,SAAd,EAAsB,aAAU,yBAAyB,GAAG,OAAO;AAC7E;AAEA,SAAS,oBAAoB;AAAA,EAC3B,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,OAAO;AAAA,EACP,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAIK;AACH,SACE,gBAAAA,KAAC,cAAc,QAAd,EACC,0BAAAA;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,WAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,0BAAAA;AAAA,QAAC,cAAc;AAAA,QAAd;AAAA,UACC,aAAU;AAAA,UACV,WAAW,GAAG,qoBAAqoB,SAAU;AAAA,UAC5pB,GAAG;AAAA;AAAA,MACN;AAAA;AAAA,EACF,GACF;AAEJ;AAEA,SAAS,kBAAkB,EAAE,GAAG,MAAM,GAA8B;AAClE,SAAO,gBAAAA,KAAC,cAAc,OAAd,EAAoB,aAAU,uBAAuB,GAAG,OAAO;AACzE;AAEA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAEG;AACD,SACE,gBAAAA;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GAGG;AACD,SACE,gBAAAA;AAAA,IAAC,cAAc;AAAA,IAAd;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,gBAAc;AAAA,MACd,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AC5FA,SAAS,UAAU,sBAAsB;AAIzC,SAAS,SAAAC,cAAa;AAGb,gBAAAC,MAoDC,QAAAC,aApDD;AADT,SAAS,MAAM,EAAE,GAAG,MAAM,GAA8B;AACtD,SAAO,gBAAAD,KAAC,eAAe,MAAf,EAAoB,aAAU,SAAS,GAAG,OAAO;AAC3D;AAEA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAiC;AAChE,SAAO,gBAAAA,KAAC,eAAe,SAAf,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAMA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAgC;AAC9D,SAAO,gBAAAE,KAAC,eAAe,QAAf,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAkC;AAC5E,SACE,gBAAAA;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,GAAG;AACL,GAGG;AACD,SACE,gBAAAC,MAAC,eACC;AAAA,oBAAAD,KAAC,gBAAa;AAAA,IACd,gBAAAC;AAAA,MAAC,eAAe;AAAA,MAAf;AAAA,QACC,aAAU;AAAA,QACV,aAAW;AAAA,QACX,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,mBACC,gBAAAA;AAAA,YAAC,eAAe;AAAA,YAAf;AAAA,cACC,aAAU;AAAA,cACV,QACE,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,MAAK;AAAA;AAAA,cACP;AAAA,cAGF;AAAA,gCAAAA;AAAA,kBAACE;AAAA,kBAAA;AAAA,gBACD;AAAA,gBACA,gBAAAF,KAAC,UAAK,WAAU,WAAU,mBAAK;AAAA;AAAA;AAAA,UACjC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAgC;AACzE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,6BAA6B,SAAS;AAAA,MACnD,GAAG;AAAA;AAAA,EACN;AAEJ;AAYA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAA+B;AACvE,SACE,gBAAAG;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA,GAAG;AACL,GAAqC;AACnC,SACE,gBAAAA;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;;;AFtDU,gBAAAC,OAiCJ,QAAAC,aAjCI;AA5DV,SAAS,WAAW,IAAY;AAC9B,QAAM,SAAS,SAAS,eAAe,EAAE;AACzC,MAAI,CAAC,OAAQ;AACb,QAAM,SAAS,OAAO,WAAW,kCAAkC,EAAE;AACrE,SAAO,eAAe,EAAE,UAAU,SAAS,SAAS,UAAU,OAAO,QAAQ,CAAC;AAE9E,SAAO,aAAa,YAAY,IAAI;AACpC,SAAO,MAAM,EAAE,eAAe,KAAK,CAAC;AACpC,UAAQ,aAAa,MAAM,IAAI,IAAI,EAAE,EAAE;AACzC;AAGO,SAAS,mBAAmB,KAAe,MAA2C;AAC3F,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAwB,IAAI;AACxD,QAAM,MAAM,OAAuB,IAAI;AACvC,QAAM,MAAM,IAAI,KAAK,GAAG;AAExB,EAAAC,WAAU,MAAM;AACd,QAAI,QAAQ;AACZ,UAAM,SAAS,MAAM;AACnB,cAAQ;AACR,YAAM,KAAK,KAAK;AAChB,UAAI,CAAC,GAAI;AACT,YAAM,OAAO,GAAG,sBAAsB;AACtC,YAAM,OAAO,KAAK,SAAS,OAAO;AAClC,YAAM,WAAW,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,KAAK,MAAM,IAAI,CAAC,IAAI;AACzE,UAAI,IAAI,QAAS,KAAI,QAAQ,MAAM,YAAY,UAAU,QAAQ;AACjE,UAAI,UAAyB;AAC7B,iBAAW,MAAM,IAAI,MAAM,GAAG,GAAG;AAC/B,cAAM,OAAO,MAAM,SAAS,eAAe,EAAE;AAC7C,YAAI,QAAQ,KAAK,sBAAsB,EAAE,OAAO,OAAO,cAAc,IAAK,WAAU;AAAA,MACtF;AACA,gBAAU,OAAO;AAAA,IACnB;AACA,UAAM,WAAW,MAAM;AACrB,UAAI,CAAC,MAAO,SAAQ,sBAAsB,MAAM;AAAA,IAClD;AACA,WAAO;AACP,WAAO,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAC7D,WAAO,iBAAiB,UAAU,QAAQ;AAC1C,WAAO,MAAM;AACX,2BAAqB,KAAK;AAC1B,aAAO,oBAAoB,UAAU,QAAQ;AAC7C,aAAO,oBAAoB,UAAU,QAAQ;AAAA,IAC/C;AAAA,EACF,GAAG,CAAC,KAAK,IAAI,CAAC;AAEd,SAAO,EAAE,QAAQ,IAAI;AACvB;AAOA,SAAS,QAAQ,EAAE,SAAS,QAAQ,WAAW,GAAqF;AAClI,SACE,gBAAAH,MAAC,QAAG,WAAU,gBACX,kBAAQ,IAAI,CAAC,UACZ,gBAAAA,MAAC,QAAkB,cAAY,MAAM,OACnC,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,IAAI,MAAM,EAAE;AAAA,MAClB,gBAAc,MAAM,OAAO,SAAS,aAAa;AAAA,MACjD,SAAS,CAAC,UAAU;AAClB,cAAM,eAAe;AACrB,mBAAW,MAAM,EAAE;AAAA,MACrB;AAAA,MAEC,gBAAM;AAAA;AAAA,EACT,KAVO,MAAM,EAWf,CACD,GACH;AAEJ;AAGO,SAAS,WAAW,EAAE,MAAM,QAAQ,GAAG,GAA8D;AAC1G,QAAM,WAAW,OAAoB,IAAI;AAGzC,EAAAG,WAAU,MAAM;AACd,UAAM,MAAM,SAAS;AACrB,UAAM,UAAU,KAAK,cAA2B,gBAAgB;AAChE,QAAI,CAAC,OAAO,CAAC,QAAS;AACtB,UAAM,MAAM,QAAQ,YAAY,IAAI;AACpC,QAAI,MAAM,IAAI,YAAY,GAAI,KAAI,YAAY,KAAK,IAAI,GAAG,MAAM,EAAE;AAAA,aACzD,MAAM,QAAQ,eAAe,IAAI,YAAY,IAAI,eAAe,GAAI,KAAI,YAAY,MAAM,QAAQ,eAAe,IAAI,eAAe;AAAA,EAC/I,GAAG,CAAC,MAAM,CAAC;AAEX,SACE,gBAAAF,MAAC,SAAI,KAAK,UAAU,IAAQ,WAAU,eAAc,cAAW,YAC7D;AAAA,oBAAAD,MAAC,OAAE,WAAU,qBAAoB,sBAAQ;AAAA,IACzC,gBAAAC,MAAC,OAAE,WAAU,oBACV;AAAA,WAAK;AAAA,MAAY;AAAA,MAAa,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AAAA,MAAO;AAAA,OACjF;AAAA,IACA,gBAAAD,MAAC,WAAQ,SAAS,KAAK,KAAK,QAAgB,YAAY,YAAY;AAAA,KACtE;AAEJ;AAKA,IAAM,QAA8D;AAAA,EAClE,EAAE,IAAI,UAAU,OAAO,iBAAiB,MAAM,SAAS;AAAA,EACvD,EAAE,IAAI,SAAS,OAAO,mBAAmB,MAAM,aAAa;AAAA,EAC5D,EAAE,IAAI,YAAY,OAAO,YAAY,MAAM,aAAa;AAC1D;AAGA,SAAS,WAAW,EAAE,MAAM,OAAO,GAAiD;AAClF,QAAM,QAAQ,OAAuB,IAAI;AACzC,QAAM,QAAQ,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,IAAI;AACxD,QAAM,OAAO,CAAC,SAAiB;AAC7B,UAAM,OAAO,KAAK,IAAI,MAAM,SAAS,GAAG,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC;AACjE,WAAO,MAAM,IAAI,EAAE,EAAE;AACrB,UAAM,SAAS,iBAAiB,QAAQ,EAAE,IAAI,GAAG,MAAM;AAAA,EACzD;AACA,SACE,gBAAAC,MAAC,SAAI,KAAK,OAAO,MAAK,cAAa,cAAW,QAAO,WAAU,mBAAkB,OAAO,EAAE,oBAAoB,MAAM,GAClH;AAAA,oBAAAD,MAAC,UAAK,WAAU,kBAAiB,eAAW,MAAC;AAAA,IAC5C,MAAM,IAAI,CAAC,SACV,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,gBAAc,KAAK,OAAO;AAAA,QAC1B,cAAY,KAAK;AAAA,QACjB,OAAO,KAAK;AAAA,QACZ,UAAU,KAAK,OAAO,OAAO,IAAI;AAAA,QACjC,SAAS,MAAM,OAAO,KAAK,EAAE;AAAA,QAC7B,WAAW,CAAC,UAAU;AACpB,cAAI,MAAM,QAAQ,gBAAgB,MAAM,QAAQ,YAAa,MAAK,CAAC;AAAA,mBAC1D,MAAM,QAAQ,eAAe,MAAM,QAAQ,UAAW,MAAK,EAAE;AAAA,cACjE;AACL,gBAAM,eAAe;AAAA,QACvB;AAAA,QAEA,0BAAAA,MAAC,KAAK,MAAL,EAAU,eAAW,MAAC;AAAA;AAAA,MAflB,KAAK;AAAA,IAgBZ,CACD;AAAA,KACH;AAEJ;AAEO,SAAS,IAAI;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AACD,QAAM,EAAE,QAAQ,OAAO,YAAY,SAAS,IAAI,YAAY;AAC5D,QAAM,CAAC,MAAM,OAAO,IAAIE,UAAS,KAAK;AACtC,QAAM,EAAE,QAAQ,IAAI,IAAI;AAExB,QAAM,SAAS,KAAK,WAAW,SAAS;AACxC,QAAM,YAAY,KAAK,IAAI,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AAC9D,QAAM,UAAU,YAAa,KAAK,IAAI,MAAM,GAAG,KAAK,IAAI,QAAQ,SAAS,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,YAAa;AAE/H,MAAI,CAAC,KAAK,WAAW,CAAC,SAAU,QAAO;AAEvC,SACE,gBAAAD,MAAC,SAAI,WAAU,WAAU,cAAW,YAAW,gBAAe,QAAQ,aAAa,QAAQ,QAAS,QAClG;AAAA,oBAAAA,MAAC,SAAI,WAAU,8CACZ;AAAA,WAAK,KAAK,aACT,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,CAAC,UAAU;AAClB,kBAAM,eAAe;AACrB,mBAAO,SAAS,EAAE,MAAM,KAAK,SAAS,sBAAsB,EAAE,OAAO,KAAK,OAAO,SAAS,UAAU,SAAS,CAAC;AAAA,UAChH;AAAA,UACA,WAAU;AAAA,UAET,eAAK,KAAK;AAAA;AAAA,MACb;AAAA,MAED,WACC,gBAAAC,MAAC,UAAK,WAAW,GAAG,kDAAkD,KAAK,KAAK,aAAa,kBAAkB,GAAG,eAAW,MAC1H;AAAA,aAAK,KAAK,aAAa,gBAAAD,MAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA,QAC5D,QAAQ;AAAA,SACX;AAAA,MAEF,gBAAAC,MAAC,SAAI,WAAU,8CACZ;AAAA,oBAAY,gBAAAD,MAAC,cAAW,MAAY,QAAgB;AAAA,QACpD,YACC,gBAAAC,MAAC,gBACC;AAAA,0BAAAD,MAAC,uBAAoB,QAAQ,gBAAAA,MAAC,UAAO,SAAQ,SAAQ,MAAK,QAAO,cAAW,gBAAe,OAAM,SAAQ,GACvG,0BAAAA,MAAC,eAAY,GACf;AAAA,UACA,gBAAAA,MAAC,uBAAoB,OAAM,OAAM,OAAO,OAAO,OAAO,WAAW,GAAG,OAAO,WAAW,MAAM,GAC1F,0BAAAC,MAAC,qBACC;AAAA,4BAAAD,MAAC,qBAAkB,mBAAK;AAAA,YACvB,UAAU,IAAI,CAAC,SACd,gBAAAC,MAAC,oBAA+B,SAAS,MAAM,UAAU,KAAK,EAAE,GAC9D;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAU;AAAA,kBACV,OAAO,EAAE,YAAY,2BAA2B,KAAK,UAAU,EAAE,EAAE,SAAS,KAAK,UAAU,EAAE,MAAM,QAAQ;AAAA;AAAA,cAC7G;AAAA,cACC,KAAK;AAAA,cACL,KAAK,OAAO,MAAM,WAAW,gBAAAA,MAACI,YAAA,EAAU,WAAU,WAAU;AAAA,iBAPxC,KAAK,EAQ5B,CACD;AAAA,aACH,GACF;AAAA,WACF;AAAA,QAEF,gBAAAJ;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,SAAS,MAAM,aAAa,eAAe,SAAS,UAAU,MAAM;AAAA,YACpE,cAAY,eAAe,SAAS,yBAAyB;AAAA,YAC7D,OAAO,eAAe,SAAS,eAAe;AAAA,YAE7C,yBAAe,SAAS,gBAAAA,MAAC,WAAQ,IAAK,gBAAAA,MAAC,YAAS;AAAA;AAAA,QACnD;AAAA,QACC,QAAQ,aACP,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,QAAQ;AAAA,YACjB,iBAAe,QAAQ;AAAA,YACvB,iBAAe,QAAQ;AAAA,YACvB,cAAY,QAAQ,OAAO,2BAA2B;AAAA,YAErD;AAAA,sBAAQ,OAAO,gBAAAD,MAAC,uBAAoB,IAAK,gBAAAA,MAAC,sBAAmB;AAAA,cAC9D,gBAAAA,MAAC,UAAK,sBAAQ;AAAA;AAAA;AAAA,QAChB;AAAA,QAED,UAAU,CAAC,QAAQ,aAClB,gBAAAC,MAAC,SAAM,MAAY,cAAc,SAC/B;AAAA,0BAAAA,MAAC,gBAAa,QAAQ,gBAAAD,MAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,sBAAqB,cAAW,0BAAyB,GACzH;AAAA,4BAAAA,MAAC,YAAS;AAAA,YACV,gBAAAA,MAAC,UAAK,WAAU,oBAAmB,sBAAQ;AAAA,aAC7C;AAAA,UACA,gBAAAC,MAAC,gBAAa,OAAO,OAAO,OAAO,WAAW,GAAG,OAAO,WAAW,eAAe,GAChF;AAAA,4BAAAA,MAAC,eACC;AAAA,8BAAAD,MAAC,cAAW,sBAAQ;AAAA,cACpB,gBAAAC,MAAC,oBACE;AAAA,qBAAK;AAAA,gBAAY;AAAA,gBAAa,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;AAAA,gBAAO;AAAA,iBACjF;AAAA,eACF;AAAA,YACA,gBAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,KAAK;AAAA,gBACd;AAAA,gBACA,YAAY,CAAC,OAAO;AAClB,0BAAQ,KAAK;AAEb,6BAAW,MAAM,WAAW,EAAE,GAAG,EAAE;AAAA,gBACrC;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,SAEJ;AAAA,OACF;AAAA,IACA,gBAAAA,MAAC,SAAI,WAAU,gBAAe,eAAW,MACvC,0BAAAA,MAAC,SAAI,KAAK,KAAK,GACjB;AAAA,KACF;AAEJ;;;AGnRM,SAMY,OAAAK,OANZ,QAAAC,cAAA;AALN,SAAS,WAAW,EAAE,KAAK,GAAoB;AAC7C,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI,KAAK;AAC7B,QAAM,QAAQ,CAAC,UAAkB,KAAK,QAAQ,KAAK,KAAK;AACxD,SACE,gBAAAD,MAAC,SAAI,WAAU,mBACb,0BAAAC,OAAC,WACE;AAAA,YACC,gBAAAD,MAAC,WACC,0BAAAA,MAAC,QACE,eAAK,SAAS,IAAI,CAAC,MAAM,MACxB,gBAAAA,MAAC,QAAW,OAAM,OAAM,OAAO,EAAE,WAAW,MAAM,CAAC,EAAE,GACnD,0BAAAA,MAAC,UAAO,OAAO,KAAK,UAAU,KADvB,CAET,CACD,GACH,GACF;AAAA,IAEF,gBAAAA,MAAC,WACE,eAAK,IAAI,CAAC,KAAK,MACd,gBAAAA,MAAC,QACE,cAAI,SAAS,IAAI,CAAC,MAAM,MACvB,gBAAAA,MAAC,QAAW,OAAO,EAAE,WAAW,MAAM,CAAC,EAAE,GACvC,0BAAAA,MAAC,UAAO,OAAO,KAAK,UAAU,KADvB,CAET,CACD,KALM,CAMT,CACD,GACH;AAAA,KACF,GACF;AAEJ;AAOO,SAAS,cAAc,EAAE,MAAM,IAAI,GAAoC;AAC5E,QAAM,YAAY,CAAC,GAAG,GAAG;AACzB,SACE,gBAAAA,MAAC,UAAK,WAAU,aACb,eAAK,SAAS,IAAI,CAAC,MAAM,UAAU;AAClC,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,OAAO,OAAO,IAAI,EAAE,KAAK;AAC/B,YAAM,QAAQ,UAAU,UAAU,CAAC,UAAU,MAAM,KAAK,KAAK,MAAM,IAAI;AACvE,YAAM,KAAK,SAAS,IAAI,UAAU,OAAO,GAAG,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK;AACnE,YAAM,MAAM,IAAI,KAAK,KAAK;AAC1B,aACE,gBAAAA,MAAC,OAAgB,IACf,0BAAAA,MAAC,UAAO,OAAO,KAAK,UAAU,KADtB,KAEV;AAAA,IAEJ;AACA,QAAI,KAAK,SAAS,QAAS,QAAO,gBAAAA,MAAC,cAAuB,QAAP,KAAmB;AACtE,WAAO,gBAAAA,MAAC,YAAqB,QAAP,KAAmB;AAAA,EAC3C,CAAC,GACH;AAEJ;AAOO,SAAS,WAAW,EAAE,OAAO,SAAS,GAA0D;AACrG,SACE,gBAAAC,OAAC,UAAK,WAAU,cACd;AAAA,oBAAAA,OAAC,SAAI,WAAU,oBACZ;AAAA,kBAAY,gBAAAD,MAAC,OAAE,iEAAmD;AAAA,MACnE,gBAAAA,MAAC,cAAW,MAAM,MAAM,OAAO,OAAM,iBAAgB;AAAA,OACvD;AAAA,IACC,WACC,gBAAAA,MAAC,SAAI,WAAU,mBAAkB,cAAY,OAC3C,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAChD,cAAW;AAAA,QACX,YAAY;AAAA,QACZ,gBAAe;AAAA,QACf,aAAY;AAAA;AAAA,IACd,GACF,IAEA,gBAAAA,MAAC,SAAI,UAAU,GAAI,iBAAM;AAAA,KAE7B;AAEJ;;;AC/FA,SAAS,aAAAE,YAAW,oBAAoB;;;ACAxC,SAAS,mBAAmB,UAAU,eAAe,kBAAkB,gCAAgC;;;ACAvG,SAAS,WAAW,UAAU,WAAW,UAAU,oBAAiC;AACpF,SAAS,uBAAuB,aAAAC,YAAW,kBAAkB;;;ACA7D,SAAS,WAAW,wBAAwB;AAInC,gBAAAC,aAAA;AADT,SAAS,QAAQ,EAAE,GAAG,MAAM,GAAgC;AAC1D,SAAO,gBAAAA,MAAC,iBAAiB,MAAjB,EAAsB,aAAU,WAAW,GAAG,OAAO;AAC/D;AAEA,SAAS,eAAe,EAAE,GAAG,MAAM,GAAmC;AACpE,SAAO,gBAAAA,MAAC,iBAAiB,SAAjB,EAAyB,aAAU,mBAAmB,GAAG,OAAO;AAC1E;AAEA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,OAAO;AAAA,EACP,aAAa;AAAA,EACb,GAAG;AACL,GAIK;AACH,SACE,gBAAAA,MAAC,iBAAiB,QAAjB,EACC,0BAAAA;AAAA,IAAC,iBAAiB;AAAA,IAAjB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MAEV,0BAAAA;AAAA,QAAC,iBAAiB;AAAA,QAAjB;AAAA,UACC,aAAU;AAAA,UACV,WAAW;AAAA,YACT;AAAA,YACA;AAAA,UACF;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA;AAAA,EACF,GACF;AAEJ;;;ACnCM,gBAAAC,aAAA;AANN,SAAS,MAAM,EAAE,WAAW,GAAG,MAAM,GAAkC;AACrE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAU;AAAA,MAEV,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,aAAU;AAAA,UACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,UACvD,GAAG;AAAA;AAAA,MACN;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAkC;AAC3E,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,mBAAmB,SAAS;AAAA,MACzC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAkC;AACzE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,8BAA8B,SAAS;AAAA,MACpD,GAAG;AAAA;AAAA,EACN;AAEJ;AAeA,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAA+B;AACrE,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAA+B;AACtE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAA+B;AACtE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;;;AF9CI,SAIQ,OAAAC,OAJR,QAAAC,cAAA;AA7BJ,IAAM,YAAqC;AAAA,EACzC,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AAAA,EACP,UAAU;AAAA,EACV,OAAO;AACT;AAGO,SAAS,MAAM,OAA2B;AAC/C,QAAM,QAAQ,CAAC,SAAiB,KAAK,QAAQ,cAAc,GAAG,EAAE,KAAK;AACrE,SAAO;AAAA,IACL,MAAM,QAAQ,IAAI,CAAC,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAI;AAAA,IAClD,GAAG,MAAM,KAAK,IAAI,CAAC,QAAQ,MAAM,QAAQ,IAAI,CAAC,MAAM,MAAM,IAAI,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,GAAI,CAAC;AAAA,EACxF,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,UAAU,EAAE,OAAO,MAAM,GAA2C;AAElF,QAAM,WAAW,CAAC,QAAgB;AAChC,UAAM,UAAU,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAG,EAAE,MAAM,CAAC;AAC5E,WAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,IAAI,CAAC,CAAC,CAAC;AAAA,EACjE;AACA,QAAM,aAAa,CAAC,UAAmB,UAAU,UAAU,4BAA4B,UAAU,WAAW,gBAAgB;AAC5H,SACE,gBAAAA,OAAC,SAAM,WAAW,GAAG,aAAa,SAAS,kBAAkB,GAC3D;AAAA,oBAAAD,MAAC,eACC,0BAAAA,MAAC,YACE,gBAAM,QAAQ,IAAI,CAAC,WAClB,gBAAAA,MAAC,aAA2B,OAAM,OAAM,WAAW,WAAW,OAAO,KAAK,GACvE,iBAAO,SADM,OAAO,GAEvB,CACD,GACH,GACF;AAAA,IACA,gBAAAA,MAAC,aACE,gBAAM,KAAK,IAAI,CAAC,KAAK,MACpB,gBAAAA,MAAC,YACE,gBAAM,QAAQ,IAAI,CAAC,QAAQ,MAC1B,gBAAAA,MAAC,aAA2B,WAAW,GAAG,WAAW,OAAO,KAAK,GAAG,mBAAmB,GAAG,OAAO,MAAM,IAAI,EAAE,UAAU,SAAS,OAAO,GAAG,EAAE,IAAI,QAC9I,0BAAAA,MAAC,UAAO,OAAO,IAAI,MAAM,CAAC,GAAG,KADf,OAAO,GAEvB,CACD,KALY,CAMf,CACD,GACH;AAAA,KACF;AAEJ;AAEA,SAAS,MAAM,EAAE,OAAO,KAAK,MAAM,OAAO,GAA0E;AAClH,QAAM,EAAE,YAAY,WAAW,IAAI,YAAY;AAC/C,QAAM,WAAW,CAAC,QAAgB,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AACzE,QAAM,cAAc,IAAI,WAAW,SAAS,IAAI,QAAQ,IAAI;AAC5D,QAAM,SAAmB,KAAK,WAAW,IAAI,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,SAAS,GAAG,EAAE,MAAM,EAAE;AACpG,QAAM,OAAO,IAAI,WAAW,IAAI,CAAC,MAAM;AACrC,UAAM,MAAM,MAAM,KAAK,CAAC;AACxB,UAAM,QAAiC,EAAE,OAAO,cAAc,IAAI,KAAK,YAAY,GAAG,IAAI,OAAO,IAAI,CAAC,EAAE;AACxG,eAAW,OAAO,KAAK,WAAY,OAAM,GAAG,IAAI,IAAI,MAAM,GAAG;AAC7D,QAAI,IAAI,SAAS,aAAa,YAAa,OAAM,IAAI,IAAI,MAAM,YAAY,GAAG;AAC9E,WAAO;AAAA,EACT,CAAC;AACD,QAAM,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI;AAClD,QAAME,UAAS;AAAA,IACb;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,OAAO,SAAS,QAAQ;AAAA,IACxB,aAAa;AAAA,IACb,WAAW,GAAG,UAAU,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,cAAc,OAAO,YAAY,KAAK,KAAK,EAAE;AAAA,IAC7F,gBAAgB,CAAC,UAAkB,YAAY,OAAO,KAAK,IAAI;AAAA,IAC/D,YAAY,OAAO,SAAS;AAAA,EAC9B;AAEA,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AACH,aAAO,gBAAAF,MAAC,aAAW,GAAGE,SAAQ,MAAK,SAAQ,QAAgB,YAAY,KAAK,UAAU,IAAI,QAAQ,KAAK;AAAA,IACzG,KAAK;AACH,aAAO,gBAAAF,MAAC,aAAW,GAAGE,SAAQ,MAAK,SAAQ,QAAgB,QAAQ,KAAK;AAAA,IAC1E,KAAK;AACH,aAAO,gBAAAF,MAAC,YAAU,GAAGE,SAAQ,YAAU,MAAC,SAAQ,SAAQ,UAAU,KAAK,WAAW,CAAC,GAAG,SAAQ,SAAQ,QAAQ,KAAK;AAAA,IACrH,KAAK;AACH,aAAO,gBAAAF,MAAC,gBAAc,GAAGE,SAAQ,MAAK,KAAI,QAAgB,QAAQ,KAAK;AAAA,IACzE;AACE,aACE,gBAAAF;AAAA,QAAC;AAAA;AAAA,UACE,GAAGE;AAAA,UACJ,aAAY;AAAA,UACZ;AAAA,UACA,SAAS,IAAI,aAAa,eAAe;AAAA,UACzC,QAAQ,IAAI,aAAa,KAAK,IAAI,KAAK,KAAK,SAAS,KAAK,EAAE,IAAI;AAAA;AAAA,MAClE;AAAA,EAEN;AACF;AAEA,SAAS,MAAM,EAAE,OAAO,IAAI,GAAwC;AAClE,QAAM,OAAO,IAAI,OAAO,CAAC,GAAG,cAAc,CAAC;AAC3C,QAAM,QACJ,MAAM,KAAK,WAAW,IAClB,KAAK,IAAI,CAAC,SAAS,EAAE,OAAO,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,EAAG,OAAO,OAAO,MAAM,KAAK,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,IAC9G,IAAI,WAAW,IAAI,CAAC,OAAO,EAAE,OAAO,MAAM,KAAK,CAAC,EAAE,KAAK,IAAI,YAAY,EAAE,GAAG,OAAO,MAAM,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE;AACvH,SACE,gBAAAF,MAAC,QAAG,WAAU,aACX,gBAAM,IAAI,CAAC,MAAM,MAChB,gBAAAC,OAAC,SACC;AAAA,oBAAAD,MAAC,QAAI,eAAK,OAAM;AAAA,IAChB,gBAAAA,MAAC,QAAI,eAAK,OAAM;AAAA,OAFR,CAGV,CACD,GACH;AAEJ;AAEA,SAAS,SAAS,EAAE,OAAO,IAAI,GAAwC;AACrE,QAAM,YAAY,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,QAAQ,IAAI,QAAQ;AACvE,QAAM,OAAO,MAAM,QAAQ,IAAI,CAAC,QAAQ,WAAW,EAAE,QAAQ,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,UAAU,SAAS;AAChH,SACE,gBAAAA,MAAC,QAAG,WAAU,gBACX,cAAI,WAAW,IAAI,CAAC,MAAM;AACzB,UAAM,MAAM,MAAM,KAAK,CAAC;AACxB,UAAM,SAAS,KAAK,OAAO,CAAC,EAAE,OAAO,MAAM,IAAI,KAAK,OAAO,GAAG,CAAC;AAE/D,UAAM,OAAO,OAAO,KAAK,CAAC,EAAE,OAAO,MAAM,OAAO,SAAS,MAAM,KAAK,OAAO,CAAC;AAC5E,UAAM,UAAU,OAAO,OAAO,CAAC,UAAU,UAAU,IAAI;AACvD,WACE,gBAAAC,OAAC,QACC;AAAA,sBAAAD,MAAC,UAAM,cAAI,KAAK,MAAM,QAAQ,SAAS,EAAE,GAAG,GAAE;AAAA,MAC9C,gBAAAC,OAAC,SACE;AAAA,gBACC,gBAAAD,MAAC,OAAE,WAAU,sBACX,0BAAAA,MAAC,UAAO,OAAO,IAAI,MAAM,KAAK,KAAK,GAAG,GACxC;AAAA,QAED,QAAQ,IAAI,CAAC,EAAE,QAAQ,MAAM,MAC5B,gBAAAC,OAAC,OACG;AAAA,mBAAQ,SAAS,KAAK,OAAO,SAAS,WAAW,gBAAAA,OAAC,UAAK,WAAU,oBAAoB;AAAA,mBAAO;AAAA,YAAM;AAAA,aAAE;AAAA,UACtG,gBAAAD,MAAC,UAAO,OAAO,IAAI,MAAM,KAAK,GAAG;AAAA,aAF3B,OAAO,GAGf,CACD;AAAA,SACH;AAAA,SAdO,CAeT;AAAA,EAEJ,CAAC,GACH;AAEJ;AAEA,SAAS,MAAM,EAAE,MAAM,GAA0B;AAC/C,SACE,gBAAAA,MAAC,QAAG,WAAU,aACX,gBAAM,KAAK,IAAI,CAAC,KAAK,MACpB,gBAAAC,OAAC,SACC;AAAA,oBAAAD,MAAC,QACC,0BAAAA,MAAC,UAAO,OAAO,IAAI,MAAM,CAAC,GAAG,GAC/B;AAAA,IACA,gBAAAA,MAAC,QACC,0BAAAA,MAAC,UAAO,OAAO,IAAI,MAAM,CAAC,GAAG,GAC/B;AAAA,OANQ,CAOV,CACD,GACH;AAEJ;AAEO,SAAS,UAAU,EAAE,IAAI,OAAO,IAAI,GAAoD;AAC7F,QAAM,EAAE,QAAQ,UAAU,OAAO,IAAI,YAAY;AACjD,QAAM,UAAU,IAAI,SAAS;AAC7B,QAAM,WAAW,IAAI,OAAO,SAAS;AAErC,MAAI;AACJ,MAAI,QAAS,QAAO,gBAAAA,MAAC,SAAI,WAAU,oBAAoB,0BAAAA,MAAC,aAAU,OAAc,GAAG;AAAA,WAC1E,IAAI,SAAS,QAAS,QAAO,gBAAAA,MAAC,SAAM,OAAc,KAAU;AAAA,WAC5D,IAAI,SAAS,WAAY,QAAO,gBAAAA,MAAC,YAAS,OAAc,KAAU;AAAA,WAClE,IAAI,SAAS,QAAS,QAAO,gBAAAA,MAAC,SAAM,OAAc;AAAA,OACtD;AACH,WACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,cAAc,YAAY,gBAAgB,GAC1D,cAAI,OAAO,IAAI,CAAC,SACf,gBAAAA,MAAC,SAAiC,WAAU,qBAAoB,cAAY,KAAK,WAAW,SAAS,KAAK,QACxG,0BAAAA,MAAC,SAAM,OAAc,KAAU,MAAY,QAAQ,UAAU,KADrD,KAAK,WAAW,KAAK,CAE/B,CACD,GACH;AAAA,EAEJ;AAEA,SACE,gBAAAC,OAAC,YAAO,WAAU,YAAW,YAAU,IAAI,MAAM,iBAAe,IAC9D;AAAA,oBAAAA,OAAC,SAAI,WAAU,kBACZ;AAAA,kBAAY,IAAI,WAAW,SAAS,KACnC,gBAAAA,OAAC,gBACC;AAAA,wBAAAD,MAAC,uBAAoB,QAAQ,gBAAAA,MAAC,UAAO,SAAQ,SAAQ,MAAK,WAAU,WAAU,yBAAwB,cAAW,iCAAgC,OAAM,eAAc,GACnK,0BAAAA,MAAC,yBAAsB,GACzB;AAAA,QACA,gBAAAA,MAAC,uBAAoB,OAAM,OAAM,OAAO,OAAO,OAAO,WAAW,GAAG,OAAO,WAAW,MAAM,GAC1F,0BAAAC,OAAC,qBACC;AAAA,0BAAAD,MAAC,qBAAkB,qBAAO;AAAA,UACzB,IAAI,WAAW,IAAI,CAAC,SACnB,gBAAAC,OAAC,oBAA4B,SAAS,MAAM,OAAO,IAAI,IAAI,GACxD;AAAA,sBAAU,IAAI;AAAA,YACd,SAAS,IAAI,QAAQ,gBAAAD,MAACG,YAAA,EAAU,WAAU,WAAU;AAAA,eAFhC,IAGvB,CACD;AAAA,WACH,GACF;AAAA,SACF;AAAA,MAED,CAAC,WACA,gBAAAF,OAAC,WACC;AAAA,wBAAAD,MAAC,kBAAe,QAAQ,gBAAAA,MAAC,UAAO,SAAQ,SAAQ,MAAK,WAAU,WAAU,yBAAwB,cAAW,kCAAiC,OAAM,aAAY,GAC7J,0BAAAA,MAAC,cAAW,GACd;AAAA,QACA,gBAAAC,OAAC,kBAAe,OAAM,OAAM,OAAO,OAAO,OAAO,WAAW,GAAG,OAAO,WAAW,qDAAqD,GACpI;AAAA,0BAAAA,OAAC,SAAI,WAAU,uFACb;AAAA,4BAAAA,OAAC,UAAK,WAAU,6CACb;AAAA,oBAAM,KAAK;AAAA,cAAO;AAAA,cAAS,MAAM,QAAQ;AAAA,cAAO;AAAA,eACnD;AAAA,YACA,gBAAAD,MAAC,cAAW,MAAM,MAAM,MAAM,KAAK,GAAG,OAAM,+BAA8B;AAAA,aAC5E;AAAA,UACA,gBAAAA,MAAC,aAAU,OAAc,OAAK,MAAC;AAAA,WACjC;AAAA,SACF;AAAA,MAED,WAAW,gBAAAA,MAAC,cAAW,MAAM,MAAM,MAAM,KAAK,GAAG,OAAM,+BAA8B;AAAA,OACxF;AAAA,IACC;AAAA,KACH;AAEJ;;;ADpOa,SAgFT,YAAAI,WAhFS,OAAAC,OAeD,QAAAC,cAfC;AAXb,IAAM,WAAqE;AAAA,EACzE,MAAM,EAAE,OAAO,QAAQ,MAAM,SAAS;AAAA,EACtC,KAAK,EAAE,OAAO,OAAO,MAAM,cAAc;AAAA,EACzC,WAAW,EAAE,OAAO,aAAa,MAAM,yBAAyB;AAAA,EAChE,SAAS,EAAE,OAAO,WAAW,MAAM,kBAAkB;AAAA,EACrD,SAAS,EAAE,OAAO,WAAW,MAAM,iBAAiB;AACtD;AAEA,SAAS,UAAU,EAAE,MAAM,GAAqB;AAC9C,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,gBAAAD,MAAC,YAAS,MAAM,MAAM,MAAM;AAAA,IACrC,KAAK,WAAW;AACd,YAAM,MAAM,IAAI,KAAK,IAAI,GAAG,MAAM,QAAQ,CAAC,CAAC;AAC5C,aACE,gBAAAA,MAAC,OAAI,IAAI,MAAM,IAAI,WAAU,kBAAiB,cAAY,MAAM,OAC9D,0BAAAA,MAAC,UAAO,OAAO,MAAM,UAAU,GACjC;AAAA,IAEJ;AAAA,IACA,KAAK,QAAQ;AACX,UAAI,MAAM,YAAY,UAAW,QAAO,gBAAAA,MAAC,YAAS,MAAM,MAAM,MAAM;AACpE,YAAM,MAAM,MAAM,KAAK,UAAU,OAAO;AACxC,aACE,gBAAAA,MAAC,OAAI,WAAU,oBAAmB,gBAAc,MAAM,SAAS,OAAO,MAAM,KAAK,UAAW,MAAM,KAAK,SAAS,SAAa,QAC1H,gBAAM,KAAK,SAAS,IAAI,CAAC,MAAM,UAC9B,gBAAAC,OAAC,QACC;AAAA,wBAAAD,MAAC,UAAK,WAAU,mBAAkB,eAAW,MAC1C,gBAAM,KAAK,UAAU,QAAQ,MAAM,KAAK,SAAS,KAAK,KAAK,EAAE,SAAS,GAAG,GAAG,IAAI,IACnF;AAAA,QACA,gBAAAA,MAAC,SACC,0BAAAA,MAAC,YAAS,OAAO,KAAK,UAAU,GAClC;AAAA,WANO,KAOT,CACD,GACH;AAAA,IAEJ;AAAA,IACA,KAAK,SAAS;AACZ,UAAI,MAAM,YAAY,WAAW;AAC/B,cAAM,UAAU,SAAS,MAAM,eAAe,MAAM,KAAK,SAAS;AAClE,eACE,gBAAAC,OAAC,WAAM,WAAU,eAAc,aAAW,MAAM,aAC9C;AAAA,0BAAAA,OAAC,OAAE,WAAU,qBACX;AAAA,4BAAAD,MAAC,QAAQ,MAAR,EAAa,eAAW,MAAC;AAAA,YACzB,QAAQ;AAAA,aACX;AAAA,UACA,gBAAAA,MAAC,QAAK,OAAO,MAAM,UAAU;AAAA,WAC/B;AAAA,MAEJ;AACA,aACE,gBAAAC,OAAC,YAAO,WAAW,MAAM,YAAY,SAAS,aAAa,aACzD;AAAA,wBAAAD,MAAC,gBACC,0BAAAA,MAAC,QAAK,OAAO,MAAM,UAAU,GAC/B;AAAA,QACC,MAAM,eAAe,gBAAAA,MAAC,gBAAY,gBAAM,aAAY;AAAA,SACvD;AAAA,IAEJ;AAAA,IACA,KAAK;AACH,aAAO,gBAAAA,MAAC,aAAU,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO;AAAA,IAC1D,KAAK;AACH,aAAO,gBAAAA,MAAC,SAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM,SAAS;AAAA,IAC9D,KAAK;AACH,aAAO,gBAAAA,MAAC,aAAU,IAAI,MAAM,IAAI,OAAO,MAAM,OAAO,KAAK,MAAM,KAAK;AAAA,IACtE,KAAK;AACH,aACE,gBAAAA,MAAC,SAAI,WAAU,aAAY,cAAY,MAAM,MAAM,QAChD,gBAAM,MAAM,IAAI,CAAC,MAAM,UACtB,gBAAAC,OAAC,aAAsB,IAAI,KAAK,IAAI,WAAU,YAC5C;AAAA,wBAAAD,MAAC,UAAK,WAAU,kBAAiB,eAAW,MACzC,iBAAO,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG,GACpC;AAAA,QACA,gBAAAA,MAAC,QACC,0BAAAA,MAAC,UAAO,OAAO,KAAK,OAAO,GAC7B;AAAA,QACA,gBAAAA,MAAC,SAAI,WAAU,YACb,0BAAAA,MAAC,UAAO,QAAQ,KAAK,QAAQ,GAC/B;AAAA,WATY,KAAK,EAUnB,CACD,GACH;AAAA,IAEJ,KAAK;AACH,aAAO,gBAAAA,MAAC,QAAG,WAAU,YAAW;AAAA,EACpC;AACF;AAEO,SAAS,OAAO,EAAE,OAAO,GAAwB;AACtD,SACE,gBAAAA,MAAAD,WAAA,EACG,iBAAO,IAAI,CAAC,OAAO,UAClB,gBAAAC,MAAC,aAAsB,SAAP,KAAqB,CACtC,GACH;AAEJ;;;AD9EU,SAwEF,YAAAE,WAxEE,OAAAC,OAgBI,QAAAC,cAhBJ;AAhBH,IAAM,eAAsE;AAAA,EACjF,OAAO,EAAE,MAAM,WAAW,MAAM,kCAAkC;AAAA,EAClE,WAAW,EAAE,MAAM,aAAa,MAAM,kCAAkC;AAAA,EACxE,OAAO,EAAE,MAAM,gBAAgB,MAAM,yBAAyB;AAAA,EAC9D,WAAW,EAAE,MAAM,qBAAqB,MAAM,sBAAsB;AAAA,EACpE,OAAO,EAAE,MAAM,SAAS,MAAM,yBAAyB;AAAA,EACvD,UAAU,EAAE,MAAM,YAAY,MAAM,4BAA4B;AAAA,EAChE,OAAO,EAAE,MAAM,aAAa,MAAM,wBAAwB;AAC5D;AAEA,SAAS,WAAW,EAAE,QAAQ,GAAyB;AACrD,QAAM,EAAE,QAAQ,UAAU,IAAI,YAAY;AAC1C,SACE,gBAAAA,OAAC,gBACC;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,QACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,WAAU;AAAA,YACV,cAAY,oBAAoB,QAAQ,aAAa,cAAc;AAAA,YACnE,OAAM;AAAA;AAAA,QACR;AAAA,QAGF,0BAAAA,MAAC,gBAAa;AAAA;AAAA,IAChB;AAAA,IACA,gBAAAA,MAAC,uBAAoB,OAAM,OAAM,OAAO,OAAO,OAAO,WAAW,GAAG,OAAO,WAAW,MAAM,GAC1F,0BAAAC,OAAC,qBACC;AAAA,sBAAAD,MAAC,qBAAkB,4BAAc;AAAA,MAChC,QAAQ,aAAa,IAAI,CAAC,WACzB,gBAAAC,OAAC,oBAA8B,SAAS,MAAM,UAAU,QAAQ,IAAI,MAAM,GAAG,WAAU,eACrF;AAAA,wBAAAA,OAAC,UAAK,WAAU,iBACd;AAAA,0BAAAD,MAAC,UAAK,WAAU,eAAe,uBAAa,MAAM,EAAE,MAAK;AAAA,UACzD,gBAAAA,MAAC,UAAK,WAAU,iCAAiC,uBAAa,MAAM,EAAE,MAAK;AAAA,WAC7E;AAAA,QACC,WAAW,QAAQ,UAAU,gBAAAA,MAACE,YAAA,EAAU,WAAU,kBAAiB;AAAA,WAL/C,MAMvB,CACD;AAAA,OACH,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,YAAY,EAAE,QAAQ,GAAyB;AAC7D,QAAM,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,YAAY,GAAG,QAAQ,EAAE;AAC/B,QAAM,UAAU,QAAQ,YACtB,gBAAAF,MAAC,QAAG,IAAI,WAAW,WAAU,UAC3B,0BAAAA,MAAC,UAAO,OAAO,QAAQ,OAAO,GAChC,IACE;AACJ,QAAM,OAAO,QAAQ,OAAO,SAAS,KACnC,gBAAAA,MAAC,SAAI,WAAU,YACb,0BAAAA,MAAC,UAAO,QAAQ,QAAQ,QAAQ,GAClC;AAGF,MAAI;AACJ,UAAQ,QAAQ,QAAQ;AAAA,IACtB,KAAK;AAAA,IACL,KAAK;AACH,aACE,gBAAAC,OAAC,SAAI,WAAU,4BACZ;AAAA;AAAA,QACA;AAAA,SACH;AAEF;AAAA,IACF,KAAK;AACH,aACE,gBAAAA,OAAC,SAAI,WAAU,2BAA0B,aAAW,QAAQ,QAAQ,QAClE;AAAA,wBAAAA,OAAC,SAAI,WAAU,kBACZ;AAAA;AAAA,UACA;AAAA,WACH;AAAA,QACC,QAAQ,WACP,gBAAAA,OAAC,YAAO,WAAU,mBAChB;AAAA,0BAAAD,MAAC,WAAQ,OAAO,QAAQ,SAAS,WAAU,2BAA0B;AAAA,UACpE,UAAU,QAAQ,OAAO,KAAK,gBAAAA,MAAC,gBAAY,oBAAU,QAAQ,OAAO,GAAE;AAAA,WACzE;AAAA,SAEJ;AAEF;AAAA,IACF,KAAK;AACH,aACE,gBAAAC,OAAAF,WAAA,EACG;AAAA,gBAAQ,WAAW,gBAAAC,MAAC,WAAQ,OAAO,QAAQ,SAAS,WAAU,aAAY;AAAA,QAC3E,gBAAAA,MAAC,SAAI,WAAU,aAAY,eAAW,MAAC;AAAA,QACvC,gBAAAC,OAAC,SAAI,WAAU,0BACZ;AAAA;AAAA,UACA;AAAA,WACH;AAAA,SACF;AAEF;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,aACE,gBAAAA,OAAC,SAAI,WAAU,2BACZ;AAAA;AAAA,QACA;AAAA,SACH;AAEF;AAAA,IACF;AACE,aACE,gBAAAA,OAAC,SAAI,WAAW,GAAG,iBAAiB,UAAU,mBAAmB,gBAAgB,GAC9E;AAAA,mBAAW,gBAAAD,MAAC,YAAQ,mBAAQ;AAAA,QAC5B;AAAA,SACH;AAAA,EAEN;AAEA,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,QAAQ;AAAA,MACZ,mBAAiB,UAAU,YAAY;AAAA,MACvC,cAAY,UAAU,SAAY;AAAA,MAClC,WAAU;AAAA,MACV,eAAa,QAAQ;AAAA,MACrB,aAAW,QAAQ;AAAA,MACnB,cAAY,UAAU,SAAY;AAAA,MAEjC;AAAA,oBAAY,QAAQ,aAAa,SAAS,KAAK,gBAAAD,MAAC,cAAW,SAAkB;AAAA,QAC7E;AAAA;AAAA;AAAA,EACH;AAEJ;;;AvBiLY,SA6BM,YAAAG,WA5BJ,OAAAC,OADF,QAAAC,cAAA;AA3QZ,IAAM,WAAW,CAAC,QAAgB;AAElC,SAAS,sBAAkC;AACzC,SAAO;AAAA,IACL,CAAC,WAAW;AACV,YAAM,QAAQ,OAAO,WAAW,8BAA8B;AAC9D,YAAM,iBAAiB,UAAU,MAAM;AACvC,aAAO,MAAM,MAAM,oBAAoB,UAAU,MAAM;AAAA,IACzD;AAAA,IACA,MAAO,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAAA,IAC5E,MAAM;AAAA,EACR;AACF;AAMA,SAAS,SAAS,MAAc,SAAkB,QAAQ,MAAe;AACvE,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAwB,IAAI;AACxD,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAS;AACd,QAAI,OAAO;AACX,UAAM,OAAO,MAAM,QAAQ,UAAU,IAAI;AAEzC,UAAM,SAAS,MAAM,sBAAsB,MAAM,sBAAsB,MAAM,SAAS,MAAM,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC;AACnH,UAAM,MAAM,WAAW,MAAM,KAAK;AAElC,QAAI,OAAO,SAAS,KAAK,cAA+B,wBAAwB,IAAI,IAAI;AACxF,QAAI,MAAM,QAAQ,UAAW,QAAO;AAAA,SAC/B;AACH,UAAI,CAAC,MAAM;AACT,eAAO,SAAS,cAAc,MAAM;AACpC,aAAK,MAAM;AACX,aAAK,OAAO;AACZ,aAAK,QAAQ,WAAW;AACxB,iBAAS,KAAK,YAAY,IAAI;AAAA,MAChC;AACA,YAAM,SAAS;AACf,YAAM,SAAS,MAAM;AACnB,eAAO,QAAQ,YAAY;AAC3B,eAAO;AAAA,MACT;AACA,aAAO,iBAAiB,QAAQ,QAAQ,EAAE,MAAM,KAAK,CAAC;AACtD,aAAO,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;AAAA,IACvD;AACA,WAAO,MAAM;AACX,aAAO;AACP,mBAAa,GAAG;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,SAAS,KAAK,CAAC;AACzB,SAAO,CAAC,WAAW,WAAW;AAChC;AAEA,IAAM,OAAiB,CAAC;AAGxB,IAAM,oBAAoB;AAG1B,SAAS,QAAQ,QAA6C,UAA2B;AACvF,QAAM,CAAC,MAAM,OAAO,IAAID,UAAS,KAAK;AACtC,EAAAC,WAAU,MAAM;AACd,UAAM,KAAK,OAAO;AAClB,QAAI,CAAC,GAAI;AACT,UAAM,WAAW,IAAI,eAAe,CAAC,CAAC,KAAK,MAAM,QAAQ,MAAM,YAAY,SAAS,QAAQ,CAAC;AAC7F,aAAS,QAAQ,EAAE;AACnB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,QAAQ,QAAQ,CAAC;AACrB,SAAO;AACT;AAGA,IAAM,gBAAgB;AAEtB,SAAS,SAAS;AAAA,EAChB,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,YAAY,iBAAiB;AAAA,EAC7B,aAAa;AAAA,EACb,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,OAAOC,QAAuB,IAAI;AAExC,QAAM,CAAC,UAAU,WAAW,IAAIF,UAAS,eAAe;AACxD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,eAAe;AAClD,QAAM,SAASG,SAAQ,MAAM,cAAc,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAChE,QAAM,WAAWA,SAAQ,MAAM,OAAO,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;AAC5D,QAAM,QAAQA,SAAQ,MAAM,QAAQ,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC;AAE1D,QAAM,eAAeA,SAAQ,MAAM;AACjC,UAAM,QAAQ,EAAE,aAAa,SAAS,MAAM,QAAQ,KAAK,CAAC,GAAG,SAAS,GAAG,SAAS,SAAS,MAAM,kBAAkB,KAAK,CAAC,GAAG,OAAO;AACnI,WAAO,WAAW,UAAU,KAAK;AAAA,EACnC,GAAG,CAAC,UAAU,QAAQ,CAAC;AAEvB,QAAM,CAAC,QAAQ,SAAS,IAAIH,UAA8B,IAAI;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAA4B,IAAI;AAE5D,QAAM,CAAC,SAAS,UAAU,IAAIA,UAA0B,IAAI;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAwC,CAAC,CAAC;AACxE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAkC,CAAC,CAAC;AACpE,QAAM,CAAC,aAAa,cAAc,IAAIA,UAA2B,IAAI;AACrE,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAA4B,IAAI;AAC5E,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAe,UAAU;AAGjD,QAAM,aAAaI;AAAA,IACjB,CAAC,SAAe;AACd,UAAI,UAAU,UAAU;AACtB,oBAAY,KAAK;AACjB,2BAAmB,KAAK;AAAA,MAC1B;AACA,cAAQ,IAAI;AAAA,IACd;AAAA,IACA,CAAC,OAAO,UAAU,gBAAgB;AAAA,EACpC;AAGA,EAAAH,WAAU,MAAM;AACd,QAAI,OAAO;AACX,UAAM,OAAO,iBAAiB,OAAO,IAAI;AACzC,UAAM,QAAQ,CAAC,SAAS,SAAS,QAAQ,EAAE,IAAI,CAAC,QAAQ,OAAO,YAAY,GAAG,CAAC,EAAE,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AACjI,gBAAY,CAAC,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,QAAQ,EAAE,KAAK,CAAC,WAAW,QAAQ,UAAU,MAAM,CAAC;AACjG,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,QAAQ,CAAC;AAKjC,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,WAAY;AAC5B,UAAM,QAAQ,IAAI,gBAAgB;AAClC,UAAM,aAAa,aAAa,EAAE,MAAM,OAAO,MAAM,aAAa,OAAO,aAAa,OAAO,CAAC;AAC9F,kBAAc,YAAY,OAAO,YAAY;AAAA,MAC3C,QAAQ,MAAM;AAAA,MACd,WAAW,gBAAgB;AAAA,MAC3B,YAAY,CAAC,aAAa;AACxB,kBAAU,SAAS,UAAU;AAC7B,mBAAW,SAAS,OAAO;AAAA,MAC7B;AAAA,IACF,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,UAAI,MAAM,OAAO,QAAS;AAC1B,cAAQ,KAAK,0DAA0D,KAAK;AAC5E,iBAAW,CAAC,CAAC;AAAA,IACf,CAAC;AACD,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,GAAG,CAAC,QAAQ,YAAY,QAAQ,OAAO,YAAY,CAAC;AAEpD,QAAM,OAAOE;AAAA,IACX,MACE,aAAa;AAAA,MACX,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,QAAQ,UAAU,CAAC;AAAA,MACnB,YAAY,EAAE,GAAG,QAAQ,KAAK,EAAE,GAAG,QAAQ,KAAK,GAAG,SAAS,GAAG,QAAQ;AAAA,IACzE,CAAC;AAAA,IACH,CAAC,QAAQ,QAAQ,QAAQ,UAAU,OAAO;AAAA,EAC5C;AAEA,QAAM,QAAQA,SAAqB,MAAM;AACvC,UAAM,kBAAkB,OAAO,YAAY;AAC3C,UAAM,SACJ,gBAAgB,OAAO,oBAAoB,YAAY,mBAAmB,SAAU,kBAAgC;AAGtH,UAAM,SAAS,SAAS,YAAY,MAAM,IAAI,EAAE,GAAG,YAAY,gBAAgB,OAAO,GAAG,GAAG,QAAQ,MAAM;AAC1G,WAAO,EAAE,GAAG,QAAQ,GAAG,WAAW;AAAA,EACpC,GAAG,CAAC,cAAc,QAAQ,QAAQ,aAAa,UAAU,CAAC;AAE1D,QAAM,SAAS,oBAAoB;AACnC,QAAM,aAAyB,mBAAmB,mBAAmB,SAAS,SAAS;AAEvF,QAAM,WAAW,WAAW;AAC5B,QAAM,aAAa,SAAS,eAAe,aAAa,MAAM,KAAK,CAAC,GAAG,SAAS;AAChF,QAAM,cAAc,aAAa,UAAU;AAK3C,EAAAF,WAAU,MAAM;AACd,QAAI,YAAY,CAAC,SAAU;AAC3B,UAAM,QAAQ,sBAAsB,MAAM;AACxC,YAAM,KAAK,KAAK;AAChB,UAAI,CAAC,MAAM,CAAC,eAAe,CAAC,WAAY;AACxC,UAAI,YAAY,SAAS,OAAO,KAAK,YAAY,SAAS,MAAM,EAAG;AACnE,YAAM,MAAM,GAAG,sBAAsB,EAAE;AACvC,YAAM,QAAQ,OAAO,cAAc;AACnC,YAAM,WAAW,YAAY,KAAK,CAAC,OAAO;AACxC,cAAM,QAAQ,GAAG,cAAc,mBAAmB,IAAI,OAAO,EAAE,CAAC,IAAI;AACpE,eAAO,CAAC,CAAC,SAAS,MAAM,sBAAsB,EAAE,MAAM,MAAM;AAAA,MAC9D,CAAC;AACD,UAAI,CAAC,SAAU,aAAY,IAAI;AAAA,IACjC,CAAC;AACD,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACzC,GAAG,CAAC,UAAU,UAAU,aAAa,YAAY,MAAM,KAAK,CAAC;AAG7D,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,QAAQ,WAAW,MAAM,YAAY,IAAI,GAAG,SAAS;AAC3D,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,UAAU,SAAS,CAAC;AAExB,EAAAA,WAAU,MAAM;AACd,QAAI,SAAU,UAAS,MAAM,KAAK;AAAA,EACpC,GAAG,CAAC,MAAM,OAAO,UAAU,MAAM,CAAC;AAGlC,QAAM,QAAQE,SAAQ,MAAM,UAAU,OAAO,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC;AAC7E,QAAM,aAAaA,SAAQ,MAAM,cAAc,KAAK,GAAG,CAAC,KAAK,CAAC;AAC9D,QAAM,YAAYC,aAAY,CAAC,IAAY,WAA0B,WAAW,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC;AAC1H,QAAM,SAASA,aAAY,CAAC,IAAY,SAAkB,YAAY,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;AAG9G,QAAM,SAASD,SAAQ,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;AACtE,QAAM,WAAW,mBAAmB,QAAQ,IAAI;AAChD,QAAM,OAAO,QAAQ,MAAM,iBAAiB;AAC5C,QAAM,CAAC,eAAe,gBAAgB,IAAIH,UAAS,IAAI;AACvD,QAAM,YAAY,MAAM;AACxB,QAAM,UAAUG;AAAA,IACd,OAAO;AAAA,MACL,WAAW,QAAQ,KAAK,WAAW,SAAS;AAAA,MAC5C,MAAM;AAAA,MACN,QAAQ,MAAM,iBAAiB,CAAC,SAAS,CAAC,IAAI;AAAA,MAC9C,IAAI;AAAA,IACN;AAAA,IACA,CAAC,MAAM,KAAK,SAAS,MAAM,eAAe,SAAS;AAAA,EACrD;AACA,QAAM,cAAc,QAAQ,aAAa,QAAQ;AAEjD,QAAM,UAAUA;AAAA,IACd,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,EAAE,WAAW,GAAG,cAAc,eAAe,UAAU,MAAM,GAAG,MAAM;AAAA,MAC9E;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,YAAY,YAAY,OAAO,YAAY,OAAO,UAAU,WAAW,MAAM;AAAA,EAChF;AAEA,SACE,gBAAAL,MAAC,oBAAiB,OAAO,SACvB,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAW,GAAG,OAAO,eAAe,UAAU,QAAQ,SAAS;AAAA,MAC/D;AAAA,MACA,cAAY,MAAM;AAAA,MAClB,cAAY;AAAA,MACZ,aAAW,CAAC;AAAA,MAEX;AAAA,SAAC,YACA,gBAAAD,MAAC,SAAI,WAAU,cAAa,MAAK,UAAS,aAAU,UAClD,0BAAAC,OAAC,SACC;AAAA,0BAAAD,MAAC,UAAK,WAAU,mBAAkB,eAAW,MAAC;AAAA,UAC9C,gBAAAA,MAAC,OAAE,6BAAe;AAAA,WACpB,GACF;AAAA,QAGD,YACC,gBAAAC,OAAC,SAAI,WAAU,gBAAe,OAAO,CAAC,UACpC;AAAA,0BAAAD,MAAC,OAAE,MAAM,IAAI,KAAK,SAAS,CAAC,GAAG,MAAM,KAAK,IAAI,WAAU,YAAW,6BAEnE;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,cACR,WAAW;AAAA,cACX,cAAc;AAAA;AAAA,UAChB;AAAA,UACA,gBAAAC,OAAC,SAAI,WAAU,YAAW,gBAAc,eAAe,QACrD;AAAA,4BAAAD,MAAC,SAAI,WAAU,eACZ,mBAAS,WACR,gBAAAA,MAAC,cAAW,OAAO,OAAO,UAAU,WAAW,WAAW,QAAW,IACnE,SAAS,UACX,gBAAAA,MAAC,iBAAc,MAAM,OAAO,MAAM,KAAK,KAAK,KAAK,IAEjD,gBAAAC,OAAAF,WAAA,EACE;AAAA,8BAAAC,MAAC,YAAS,MAAY;AAAA,cACtB,gBAAAA,MAAC,UACE,eAAK,SAAS,IAAI,CAAC,YAClB,gBAAAA,MAAC,eAA6B,WAAZ,QAAQ,EAAsB,CACjD,GACH;AAAA,eACF,GAEJ;AAAA,YACC,eAAe,gBAAAA,MAAC,cAAW,MAAY,QAAQ,SAAS,QAAQ,IAAI,WAAW;AAAA,aAClF;AAAA,WACF;AAAA;AAAA;AAAA,EAEJ,GACF;AAEJ;AAOO,SAAS,iBAAiB,OAA8B;AAC7D,QAAM,EAAE,UAAU,iBAAiB,IAAI;AAIvC,QAAM,CAACO,WAAU,WAAW,IAAIL,UAAiE,EAAE,UAAU,KAAK,GAAG,MAAM,KAAK,CAAC;AACjI,MAAI,UAAUK;AACd,MAAI,aAAaA,UAAS,UAAU;AAClC,cAAU,EAAE,UAAU,KAAK,aAAaA,UAAS,OAAOA,UAAS,MAAMA,UAAS,MAAM,GAAG,MAAMA,UAAS,KAAK;AAC7G,gBAAY,OAAO;AAAA,EACrB;AACA,QAAM,eAAeD;AAAA,IACnB,CAAC,SAAiB;AAChB,kBAAY,CAAC,cAAc,EAAE,GAAG,UAAU,MAAM,KAAK,EAAE;AACvD,yBAAmB,IAAI;AAAA,IACzB;AAAA,IACA,CAAC,gBAAgB;AAAA,EACnB;AACA,SAAO,gBAAAN,MAAC,YAA4B,GAAG,OAAO,kBAAkB,gBAA1C,QAAQ,GAAgD;AAChF;","names":["useCallback","useEffect","useMemo","useRef","useState","words","tokens","cache","tokens","children","cache","tokens","jsx","Fragment","jsx","jsxs","useEffect","useState","jsx","jsxs","api","jsx","jsxs","jsx","jsx","jsxs","jsx","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","CheckIcon","useEffect","useState","ChevronRightIcon","CheckIcon","jsx","jsxs","jsx","XIcon","jsx","jsxs","jsx","jsxs","XIcon","jsx","jsx","jsxs","useState","useEffect","CheckIcon","jsx","jsxs","CheckIcon","CheckIcon","jsx","jsx","jsx","jsx","jsxs","common","CheckIcon","Fragment","jsx","jsxs","Fragment","jsx","jsxs","CheckIcon","Fragment","jsx","jsxs","useState","useEffect","useRef","useMemo","useCallback","identity"]}
|
|
1
|
+
{"version":3,"sources":["../src/stunning-md/components/stunning-markdown.tsx","../src/lib/utils.ts","../src/stunning-md/chat.ts","../src/stunning-md/theme/chart.ts","../src/stunning-md/theme/color.ts","../src/stunning-md/theme/themes.ts","../src/stunning-md/components/chat-ui.tsx","../src/components/ui/button.tsx","../src/stunning-md/analyze/text.ts","../src/stunning-md/parse.ts","../src/stunning-md/components/flow.tsx","../src/stunning-md/components/code-block.tsx","../src/stunning-md/components/context.tsx","../src/stunning-md/components/nav.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ui/sheet.tsx","../src/stunning-md/components/turn.tsx","../src/stunning-md/analyze/images.ts","../src/stunning-md/analyze/tables.ts","../src/stunning-md/analyze/plan.ts","../src/stunning-md/classifier.ts","../src/stunning-md/components/media.tsx","../src/components/ui/carousel.tsx","../src/components/ui/dialog.tsx","../src/stunning-md/components/hero.tsx","../src/stunning-md/components/plain.tsx","../src/stunning-md/components/section.tsx","../src/stunning-md/components/blocks.tsx","../src/stunning-md/components/data-block.tsx","../src/components/ui/popover.tsx","../src/components/ui/table.tsx","../src/stunning-md/components/use-chat.ts"],"sourcesContent":["\"use client\"\n\nimport { useCallback, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { settledMarkdown, type Chat } from \"../chat\"\nimport type { Classify } from \"../classifier\"\nimport { chartThemeFor } from \"../theme/chart\"\nimport { fontPairings, googleFontsUrl, themeChoice, themeVars } from \"../theme/themes\"\nimport type { Appearance, DocumentPlan, PaletteId, ThemeChoice, TocEntry } from \"../types\"\nimport { ChatDock, SidebarContents } from \"./chat-ui\"\nimport { StunningProvider, type StunningContext } from \"./context\"\nimport { Nav, Sidebar, scrollToId, useReadingPosition, type View } from \"./nav\"\nimport { TurnView, useFonts, type TurnReport } from \"./turn\"\nimport { useChatSession } from \"./use-chat\"\n\nexport type StunningMarkdownProps = {\n /** The document to show. May be empty when `chat` is given: the page then starts blank. */\n markdown: string\n /**\n * The text is still being written — by a model, say — and `markdown` will\n * keep growing. The page is then laid out as the text arrives: a section at a\n * time, as each is completed, in a theme chosen once from the opening. Pass\n * the text so far on every update, and `false` (or nothing) when it is done.\n */\n streaming?: boolean\n /**\n * Turns the page into a conversation: a floating input sends requests to this\n * function, and each answer is laid out below as content while the model's\n * remarks about it stay in the sidebar.\n */\n chat?: Chat\n /**\n * Answers the judgement calls structure cannot settle (theme, typography,\n * ambiguous tables, hero image). Without it everything is decided by rules.\n */\n classifier?: Classify\n /** Fixes parts of the theme — palette, typefaces or corner style — overriding everything else. */\n theme?: Partial<ThemeChoice>\n /**\n * Choose a theme to suit each document and each answer. Default `true`. Set\n * it to `false` to stay on one theme throughout — `theme.palette` if given,\n * otherwise `paper` — with nothing asked of the classifier about it. The\n * reader can switch it either way from the theme menu.\n */\n autoTheme?: boolean\n /** `auto` follows the reader's system setting. */\n appearance?: Appearance | \"auto\"\n /** Maps URLs in the markdown (e.g. relative image paths) to loadable ones. */\n resolveUrl?: (url: string) => string\n /** Let the reader edit the text in the markdown view. Edits stay in the page unless you handle `onMarkdownChange`. */\n editable?: boolean\n /** Called with the new text when the reader's edits are applied. */\n onMarkdownChange?: (markdown: string) => void\n /** Show the theme, layout and chart-form pickers. Default `true`. */\n controls?: boolean\n /** Load the theme's typefaces from Google Fonts. Default `true`. */\n loadFonts?: boolean\n /** Longest wait for an image to report its size, in ms. Default 2500. */\n settleMs?: number\n /**\n * Longest the loader stays up waiting for the classifier and fonts, in ms.\n * Normally it lifts much sooner — as soon as the theme is chosen and the first\n * sections have stopped moving. Default 8000.\n */\n maxWaitMs?: number\n /**\n * A control of your own — a single button or link with an icon — shown as a\n * round button to the left of the chat input.\n */\n chatAccessory?: React.ReactNode\n className?: string\n /** Called whenever the plan or theme changes — useful for debugging and tooling. */\n onPlan?: (plan: DocumentPlan, theme: ThemeChoice) => void\n}\n\nconst identity = (url: string) => url\nconst noop = () => {}\n\nfunction useSystemAppearance(): Appearance {\n return useSyncExternalStore(\n (notify) => {\n const query = window.matchMedia(\"(prefers-color-scheme: dark)\")\n query.addEventListener(\"change\", notify)\n return () => query.removeEventListener(\"change\", notify)\n },\n () => (window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"),\n () => \"light\",\n )\n}\n\n/** The component must be at least this wide, in px, before the contents sit beside the document. */\nconst SIDEBAR_MIN_WIDTH = 1400\n\n/** Whether the element is wide enough — measured on the component, not the window, so embedding works. */\nfunction useWide(target: React.RefObject<HTMLElement | null>, minWidth: number): boolean {\n const [wide, setWide] = useState(false)\n useEffect(() => {\n const el = target.current\n if (!el) return\n const observer = new ResizeObserver(([entry]) => setWide(entry.contentRect.width >= minWidth))\n observer.observe(el)\n return () => observer.disconnect()\n }, [target, minWidth])\n return wide\n}\n\n/** The look of the chat itself — sidebar and input — whatever the turns are wearing. */\nconst CHAT_THEME = themeChoice(\"ink\")\n\n/** How much of a document that is still being written must be there before its theme is chosen, in characters. */\nconst OPENING_LENGTH = 300\nconst FRONTMATTER = /^---[ \\t]*\\r?\\n[\\s\\S]*?\\n(---|\\.\\.\\.)[ \\t]*(\\r?\\n|$)/\n\n/** The opened document is the first thing on the page; chat turns follow it. */\nconst DOCUMENT = \"doc\"\n\n/** The first few words of some text, for pointing at a passage that has no heading. */\nconst opening = (text: string) => {\n const words = text.replace(/\\s+/g, \" \").trim().split(\" \")\n return words.length > 9 ? `${words.slice(0, 9).join(\" \")} …` : words.join(\" \")\n}\n\nfunction Page({\n markdown,\n streaming = false,\n chat,\n chatAccessory,\n editable = false,\n onMarkdownChange,\n classifier,\n theme: fixedTheme,\n autoTheme: autoThemeProp = true,\n appearance: appearanceProp = \"auto\",\n resolveUrl = identity,\n controls = true,\n loadFonts = true,\n settleMs = 2500,\n maxWaitMs = 8000,\n className,\n onPlan,\n}: StunningMarkdownProps) {\n const root = useRef<HTMLDivElement>(null)\n const [view, setView] = useState<View>(\"designed\")\n const [appearancePick, setAppearancePick] = useState<Appearance | null>(null)\n const [palettePicks, setPalettePicks] = useState<Record<string, PaletteId>>({})\n const [reports, setReports] = useState<Record<string, TurnReport>>({})\n const [documentReady, setDocumentReady] = useState(false)\n\n // A document that arrives a little at a time is shown as far as it is complete.\n // Having grown on the page, it keeps the look it chose at the start — and there\n // was never a finished page to hold back behind a loader.\n const [streamed, setStreamed] = useState(streaming)\n if (streaming && !streamed) setStreamed(true)\n const settled = useMemo(() => (streaming ? settledMarkdown(markdown) : null), [streaming, markdown])\n const shown = settled ? settled.markdown : markdown\n const writing = settled?.writing ?? null\n // Its theme is chosen from everything written so far — once that is enough to\n // choose by, or all there is going to be.\n const themeBasis = !streaming || markdown.replace(FRONTMATTER, \"\").trim().length >= OPENING_LENGTH ? markdown : null\n\n const hasDocument = streaming || markdown.trim().length > 0\n // Where the reader was before a turn took them to its place on the page.\n const before = useRef(0)\n const session = useChatSession({\n chat,\n classifier,\n document: hasDocument ? markdown : \"\",\n // Bring the new turn into view; its content will appear there.\n onTurnStart: useCallback((turnId: string) => {\n before.current = window.scrollY\n setTimeout(() => scrollToId(`${turnId}-turn`), 80)\n }, []),\n // The model had nothing for the page: its place is gone, so go back to where the reader was.\n onTurnEmpty: useCallback(() => {\n setTimeout(() => {\n const reduce = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n window.scrollTo({ top: before.current, behavior: reduce ? \"auto\" : \"smooth\" })\n }, 80)\n }, []),\n })\n\n // The turns on the page, top to bottom. A turn with nothing to show takes no room.\n const turns = useMemo(() => {\n const placed = session.turns.filter((turn) => (turn.streaming && !turn.unanswered) || turn.markdown.trim())\n // On a page with nothing on it yet, the request is shown where the answer would\n // go before it is known to want one: there is nothing else there to look at.\n const blank = !hasDocument && placed.length === 0\n return [\n ...(hasDocument ? [{ id: DOCUMENT, prefix: \"\", markdown: shown, streaming, waiting: streaming && !markdown.trim(), writing, request: \"\", idle: false }] : []),\n ...(blank ? session.turns.filter((turn) => turn.streaming) : placed).map((turn) => ({ ...turn, prefix: `${turn.id}-`, idle: turn.unanswered })),\n ]\n }, [hasDocument, shown, streaming, markdown, writing, session.turns])\n\n const report = useCallback(\n (id: string, next: TurnReport) => {\n setReports((all) => (all[id]?.plan === next.plan && all[id]?.theme === next.theme ? all : { ...all, [id]: next }))\n if (id === DOCUMENT && next.theme) onPlan?.(next.plan, next.theme)\n },\n [onPlan],\n )\n\n // What a turn put on the page, as a short list: its title and headings, or —\n // if it has none — its opening words.\n const refsOf = useCallback(\n (turnId: string): TocEntry[] => {\n const plan = reports[turnId]?.plan\n if (!plan) return []\n const title: TocEntry[] = plan.hero.titleText ? [{ id: `${turnId}-turn`, text: plan.hero.titleText, depth: 0 }] : []\n if (title.length || plan.toc.length) return [...title, ...plan.toc]\n const text = plan.hero.lead.length\n ? plan.hero.lead.flat().map((node) => (\"value\" in node ? node.value : \"\")).join(\"\")\n : (session.turns.find((turn) => turn.id === turnId)?.markdown ?? \"\")\n return text.trim() ? [{ id: `${turnId}-turn`, text: opening(text.replace(/[#*_`>|]/g, \"\")), depth: 0 }] : []\n },\n [reports, session.turns],\n )\n\n const documentPlan = hasDocument ? reports[DOCUMENT]?.plan : undefined\n const anchors = useMemo(\n () => turns.flatMap((turn) => [`${turn.id}-turn`, ...(reports[turn.id]?.plan.toc.map((entry) => entry.id) ?? [])]),\n [turns, reports],\n )\n const position = useReadingPosition(anchors, root)\n\n // The bar takes on the look of the turn being read — or, while a new turn has\n // yet to choose one, the plain look of the chat.\n const activeTurn = useMemo(() => {\n const active = position.active\n const owner = active && turns.find((turn) => active === `${turn.id}-turn` || reports[turn.id]?.plan.toc.some((entry) => entry.id === active))\n return (owner || turns[0])?.id ?? null\n }, [position.active, turns, reports])\n const system = useSystemAppearance()\n const appearance: Appearance = appearancePick ?? (appearanceProp === \"auto\" ? system : appearanceProp)\n // Themes follow the content, each turn its own — unless that is switched off,\n // in which case one theme is worn by the whole page and everything added to it.\n const [autoTheme, setAutoTheme] = useState(autoThemeProp)\n const [pagePick, setPagePick] = useState<PaletteId | null>(null)\n const pageTheme: PaletteId = pagePick ?? fixedTheme?.palette ?? \"paper\"\n const theme = useMemo<ThemeChoice>(\n () => ({\n ...(autoTheme ? (activeTurn && reports[activeTurn]?.theme) || themeChoice(palettePicks[\"\"] ?? \"ink\") : themeChoice(pageTheme)),\n ...fixedTheme,\n }),\n [autoTheme, pageTheme, activeTurn, reports, palettePicks, fixedTheme],\n )\n const style = useMemo(() => themeVars(theme, appearance), [theme, appearance])\n // The conversation is not part of any one answer: its sidebar and input keep a\n // plain look of their own while the turns beside them each wear their theme.\n const neutralStyle = useMemo(() => themeVars(CHAT_THEME, appearance), [appearance])\n const chatStyle = chat ? neutralStyle : undefined\n useFonts(googleFontsUrl(fontPairings[CHAT_THEME.fonts]), loadFonts && !!chat)\n const chartTheme = useMemo(() => chartThemeFor(theme), [theme])\n const context = useMemo<StunningContext>(\n () => ({\n resolveUrl,\n appearance,\n theme,\n chartTheme,\n portal: { className: cn(\"smd-portal\", appearance === \"dark\" && \"dark\"), style },\n controls,\n setLayout: noop,\n setViz: noop,\n }),\n [resolveUrl, appearance, theme, chartTheme, style, controls],\n )\n\n // Contents and conversation: beside the page when there is room for both, in a sheet otherwise.\n const hasContents = view !== \"source\" && (!!chat || !!documentPlan?.showToc)\n const wide = useWide(root, SIDEBAR_MIN_WIDTH)\n // A document's contents are open from the start. A conversation stays out of the\n // way until there is something in it: it opens when the first reply starts to\n // arrive. Either way, the reader's own choice then stands.\n const [sidebarPick, setSidebarPick] = useState<boolean | null>(null)\n const replied = session.items.some((item) => item.type !== \"user\")\n const sidebarWanted = sidebarPick ?? (chat ? replied : true)\n const sidebarId = useId()\n const sidebar = useMemo(\n () => ({ available: wide && hasContents, open: sidebarWanted, toggle: () => setSidebarPick(!sidebarWanted), id: sidebarId }),\n [wide, hasContents, sidebarWanted, sidebarId],\n )\n const showSidebar = sidebar.available && sidebar.open\n // On a narrower screen the same contents open in a sheet over the page.\n const [sheetWanted, setSheetWanted] = useState(false)\n const menu = useMemo(() => ({ open: sheetWanted, onOpenChange: setSheetWanted }), [sheetWanted])\n const showSheet = sheetWanted && hasContents && !sidebar.available\n // What the conversation's end depends on: its entries, the headings listed for\n // each answer — which keep arriving after the entry itself — and whether a\n // reply is still being written.\n const listed = session.items.reduce((sum, item) => sum + (item.type === \"contents\" ? refsOf(item.turnId).length : 0), 0)\n const tail = session.items.length ? `${session.items.length}:${listed}:${session.busy}` : \"\"\n const meta = documentPlan ? `${documentPlan.readingTime} min read · ${documentPlan.sections.filter((s) => s.titleText).length} sections` : \"\"\n const renderContents = (navigate: (id: string) => void) => (\n <SidebarContents\n document={documentPlan ? { toc: documentPlan.toc, meta } : null}\n chat={!!chat}\n items={session.items}\n refsOf={refsOf}\n active={position.active}\n busy={session.busy}\n onNavigate={navigate}\n />\n )\n\n // The bar names the turn being read; a turn without a title of its own is named by its section alone.\n const title = (activeTurn && reports[activeTurn]?.plan.hero.titleText) || \"\"\n const crumb = useMemo(() => {\n for (const turn of turns) {\n const toc = reports[turn.id]?.plan.toc ?? []\n const index = toc.findIndex((entry) => entry.id === position.active)\n if (index >= 0) return (toc.slice(0, index + 1).findLast((entry) => entry.depth === 0) ?? toc[index]).text\n }\n return null\n }, [turns, reports, position.active])\n\n // The document is laid out under a loader until its top has settled; a blank page has nothing to wait for.\n const ready = !hasDocument || documentReady || streamed\n const markReady = useCallback(() => setDocumentReady(true), [])\n\n const nav = (\n <Nav\n title={title}\n titleTarget={activeTurn ? `${activeTurn}-turn` : undefined}\n crumb={crumb}\n contents={\n hasContents\n ? { label: \"Contents\", description: meta, showTitle: !chat, style: chatStyle, docked: !!chat, tail, render: renderContents }\n : null\n }\n root={root}\n bar={position.bar}\n sidebar={sidebar}\n menu={menu}\n view={view}\n onView={setView}\n onPalette={(palette) => (autoTheme ? setPalettePicks((all) => ({ ...all, [activeTurn ?? \"\"]: palette })) : setPagePick(palette))}\n autoTheme={autoTheme}\n onAutoTheme={(next) => {\n // Staying on a theme means staying on the one in front of the reader.\n if (!next) setPagePick(theme.palette)\n setAutoTheme(next)\n }}\n onAppearance={setAppearancePick}\n />\n )\n\n return (\n <StunningProvider value={context}>\n <div\n ref={root}\n className={cn(\"smd\", appearance === \"dark\" && \"dark\", className)}\n style={style}\n data-theme={theme.palette}\n data-ready={ready}\n data-chat={chat ? \"\" : undefined}\n aria-busy={!ready}\n >\n {!ready && (\n <div className=\"smd-loader\" role=\"status\" aria-live=\"polite\">\n <div>\n <span className=\"smd-loader-mark\" aria-hidden />\n <p>Stunnifying ...</p>\n </div>\n </div>\n )}\n {/* Laid out beneath the loader so its final shape can be measured before it is shown. */}\n <div className=\"smd-document\" inert={!ready}>\n <a href={`#${turns[0] ? `${turns[0].id}-turn` : \"smd-main\"}`} className=\"smd-skip\">\n Skip to content\n </a>\n {!chat && nav}\n <div className=\"smd-body\" data-sidebar={sidebar.available ? (sidebar.open ? \"open\" : \"closed\") : undefined}>\n <div className=\"smd-content\">\n {/* With chat, the bar belongs to the page; the conversation runs the full height beside both. */}\n {chat && nav}\n <main id=\"smd-main\">\n {turns.map((turn, index) => (\n <div key={turn.id} className=\"smd-turn-slot\">\n {/* Turns are set apart by a band of empty page. */}\n {index > 0 && <div className=\"smd-turn-gap\" aria-hidden />}\n <TurnView\n id={turn.id}\n prefix={turn.prefix}\n markdown={turn.markdown}\n streaming={turn.streaming}\n waiting={turn.waiting}\n idle={turn.idle}\n // Until the answer starts, the turn shows what was asked in its place.\n asked={turn.request || undefined}\n writing={turn.writing}\n lockTheme={turn.id !== DOCUMENT || streamed}\n themeContext={turn.request || undefined}\n opening={turn.id === DOCUMENT && streamed ? themeBasis : undefined}\n // A turn that has yet to choose its look waits in the plain one, whatever the page around it is wearing.\n pendingStyle={turn.id !== DOCUMENT || streamed ? neutralStyle : undefined}\n // The newest answer gets a full window to itself, so it can be brought to\n // the top as soon as it starts and its content arrives in view.\n fill={turn.id !== DOCUMENT && index === turns.length - 1}\n onReady={turn.id === DOCUMENT && !streamed ? markReady : undefined}\n classifier={classifier}\n fixedTheme={fixedTheme}\n palettePick={autoTheme ? (palettePicks[turn.id] ?? null) : pageTheme}\n autoTheme={autoTheme}\n appearance={appearance}\n resolveUrl={resolveUrl}\n controls={controls}\n editable={editable && turn.id === DOCUMENT && !streaming}\n loadFonts={loadFonts}\n settleMs={settleMs}\n maxWaitMs={maxWaitMs}\n view={view}\n onReport={report}\n onMarkdownChange={turn.id === DOCUMENT ? onMarkdownChange : undefined}\n />\n </div>\n ))}\n {chat && turns.length === 0 && (\n <div className=\"smd-empty\">\n <p>A blank page.</p>\n <p>Ask for something below and it will be laid out here.</p>\n </div>\n )}\n </main>\n {chat && (\n <ChatDock\n notes={session.notes}\n busy={session.busy}\n quiet={showSidebar || showSheet}\n over={showSheet}\n accessory={chatAccessory}\n style={chatStyle}\n onSend={session.send}\n onStop={session.stop}\n />\n )}\n </div>\n {/* Kept in place while shut, so that opening and closing can be shown as a movement. */}\n {sidebar.available && (\n <Sidebar\n hidden={!sidebar.open}\n id={sidebarId}\n title=\"Contents\"\n showTitle={!chat}\n active={position.active}\n tail={tail}\n style={chatStyle}\n >\n {renderContents(scrollToId)}\n </Sidebar>\n )}\n </div>\n </div>\n </div>\n </StunningProvider>\n )\n}\n\n/**\n * Renders a markdown string as a designed, responsive page: a hero, sections\n * laid out by the shape of their content, charts for tabular data, a contents\n * menu, and a theme chosen to suit the text. With `chat`, the page also takes\n * requests, and lays each answer out below as it is written.\n */\nexport function StunningMarkdown(props: StunningMarkdownProps) {\n const { markdown, streaming = false, onMarkdownChange } = props\n // A different document starts from a clean slate — no stale sizes, judgements,\n // picks or conversation. The reader's own edit coming back through the\n // `markdown` prop is the same document, and must not reset anything. Nor must\n // a document that is still being written, for as long as it carries on from\n // what was there; one that starts over is a new document.\n const [identity, setIdentity] = useState<{ markdown: string; streaming: boolean; key: number; echo: string | null }>({ markdown, streaming, key: 0, echo: null })\n let current = identity\n if (markdown !== identity.markdown || streaming !== identity.streaming) {\n const grows = (streaming || identity.streaming) && markdown.startsWith(identity.markdown.slice(0, 64))\n const same = markdown === identity.markdown || markdown === identity.echo || grows\n current = { markdown, streaming, key: same ? identity.key : identity.key + 1, echo: identity.echo }\n setIdentity(current)\n }\n const handleChange = useCallback(\n (text: string) => {\n setIdentity((previous) => ({ ...previous, echo: text }))\n onMarkdownChange?.(text)\n },\n [onMarkdownChange],\n )\n return <Page key={current.key} {...props} onMarkdownChange={handleChange} />\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import type { Classify } from \"./classifier\"\n\nexport type ChatMessage = { role: \"system\" | \"user\" | \"assistant\"; content: string }\n\n/**\n * Anything that answers a conversation with a stream of text: usually\n * `createChat` pointed at an OpenAI-compatible endpoint or at your own proxy.\n */\nexport type Chat = (messages: ChatMessage[], signal?: AbortSignal) => AsyncIterable<string>\n\n/**\n * A chat function for an OpenAI-compatible `chat/completions` endpoint, read as\n * a stream. Point it at a route on your own server when the provider needs a key\n * (see `createChatHandler` in `stunning-md/server`); a key in browser code is public.\n */\nexport function createChat(options: { endpoint: string; model?: string; headers?: Record<string, string> }): Chat {\n return async function* (messages, signal) {\n const response = await fetch(options.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"text/event-stream\", ...options.headers },\n body: JSON.stringify({ ...(options.model ? { model: options.model } : {}), messages, stream: true }),\n signal,\n })\n if (!response.ok || !response.body) {\n const detail = await response.text().catch(() => \"\")\n throw new Error(`chat responded ${response.status}${detail ? `: ${detail.slice(0, 200)}` : \"\"}`)\n }\n // Some servers ignore `stream` and answer in one piece.\n if ((response.headers.get(\"content-type\") ?? \"\").includes(\"application/json\")) {\n const data = await response.json()\n const failure = errorIn(data)\n if (failure) throw new Error(failure)\n const whole = data?.choices?.[0]?.message?.content\n if (typeof whole === \"string\") yield whole\n return\n }\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = \"\"\n // Text that is not part of the event stream — some providers report an error this way, under a 200.\n let stray = \"\"\n let yielded = false\n for (;;) {\n const { done, value } = await reader.read()\n buffer += done ? decoder.decode() : decoder.decode(value, { stream: true })\n const lines = buffer.split(\"\\n\")\n buffer = done ? \"\" : (lines.pop() ?? \"\")\n for (const raw of lines) {\n const line = raw.trim()\n if (!line.startsWith(\"data:\")) {\n if (line && !line.startsWith(\":\") && stray.length < 4000) stray += raw\n continue\n }\n const payload = line.slice(5).trim()\n if (payload === \"[DONE]\") return\n let event: unknown\n try {\n event = JSON.parse(payload)\n } catch {\n // A partial line; nothing to show.\n continue\n }\n const failure = errorIn(event)\n if (failure) throw new Error(failure)\n const delta = (event as { choices?: { delta?: { content?: unknown } }[] })?.choices?.[0]?.delta?.content\n if (typeof delta === \"string\" && delta) {\n yielded = true\n yield delta\n }\n }\n if (done) break\n }\n if (!yielded && stray.trim()) {\n let failure: string | null = null\n try {\n failure = errorIn(JSON.parse(stray))\n } catch {\n // Not JSON: nothing recognisable to report.\n }\n throw new Error(failure ?? \"the chat model returned nothing\")\n }\n }\n}\n\n/** The message of an error object, in the shapes providers use: `{ error }` or `[{ error }]`. */\nfunction errorIn(body: unknown): string | null {\n const first = Array.isArray(body) ? body[0] : body\n const error = (first as { error?: unknown } | null)?.error\n if (!error) return null\n if (typeof error === \"string\") return error\n const message = (error as { message?: unknown }).message\n return typeof message === \"string\" && message ? message : \"the chat model reported an error\"\n}\n\n/**\n * The address of an OpenAI-compatible chat endpoint, given either the full\n * `…/chat/completions` address or just the API's base (`…/v1`).\n */\nexport function chatCompletionsUrl(url: string): string {\n const trimmed = url.trim().replace(/\\/+$/, \"\")\n return /\\/chat\\/completions$/.test(trimmed) ? trimmed : `${trimmed}/chat/completions`\n}\n\n// --- splitting a reply into blocks ----------------------------------------------\n\nexport type BlockKind = \"heading\" | \"paragraph\" | \"other\"\n\nexport type ReplyBlock = {\n text: string\n kind: BlockKind\n /** Heading level, for headings. */\n depth?: number\n}\n\nconst HEADING = /^(#{1,6})\\s+\\S/\nconst FENCE = /^\\s{0,3}(```+|~~~+)/\nconst NOT_PROSE = /^(\\s{0,3}([-*+]|\\d+[.)])\\s|\\s{0,3}>|\\s{0,3}\\||\\s{0,3}(-{3,}|\\*{3,}|_{3,})\\s*$|\\s{0,3}<|\\s{2,}\\S|!\\[[^\\]]*\\]\\([^)]*\\)\\s*$|\\[!\\[)/\n\nfunction describe(text: string): ReplyBlock {\n const first = text.split(\"\\n\")[0]\n const heading = HEADING.exec(first)\n if (heading) return { text, kind: \"heading\", depth: heading[1].length }\n const table = /^\\s{0,3}\\|?\\s*:?-{3,}/.test(text.split(\"\\n\")[1] ?? \"\")\n // A line set wholly in bold is a title in all but name.\n const boldLine = /^\\*\\*[^*\\n]+\\*\\*:?$/.test(text)\n if (FENCE.test(first) || first.startsWith(\"$$\") || NOT_PROSE.test(first) || table || boldLine) return { text, kind: \"other\" }\n return { text, kind: \"paragraph\" }\n}\n\n/**\n * Cuts markdown, as it streams in, into the blocks a reader would recognise:\n * paragraphs, headings, lists, tables, code. A block is released once it is\n * known to be complete — at the blank line after it, or at the end.\n */\nexport class BlockSplitter {\n private pending = \"\"\n private lines: string[] = []\n private fence: string | null = null\n private math = false\n\n private flush(out: ReplyBlock[]) {\n const text = this.lines.join(\"\\n\").trim()\n this.lines = []\n if (text) out.push(describe(text))\n }\n\n private take(line: string, out: ReplyBlock[]) {\n const fence = FENCE.exec(line)\n if (this.fence) {\n this.lines.push(line)\n if (fence && fence[1].startsWith(this.fence[0]) && fence[1].length >= this.fence.length && !line.trim().slice(fence[1].length).trim()) {\n this.fence = null\n }\n return\n }\n if (this.math) {\n this.lines.push(line)\n if (line.trim().endsWith(\"$$\")) this.math = false\n return\n }\n if (fence) {\n this.lines.push(line)\n this.fence = fence[1]\n return\n }\n if (line.trim().startsWith(\"$$\") && this.lines.length === 0) {\n this.lines.push(line)\n this.math = !(line.trim().length > 2 && line.trim().endsWith(\"$$\"))\n return\n }\n if (!line.trim()) return this.flush(out)\n // A heading is a block of its own, with or without blank lines around it.\n if (HEADING.test(line)) {\n this.flush(out)\n this.lines.push(line)\n return this.flush(out)\n }\n this.lines.push(line)\n }\n\n /** Feed more text; returns the blocks that are now complete. */\n push(text: string): ReplyBlock[] {\n const out: ReplyBlock[] = []\n this.pending += text\n const lines = this.pending.split(\"\\n\")\n this.pending = lines.pop() ?? \"\"\n for (const line of lines) this.take(line.replace(/\\r$/, \"\"), out)\n return out\n }\n\n /** The stream is over; returns whatever was still open. */\n end(): ReplyBlock[] {\n const out: ReplyBlock[] = []\n if (this.pending) this.take(this.pending, out)\n this.pending = \"\"\n this.fence = null\n this.math = false\n this.flush(out)\n return out\n }\n\n}\n\nconst FRONTMATTER_OPEN = /^---[ \\t]*\\r?\\n/\n\n/**\n * How much of a markdown text that is still being written is ready to be laid\n * out. Given the text so far, returns the part that will not change shape as\n * more arrives, and the heading of the section being written.\n *\n * A section is ready once the next one starts, so its layout is decided once.\n * Text before the first heading, and the opening under a `# Title`, is ready a\n * block at a time. A line, code fence or frontmatter block that is not yet\n * closed is never included.\n */\nexport function settledMarkdown(text: string): { markdown: string; writing: string | null } {\n let start = 0\n if (FRONTMATTER_OPEN.test(text)) {\n const opening = FRONTMATTER_OPEN.exec(text)![0].length\n // Too early to tell frontmatter from a rule: wait for the line after it.\n if (text.length === opening) return { markdown: \"\", writing: null }\n if (/\\S/.test(text[opening])) {\n const close = /\\n(---|\\.\\.\\.)[ \\t]*\\r?\\n/.exec(text.slice(opening - 1))\n if (!close) return { markdown: \"\", writing: null }\n start = opening - 1 + close.index + close[0].length\n }\n }\n\n let settled = start\n let writing: string | null = null\n // The depth of the section being collected, if it is held back until the next one starts.\n let open: number | null = null\n let fence: string | null = null\n let math = false\n let inBlock = false\n\n for (let at = start; ; ) {\n const end = text.indexOf(\"\\n\", at)\n // The last line is still being written.\n if (end < 0) break\n const line = text.slice(at, end).replace(/\\r$/, \"\")\n const lineStart = at\n at = end + 1\n\n const marker = FENCE.exec(line)\n if (fence) {\n if (marker && marker[1].startsWith(fence[0]) && marker[1].length >= fence.length && !line.trim().slice(marker[1].length).trim()) fence = null\n continue\n }\n if (math) {\n if (line.trim().endsWith(\"$$\")) math = false\n continue\n }\n if (marker) {\n fence = marker[1]\n inBlock = true\n continue\n }\n if (line.trim().startsWith(\"$$\") && !inBlock) {\n math = !(line.trim().length > 2 && line.trim().endsWith(\"$$\"))\n inBlock = true\n continue\n }\n if (!line.trim()) {\n // Outside a section, and in the opening under a title, each block stands as soon as it ends.\n if (open === null) settled = at\n else if (open === 1 && inBlock) {\n settled = at\n open = null\n }\n inBlock = false\n continue\n }\n const heading = HEADING.exec(line)\n if (heading) {\n const depth = heading[1].length\n writing = line.replace(/^#{1,6}\\s+/, \"\").replace(/\\s+#+\\s*$/, \"\")\n // A sub-heading continues the open section; anything at its level or above starts a new one.\n if (!(open !== null && open !== 1 && depth > open)) {\n settled = lineStart\n open = depth\n }\n inBlock = false\n continue\n }\n inBlock = true\n }\n return { markdown: text.slice(0, settled), writing }\n}\n\n// --- sorting a reply into commentary and content ---------------------------------\n\nexport type TurnEvent =\n /** Something the assistant said about its answer, not part of it. */\n | { type: \"commentary\"; text: string }\n /** The answer so far: every section that is complete, as one markdown document. */\n | { type: \"content\"; markdown: string }\n /** What is being written now — the heading of the section in progress, if it has one. */\n | { type: \"writing\"; heading: string | null }\n /**\n * Whether the reply is an answer at all. Sent with `false` when the model\n * opens by saying it does not know, cannot help or needs to ask something —\n * there will be nothing for the page — and with `true` if content follows after all.\n */\n | { type: \"answer\"; answered: boolean }\n\nexport type TurnResult = {\n /** Everything the model said, untouched. */\n raw: string\n /** The answer only, without commentary. */\n content: string\n}\n\nconst COMMENTARY_QUESTION = {\n type: \"noul\" as const,\n criteria: {\n true: \"the assistant is addressing the user directly about its answer (for example 'Here is…', 'Sure', 'Let me know…', 'I have…', 'Want me to…')\",\n false: \"a passage of the document itself, giving information to its readers\",\n },\n}\n\n/** Wording that marks a paragraph as addressed to the user rather than written for the page. */\nconst ADDRESSES_USER =\n /^(sure|certainly|of course|absolutely|great|okay|ok|alright|got it|no problem|here[’']?s|here (is|are)|below (is|are|you)|i[’'](ve|ll|d)\\b|i (have|will|can|kept|made|added|drafted|wrote|put|used|assumed|left)\\b|let me\\b|hope (this|that)|want me to|would you like|do you want|should i\\b|feel free|happy to|if you[’']?d like|if you would like|is there anything|anything else)|\\blet me know\\b|\\bwant me to\\b|\\bwould you like me to\\b/i\n\nconst ANSWERS_QUESTION = {\n type: \"noul\" as const,\n criteria: {\n true: \"the assistant knows the answer and is providing it\",\n false: \"the assistant does not know the answer, cannot help, or asks a question back\",\n },\n}\n\n/** Openings that give no answer — used when there is no classifier to ask. */\nconst NO_ANSWER =\n /^(sorry|apologies|unfortunately|i[’']?m (not sure|sorry|afraid|unable|not able)|i (don[’']?t|do not|can[’']?t|cannot|couldn[’']?t|am not able|am unable)\\b|(could|can|would) you (please )?(clarify|tell|share|provide|say|explain|rephrase|give)|what (do you mean|would you like|exactly))/i\n\nconst WANTS_CONTENT_QUESTION = {\n type: \"noul\" as const,\n criteria: {\n true: \"the user asks for something to be written, explained, listed, compared or added to the page\",\n false: \"the user is only making conversation: a greeting, thanks, small talk, feedback, or a question about the assistant itself\",\n },\n}\n\n/** Below this the classifier takes a message for conversation; it leans towards content, which is the costlier thing to miss. */\nconst CONVERSATION_BELOW = 0.42\n\n/** Messages that are conversation and nothing else — used when there is no classifier to ask. */\nconst SMALL_TALK =\n /^(h+i+|he+y+|hello+|hiya|howdy|yo|good (morning|afternoon|evening|night)|thanks?( you)?|thx|ty|cheers|ok(ay)?|cool|nice( (work|one|job))?|great( (work|job))?|good (work|job)|well done|awesome|perfect|lovely|love it|(that |this |it )?looks? (good|nice|great)|lol|ha(ha)+|bye|goodbye|see you|never ?mind|how are you|how('?s| is) it going|what'?s up|who are you|what are you|what can you do|what (model|llm) are you|are you (there|real|a bot|an ai|ok)|can you hear me|(are )?you there|test(ing)?)\\b(?:[\\s,!.?]+(there|again|everyone|all|you|so much|a lot|very much|today|then|cool|nice|great|thanks?( you)?))*[\\s!.?…]*$/i\n\n/**\n * Whether a message asks for something for the page — as opposed to a greeting,\n * thanks or small talk, whose reply belongs in the conversation alone. Asked\n * before the reply arrives, so the page need not make room for an answer that\n * is never coming. The classifier answers this reliably; without one, only\n * messages that are plainly small talk are taken as such.\n */\nexport function wantsContent(request: string, classify?: Classify, signal?: AbortSignal): Promise<boolean> {\n const text = request.trim()\n const byWording = !SMALL_TALK.test(text)\n if (!classify) return Promise.resolve(byWording)\n return classify({ state: `User: ${text.replace(/\\s+/g, \" \").slice(0, 400)}`, questions: { wants: WANTS_CONTENT_QUESTION } }, signal).then(\n (result) => (result.wants?.type === \"noul\" ? result.wants.noul >= CONVERSATION_BELOW : byWording),\n () => byWording,\n )\n}\n\n/** Where a paragraph sits in the reply — remarks to the user live at its edges. */\ntype Position = \"opening\" | \"inside\" | \"closing\"\n\nconst headingText = (block: ReplyBlock) => block.text.replace(/^#{1,6}\\s+/, \"\").replace(/\\s+#+\\s*$/, \"\")\n\n/**\n * Reads a model's reply as it streams and sorts it, block by block, into\n * commentary (remarks to the user) and content (the thing that was asked for).\n *\n * Headings, lists, tables, code and images are content. Plain paragraphs are\n * judged by where they sit and how they read: remarks to the user come at the\n * start or the end of a reply and usually announce themselves (\"Sure, here\n * is…\", \"Let me know…\"). The classifier is asked about the unclear ones.\n * Without a classifier, the first paragraph of the reply is taken as\n * commentary, and so is the last.\n *\n * Content is released a section at a time, once the section is complete, so a\n * section's layout is decided once and does not shift as it grows. Text that\n * comes before any heading is released paragraph by paragraph.\n */\nexport async function sortReply(options: {\n stream: AsyncIterable<string>\n /** What the user asked — needed to judge whether the reply answers it. */\n request?: string\n /**\n * The user was only making conversation (see `wantsContent`): the reply is\n * taken as conversation too, unless it turns out to carry content after all.\n */\n smallTalk?: boolean | Promise<boolean>\n classify?: Classify\n signal?: AbortSignal\n onEvent: (event: TurnEvent) => void\n}): Promise<TurnResult> {\n const { stream, request, smallTalk, classify, signal, onEvent } = options\n const splitter = new BlockSplitter()\n const released: string[] = []\n let raw = \"\"\n let index = 0\n let lastHeading: string | null = null\n // Once a heading, list or table has appeared, the opening remarks are over.\n let structured = false\n // The section being collected: it is held back until the next section starts.\n let open: { depth: number; blocks: string[] } | null = null\n // Blocks are judged as they complete but handled strictly in order.\n let chain: Promise<void> = Promise.resolve()\n // Whether a paragraph is the last thing in the reply is only known once the\n // next block arrives — or does not.\n let settlePosition: ((position: Position) => void) | null = null\n\n // Set when the reply opens without an answer: nothing is for the page unless real content follows.\n let unanswered = false\n\n /**\n * Whether the reply's opening paragraph is an answer, or the start of one —\n * as opposed to \"I don't know\", \"I can't help\" or a question back. Unlike the\n * remark-or-content question, this is one the classifier answers reliably.\n */\n const answers = async (text: string): Promise<boolean> => {\n // Conversation in, conversation out: there is nothing to ask.\n if (await smallTalk) return false\n if (!classify) return !NO_ANSWER.test(text)\n const state = `${request ? `User: ${request.replace(/\\s+/g, \" \").slice(0, 400)}\\n` : \"\"}Assistant: ${text.slice(0, 700)}`\n return classify({ state, questions: { answers: ANSWERS_QUESTION } }, signal).then(\n (result) => (result.answers?.type === \"noul\" ? result.answers.noul >= 0.5 : !NO_ANSWER.test(text)),\n () => !NO_ANSWER.test(text),\n )\n }\n\n const emitContent = () => onEvent({ type: \"content\", markdown: released.join(\"\\n\\n\") })\n const flush = () => {\n if (!open) return\n released.push(...open.blocks)\n open = null\n emitContent()\n }\n\n const ask = (text: string): Promise<number | null> =>\n classify!({ state: text.slice(0, 700), questions: { commentary: COMMENTARY_QUESTION } }, signal).then(\n (answers) => (answers.commentary?.type === \"noul\" ? answers.commentary.noul : null),\n () => null,\n )\n\n /**\n * Position and wording settle the clear cases; the classifier is asked about\n * the rest. On its own it is not a reliable judge of this, so it is never\n * allowed to overrule both.\n */\n const judge = async (text: string, first: boolean, position: Position): Promise<boolean> => {\n if (!classify) return first || position === \"closing\"\n const cue = ADDRESSES_USER.test(text)\n // In the body of the answer, only a paragraph that both reads like a remark and is judged one counts.\n if (position === \"inside\") return cue ? ((await ask(text)) ?? 0) >= 0.5 : false\n if (cue) return true\n const score = await ask(text)\n // If the classifier cannot be reached, fall back to the unaided rule.\n return score === null ? first || position === \"closing\" : score >= 0.3\n }\n\n const isCommentary = (block: ReplyBlock, first: boolean): Promise<boolean> => {\n if (block.kind !== \"paragraph\") return Promise.resolve(false)\n if (first || (classify && !structured)) return judge(block.text, first, \"opening\")\n return new Promise<Position>((resolve) => {\n settlePosition = resolve\n }).then((position) => judge(block.text, first, position))\n }\n\n const handle = (block: ReplyBlock, commentary: boolean) => {\n if (unanswered) {\n // Everything said around a non-answer is conversation…\n if (block.kind === \"paragraph\") return onEvent({ type: \"commentary\", text: block.text })\n // …unless the model goes on to produce something after all.\n unanswered = false\n onEvent({ type: \"answer\", answered: true })\n }\n if (commentary) return onEvent({ type: \"commentary\", text: block.text })\n if (block.kind === \"heading\") {\n const depth = block.depth ?? 2\n // A sub-heading continues the open section; anything at its level or above starts a new one.\n if (open && open.depth !== 1 && depth > open.depth) {\n open.blocks.push(block.text)\n return\n }\n flush()\n open = { depth, blocks: [block.text] }\n return\n }\n if (open) {\n open.blocks.push(block.text)\n // A title's section is the page's opening: it is shown once it has its first\n // block, and what follows — up to the next heading — arrives a block at a time.\n if (open.depth === 1) flush()\n } else {\n released.push(block.text)\n emitContent()\n }\n }\n\n const accept = (blocks: ReplyBlock[]) => {\n for (const block of blocks) {\n // Something followed the previous paragraph, so it was not the closing one.\n settlePosition?.(\"inside\")\n settlePosition = null\n const first = index++ === 0\n const verdict = isCommentary(block, first)\n // The opening paragraph also says whether there is an answer coming at all.\n const answered = first && block.kind === \"paragraph\" ? answers(block.text) : null\n if (block.kind === \"heading\") lastHeading = headingText(block)\n if (block.kind !== \"paragraph\") structured = true\n chain = chain.then(async () => {\n if (answered && !(await answered)) {\n unanswered = true\n onEvent({ type: \"answer\", answered: false })\n }\n // Nothing more needs judging about a paragraph of a non-answer.\n handle(block, unanswered && block.kind === \"paragraph\" ? true : await verdict)\n })\n }\n }\n\n let writing: string | null | undefined\n for await (const delta of stream) {\n if (signal?.aborted) break\n raw += delta\n accept(splitter.push(delta))\n // Tell the page which section is being written, so it can show that work is under way.\n if (lastHeading !== writing) onEvent({ type: \"writing\", heading: (writing = lastHeading) })\n }\n accept(splitter.end())\n // Nothing follows the final paragraph: it closes the reply.\n ;(settlePosition as ((position: Position) => void) | null)?.(\"closing\")\n await chain\n flush()\n return { raw, content: released.join(\"\\n\\n\") }\n}\n\n/** How the assistant is asked to write, so its answer can be laid out as a page. */\nexport const CHAT_INSTRUCTIONS = [\n \"You are writing for a page that turns markdown into a designed website.\",\n \"Answer in markdown. When asked for a document, start with a `# Title`, add a short opening paragraph, and use `##` sections; use `###` for short sub-points.\",\n \"Use tables for figures, schedules and comparisons, lists for short points, and blockquotes for quotations.\",\n \"The page draws charts by itself: a markdown table of numbers becomes a bar, line or area chart, shares of a whole become a donut, a row of key figures becomes stat tiles, and dated events become a timeline. So when a chart or graph is wanted, just write the data as a plain markdown table — one row per category or period, a header row, units in the header or the cells — and never draw one in text, link an image of one, or write chart code.\",\n \"Keep any remarks to the user — acknowledgements, caveats, questions, offers of more help — in their own short paragraphs, separate from the content.\",\n].join(\" \")\n\n/**\n * How the assistant is told about the document already on the page. What it\n * writes is appended below that document, so it must write only what is new.\n */\nexport function documentContext(markdown: string, limit = 16000): string {\n if (!markdown.trim()) return \"\"\n return [\n \"\",\n \"\",\n \"The page already shows the document below. Whatever you write is added to the page beneath it, as a new part.\",\n \"Write only the new material that was asked for — never reproduce or rewrite the existing document, not even to place the new part in context.\",\n \"\",\n \"<document>\",\n markdown.slice(0, limit),\n \"</document>\",\n ].join(\"\\n\")\n}\n","import { createTheme, type ChartTheme, type ChartThemeTokens, type ThemeId } from \"generative-charts\"\nimport type { Appearance, ThemeChoice } from \"../types\"\nimport { checkPalette, contrast, cvdDistance, deltaE, fromOklch, PALETTE_RULES, toOklch } from \"./color\"\nimport { fontPairings, themes, type ChartStyle, type PaletteTokens } from \"./themes\"\n\n/**\n * The fallback series colours: a fixed order of eight hues known to keep\n * neighbours apart for colour-blind readers. Used only if a theme's own\n * palette cannot be built to the same standard.\n */\nconst REFERENCE = {\n light: [\"#2a78d6\", \"#eb6834\", \"#1baf7a\", \"#eda100\", \"#e87ba4\", \"#008300\", \"#4a3aa7\", \"#e34948\"],\n dark: [\"#3987e5\", \"#d95926\", \"#199e70\", \"#c98500\", \"#d55181\", \"#008300\", \"#9085e9\", \"#e66767\"],\n}\n\nconst SLOTS = 8\nconst cache = new Map<string, string[]>()\n\n/**\n * Builds a theme's series colours from its accent. The accent (moved into the\n * legible lightness band if need be) leads; each further colour is the candidate\n * that stays furthest from the ones before it — to readers with and without\n * colour-vision deficiency. Candidates share the accent's intensity, so a muted\n * theme gets muted charts and a vivid one vivid charts. The result is checked\n * against the same rules as the reference palette and only used if it passes.\n */\nexport function seriesColors(accent: string, surface: string, mode: Appearance): string[] {\n const key = `${accent}|${surface}|${mode}`\n const hit = cache.get(key)\n if (hit) return hit\n\n const [lo, hi] = PALETTE_RULES.band[mode]\n const legible = (hex: string) => contrast(hex, surface) >= PALETTE_RULES.contrastMin\n const source = toOklch(accent)\n // A colourless accent (black ink, white chalk) cannot identify a series; start from a neutral blue.\n const hue = source.c < 0.04 ? 255 : source.h\n\n // The lead colour is the nearest thing to the accent that is legible on the\n // surface and saturated enough to read as a colour. Some hues (teal, for one)\n // cannot hold their saturation when dark, so lightness may move, then hue.\n let anchor = \"\"\n let nearest = Infinity\n for (let shift = 0; shift <= 30; shift += 5) {\n for (const h of shift ? [hue - shift, hue + shift] : [hue]) {\n for (let l = lo + 0.01; l <= hi - 0.01; l += 0.01) {\n const hex = fromOklch({ l, c: Math.max(source.c, 0.12), h: (h + 360) % 360 })\n if (toOklch(hex).c < PALETTE_RULES.chromaFloor + 0.005 || !legible(hex)) continue\n const distance = Math.abs(l - source.l) * 2 + shift / 60\n if (distance < nearest) [anchor, nearest] = [hex, distance]\n }\n }\n }\n\n const levels = mode === \"light\" ? [0.47, 0.55, 0.63, 0.7] : [0.52, 0.58, 0.64]\n const intensity = Math.min(0.17, Math.max(0.115, toOklch(anchor || accent).c))\n\n let result: string[] | null = null\n for (const chroma of [intensity, intensity + 0.02, intensity + 0.04, 0.19]) {\n if (!anchor) break\n const candidates: string[] = []\n for (let h = 0; h < 360; h += 10) {\n for (const l of levels) {\n const hex = fromOklch({ l, c: chroma, h })\n if (toOklch(hex).c >= PALETTE_RULES.chromaFloor + 0.005 && legible(hex)) candidates.push(hex)\n }\n }\n const chosen = [anchor]\n while (chosen.length < SLOTS) {\n const previous = chosen[chosen.length - 1]\n let best = \"\"\n let bestScore = -1\n for (const candidate of candidates) {\n if (chosen.includes(candidate)) continue\n // Neighbours matter most (they touch in bars and legends); every other pair must still differ.\n let score = Math.min(cvdDistance(previous, candidate) / PALETTE_RULES.cvdTarget, deltaE(previous, candidate) / PALETTE_RULES.normalFloor)\n for (const other of chosen) {\n score = Math.min(score, cvdDistance(other, candidate) / 5, deltaE(other, candidate) / 12)\n }\n if (score > bestScore) [best, bestScore] = [candidate, score]\n }\n if (!best) break\n chosen.push(best)\n }\n if (chosen.length === SLOTS && checkPalette(chosen, mode, surface).ok) {\n result = chosen\n break\n }\n }\n\n const palette = result ?? REFERENCE[mode]\n cache.set(key, palette)\n return palette\n}\n\n/** The chart library draws three distinct families; a fourth, plain look comes from using none of them. */\nconst FAMILY: Record<ChartStyle, ThemeId | null> = {\n linework: \"mono-editorial\",\n instrument: \"neon-instruments\",\n soft: \"airform\",\n flat: null,\n}\n\nfunction tokens(palette: PaletteTokens, mode: Appearance, style: ChartStyle, formality: number, fontFamily: string): Partial<ChartThemeTokens> {\n const mix = (amount: number) => `color-mix(in oklab, ${palette.fg} ${amount}%, ${palette.bg})`\n const series = seriesColors(palette.accent, palette.bg, mode)\n const lead = series[0]\n // Linework charts are drawn in ink: series alternate between solid and dashed\n // strokes, as in print, so the second tone only needs to mark the legend.\n const ink = [palette.fg, palette.muted, palette.fg, palette.muted, palette.fg, palette.muted]\n const round = Math.round((1 - formality) * 9)\n return {\n background: \"transparent\",\n plotBackground: \"transparent\",\n surface: palette.surface,\n text: palette.fg,\n textMuted: palette.muted,\n grid: mix(10),\n axis: mix(28),\n border: \"transparent\",\n borderStrong: style === \"linework\" ? palette.fg : mix(28),\n zeroLine: style === \"linework\" ? palette.fg : mix(40),\n palette: style === \"linework\" ? ink : series,\n positive: style === \"linework\" ? palette.fg : lead,\n negative: style === \"linework\" ? palette.fg : mix(55),\n lineUnderlay: palette.bg,\n areaStart: style === \"linework\" ? palette.fg : `color-mix(in oklab, ${lead} 38%, transparent)`,\n areaEnd: style === \"linework\" ? palette.bg : `color-mix(in oklab, ${lead} 3%, transparent)`,\n pointFill: palette.bg,\n pointStroke: style === \"linework\" ? palette.fg : lead,\n pointHalo: style === \"linework\" ? palette.bg : `color-mix(in oklab, ${lead} 20%, transparent)`,\n markHighlight: style === \"soft\" ? \"rgba(255,255,255,.5)\" : style === \"linework\" ? palette.bg : \"rgba(255,255,255,.14)\",\n markShadow:\n style === \"soft\"\n ? `0 10px 22px color-mix(in oklab, ${palette.fg} ${mode === \"dark\" ? 0 : 16}%, transparent)`\n : \"0 0 0 transparent\",\n tooltipBackground: palette.fg,\n tooltipText: palette.bg,\n tooltipBorder: \"transparent\",\n focusRing: palette.accent,\n fontFamily,\n radius: 0,\n markRadius: style === \"linework\" ? 0 : style === \"soft\" ? Math.max(4, round) : round,\n shadow: \"none\",\n }\n}\n\n/**\n * The chart theme for a page theme: series colours grown from its accent, its\n * typeface, its corner style, and the drawing family that suits its character.\n */\nexport function chartThemeFor(choice: ThemeChoice): ChartTheme {\n const theme = themes[choice.palette]\n const fonts = fontPairings[choice.fonts]\n const family = FAMILY[theme.chart]\n const font = theme.chart === \"linework\" ? fonts.mono : fonts.body\n return createTheme(family ?? \"airform\", {\n // A family's distinctive rendering is keyed on its id; any other id draws plainly.\n id: family ?? `stunning-${choice.palette}`,\n name: theme.name,\n light: tokens(theme.light, \"light\", theme.chart, choice.formality, font),\n dark: tokens(theme.dark, \"dark\", theme.chart, choice.formality, font),\n })\n}\n","/**\n * Colour maths for chart palettes: OKLab/OKLCH conversion, colour-vision\n * deficiency simulation (Machado, Oliveira & Fernandes 2009, severity 1.0),\n * and the checks a categorical palette has to clear.\n */\n\nexport type Oklch = { l: number; c: number; h: number }\n\nconst toLinear = (c: number) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4)\nconst fromLinear = (c: number) => (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055)\n\nfunction linearRgb(hex: string): [number, number, number] {\n const h = hex.replace(/^#/, \"\")\n return [0, 2, 4].map((i) => toLinear(parseInt(h.slice(i, i + 2), 16) / 255)) as [number, number, number]\n}\n\nfunction oklabFromLinear([r, g, b]: [number, number, number]): [number, number, number] {\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b)\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b)\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b)\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ]\n}\n\nexport function toOklch(hex: string): Oklch {\n const [l, a, b] = oklabFromLinear(linearRgb(hex))\n return { l, c: Math.hypot(a, b), h: ((Math.atan2(b, a) * 180) / Math.PI + 360) % 360 }\n}\n\nfunction linearFromOklch({ l, c, h }: Oklch): [number, number, number] {\n const a = c * Math.cos((h * Math.PI) / 180)\n const b = c * Math.sin((h * Math.PI) / 180)\n const l3 = (l + 0.3963377774 * a + 0.2158037573 * b) ** 3\n const m3 = (l - 0.1055613458 * a - 0.0638541728 * b) ** 3\n const s3 = (l - 0.0894841775 * a - 1.291485548 * b) ** 3\n return [\n 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3,\n -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3,\n -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3,\n ]\n}\n\nconst inGamut = (rgb: number[]) => rgb.every((v) => v >= -0.0005 && v <= 1.0005)\n\n/** OKLCH to hex, giving up chroma — never hue or lightness — to stay inside sRGB. */\nexport function fromOklch(color: Oklch): string {\n let { c } = color\n if (!inGamut(linearFromOklch(color))) {\n let low = 0\n let high = c\n for (let i = 0; i < 18; i++) {\n c = (low + high) / 2\n if (inGamut(linearFromOklch({ ...color, c }))) low = c\n else high = c\n }\n c = low\n }\n const channel = (v: number) =>\n Math.round(Math.min(1, Math.max(0, fromLinear(Math.min(1, Math.max(0, v))))) * 255)\n .toString(16)\n .padStart(2, \"0\")\n return `#${linearFromOklch({ ...color, c }).map(channel).join(\"\")}`\n}\n\nconst luminance = (hex: string) => {\n const [r, g, b] = linearRgb(hex)\n return 0.2126 * r + 0.7152 * g + 0.0722 * b\n}\n\n/** WCAG contrast ratio. */\nexport function contrast(a: string, b: string): number {\n const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x)\n return (hi + 0.05) / (lo + 0.05)\n}\n\ntype Vision = \"protan\" | \"deutan\"\n\nconst MACHADO: Record<Vision, number[][]> = {\n protan: [\n [0.152286, 1.052583, -0.204868],\n [0.114503, 0.786281, 0.099216],\n [-0.003882, -0.048116, 1.051998],\n ],\n deutan: [\n [0.367322, 0.860646, -0.227968],\n [0.280085, 0.672501, 0.047413],\n [-0.01182, 0.04294, 0.968881],\n ],\n}\n\nfunction simulate(hex: string, vision: Vision): [number, number, number] {\n const rgb = linearRgb(hex)\n return MACHADO[vision].map((row) => Math.min(1, Math.max(0, row[0] * rgb[0] + row[1] * rgb[1] + row[2] * rgb[2]))) as [number, number, number]\n}\n\n/** Distance in OKLab ×100 — as seen with full colour vision, or with a simulated deficiency. */\nexport function deltaE(a: string, b: string, vision?: Vision): number {\n const x = oklabFromLinear(vision ? simulate(a, vision) : linearRgb(a))\n const y = oklabFromLinear(vision ? simulate(b, vision) : linearRgb(b))\n return 100 * Math.hypot(x[0] - y[0], x[1] - y[1], x[2] - y[2])\n}\n\n/** The smaller of the protan and deutan distances: how far apart two colours stay for red-green deficient readers. */\nexport const cvdDistance = (a: string, b: string) => Math.min(deltaE(a, b, \"protan\"), deltaE(a, b, \"deutan\"))\n\nexport const PALETTE_RULES = {\n /** OKLCH lightness a series colour must sit within, per mode. */\n band: { light: [0.43, 0.77], dark: [0.48, 0.67] } as Record<\"light\" | \"dark\", [number, number]>,\n /** Below this chroma a hue reads as grey. */\n chromaFloor: 0.1,\n /** Neighbouring series, simulated red-green deficiency. */\n cvdTarget: 8,\n /** Neighbouring series, full colour vision. */\n normalFloor: 15,\n /** Each mark against the chart surface. */\n contrastMin: 3,\n}\n\nexport type PaletteReport = {\n ok: boolean\n offBand: string[]\n lowChroma: string[]\n worstCvd: number\n worstNormal: number\n lowContrast: string[]\n}\n\n/**\n * Checks a categorical palette, in order: every colour inside the lightness band\n * and above the chroma floor, and each neighbouring pair distinguishable both\n * with full colour vision and under red-green deficiency. Low contrast against\n * the surface is reported but does not fail — charts always offer a table view.\n */\nexport function checkPalette(palette: string[], mode: \"light\" | \"dark\", surface: string): PaletteReport {\n const [lo, hi] = PALETTE_RULES.band[mode]\n const offBand = palette.filter((c) => toOklch(c).l < lo || toOklch(c).l > hi)\n const lowChroma = palette.filter((c) => toOklch(c).c < PALETTE_RULES.chromaFloor)\n let worstCvd = Infinity\n let worstNormal = Infinity\n for (let i = 1; i < palette.length; i++) {\n worstCvd = Math.min(worstCvd, cvdDistance(palette[i - 1], palette[i]))\n worstNormal = Math.min(worstNormal, deltaE(palette[i - 1], palette[i]))\n }\n const lowContrast = palette.filter((c) => contrast(c, surface) < PALETTE_RULES.contrastMin)\n return {\n ok: !offBand.length && !lowChroma.length && worstCvd >= PALETTE_RULES.cvdTarget && worstNormal >= PALETTE_RULES.normalFloor,\n offBand,\n lowChroma,\n worstCvd,\n worstNormal,\n lowContrast,\n }\n}\n","import type { CSSProperties } from \"react\"\nimport type { Appearance, FontPairingId, PaletteId, ThemeChoice } from \"../types\"\n\nexport type PaletteTokens = {\n bg: string\n /** Cards, code blocks and tinted section bands. */\n surface: string\n fg: string\n /** Secondary text. */\n muted: string\n border: string\n accent: string\n accentFg: string\n /**\n * A second colour, where the theme has one: quotations are set in it — a band\n * across the page for a quotation that is a section of its own, a block for one\n * inside an article — so the page has more than one note to play.\n */\n highlight?: { bg: string; fg: string }\n}\n\n/**\n * Chart drawing styles: `linework` is monochrome print-style ink with hatching,\n * `instrument` has rounded, saturated marks on calm surfaces, `soft` adds\n * gradients and depth, and `flat` is plain solid colour.\n */\nexport type ChartStyle = \"linework\" | \"instrument\" | \"soft\" | \"flat\"\n\n/**\n * How a text-led hero is set: `wash` tints the page with a soft glow of the\n * accent; `block` is a cover in the accent colour itself; `ink` is a cover in\n * the theme's darkest tone, the page's colours reversed.\n */\nexport type HeroTone = \"wash\" | \"block\" | \"ink\"\n\n/** The families the themes fall into by subject — how the picker is arranged. */\nexport type ThemeTopic = \"writing\" | \"official\" | \"technology\" | \"lifestyle\" | \"wellbeing\" | \"culture\"\n\nexport const themeTopics: { id: ThemeTopic; name: string }[] = [\n { id: \"writing\", name: \"Writing\" },\n { id: \"official\", name: \"Business & official\" },\n { id: \"technology\", name: \"Technology\" },\n { id: \"lifestyle\", name: \"Places & lifestyle\" },\n { id: \"wellbeing\", name: \"Nature & health\" },\n { id: \"culture\", name: \"Culture & play\" },\n]\n\nexport type Theme = {\n id: PaletteId\n name: string\n /** The family of subjects it belongs to. */\n topic: ThemeTopic\n /**\n * The kinds of document this theme suits — and all the classifier reads when\n * choosing one. Name subjects, not moods: measured against documents of known\n * subject, subjects alone choose better, and in half the time, than subjects\n * with colours and typefaces beside them.\n */\n description: string\n /** Its key colours in a few plain words, for people reading the list. */\n look: string\n /** Typography used unless the caller picks another. */\n fonts: FontPairingId\n /** 0 = soft and rounded … 1 = sharp and formal. Sets the corner radius. */\n formality: number\n /** How charts are drawn under this theme. */\n chart: ChartStyle\n /** How the opening of the page is set off from the rest. */\n hero: HeroTone\n /** Fallback matching when no classifier is configured. */\n keywords: RegExp\n light: PaletteTokens\n dark: PaletteTokens\n}\n\nconst tokens = (\n bg: string,\n surface: string,\n fg: string,\n muted: string,\n border: string,\n accent: string,\n accentFg: string,\n highlight?: string,\n highlightFg?: string,\n): PaletteTokens => ({\n bg,\n surface,\n fg,\n muted,\n border,\n accent,\n accentFg,\n ...(highlight && highlightFg ? { highlight: { bg: highlight, fg: highlightFg } } : {}),\n})\n\nexport const themes: Record<PaletteId, Theme> = {\n paper: {\n id: \"paper\",\n name: \"Paper\",\n topic: \"writing\",\n description: \"essays, short stories, fiction, memoir, opinion, local history\",\n look: \"cream paper, terracotta accent\",\n fonts: \"editorial\",\n formality: 0.5,\n chart: \"flat\",\n hero: \"wash\",\n keywords: /\\b(essay|story|chapter|novel|memoir|poem|letter|journal|philosophy|opinion|notebook|writing)\\b/gi,\n light: tokens(\"#f5eedf\", \"#ebe1cc\", \"#1f1b16\", \"#4e473c\", \"#d6c9b0\", \"#a23f17\", \"#ffffff\"),\n dark: tokens(\"#1b1612\", \"#29221b\", \"#f3ecdf\", \"#b8ad9d\", \"#3f352a\", \"#f0a070\", \"#1a120c\"),\n },\n ink: {\n id: \"ink\",\n name: \"Ink\",\n topic: \"writing\",\n description: \"meeting notes, memos, minutes, plain lists\",\n look: \"white page, black cover, no colour\",\n fonts: \"modern\",\n formality: 0.7,\n chart: \"linework\",\n hero: \"ink\",\n keywords: /\\b(design|minimal|typography|studio|portfolio|notes|memo|manifesto)\\b/gi,\n light: tokens(\"#ffffff\", \"#f1f1f2\", \"#000000\", \"#505056\", \"#d4d4d8\", \"#111111\", \"#ffffff\"),\n dark: tokens(\"#000000\", \"#161618\", \"#ffffff\", \"#a8a8b0\", \"#2e2e33\", \"#f4f4f5\", \"#0a0a0a\"),\n },\n ocean: {\n id: \"ocean\",\n name: \"Ocean\",\n topic: \"official\",\n description: \"business reports, finance, sales, strategy, investors\",\n look: \"cool white, corporate blue cover, amber\",\n fonts: \"modern\",\n formality: 0.6,\n chart: \"soft\",\n hero: \"block\",\n keywords: /\\b(revenue|profit|quarter|q[1-4]|market|investor|financial|growth|customers?|sales|strategy|kpi|forecast|budget|margin|earnings|business)\\b/gi,\n light: tokens(\"#eef4fa\", \"#dce8f4\", \"#0a1f33\", \"#374c63\", \"#bfd2e5\", \"#0a55a0\", \"#ffffff\", \"#f2b84b\", \"#0a1f33\"),\n dark: tokens(\"#0a1a30\", \"#12284a\", \"#eaf2fb\", \"#a0b6ce\", \"#24406b\", \"#6cb8ff\", \"#06121d\", \"#f2b84b\", \"#0a1a30\"),\n },\n forest: {\n id: \"forest\",\n name: \"Forest\",\n topic: \"wellbeing\",\n description: \"nature, environment, outdoors, gardening, biology\",\n look: \"sage green page, deep forest green\",\n fonts: \"friendly\",\n formality: 0.35,\n chart: \"instrument\",\n hero: \"wash\",\n keywords: /\\b(nature|climate|forest|garden|plants?|sustainab\\w+|environment\\w*|organic|wildlife|hiking|ecology|carbon|farm\\w*|valley|trail)\\b/gi,\n light: tokens(\"#e3ecd8\", \"#f5f9ef\", \"#14241a\", \"#3c5040\", \"#c3d2b5\", \"#1f6b35\", \"#ffffff\"),\n dark: tokens(\"#0f2417\", \"#183422\", \"#e8f2e4\", \"#abc1ad\", \"#2b4b36\", \"#8fdc9c\", \"#0b160e\"),\n },\n sunset: {\n id: \"sunset\",\n name: \"Sunset\",\n topic: \"lifestyle\",\n description: \"travel journals, itineraries, destinations, city guides\",\n look: \"apricot page, burnt orange cover\",\n fonts: \"elegant\",\n formality: 0.4,\n chart: \"soft\",\n hero: \"block\",\n keywords: /\\b(travel|trip|beach|hotel|festival|holiday|itinerary|adventure|temples?|shrine|guesthouse|city|walks?|journey|island)\\b/gi,\n light: tokens(\"#fde3cf\", \"#fff5ec\", \"#2a130a\", \"#694133\", \"#efc3a7\", \"#a32c0c\", \"#ffffff\"),\n dark: tokens(\"#24101a\", \"#361a27\", \"#fdeee6\", \"#cfa79b\", \"#4e2839\", \"#ff9a62\", \"#200e06\"),\n },\n violet: {\n id: \"violet\",\n name: \"Violet\",\n topic: \"technology\",\n description: \"tech products, startups, AI, launches, pricing pages\",\n look: \"lavender page, vivid purple cover, lime\",\n fonts: \"friendly\",\n formality: 0.25,\n chart: \"instrument\",\n hero: \"block\",\n keywords: /\\b(product|startup|launch|ai|model|platform|features?|app|saas|creative|innovation|roadmap|pricing|beta)\\b/gi,\n light: tokens(\"#eae4ff\", \"#f8f5ff\", \"#17112e\", \"#4e456e\", \"#cdc2f4\", \"#5a2be0\", \"#ffffff\", \"#c8f560\", \"#17112e\"),\n dark: tokens(\"#170f3a\", \"#231856\", \"#f0ebff\", \"#b3a9db\", \"#382a78\", \"#b39dff\", \"#120b2a\", \"#c8f560\", \"#170f3a\"),\n },\n terminal: {\n id: \"terminal\",\n name: \"Terminal\",\n topic: \"technology\",\n description: \"software docs, READMEs, API and developer guides, framework comparisons\",\n look: \"cool grey, dark slate cover, teal, amber\",\n fonts: \"technical\",\n formality: 0.6,\n chart: \"flat\",\n hero: \"ink\",\n keywords: /\\b(install|npm|api|cli|usage|config\\w*|repository|function|library|docker|git|sdk|endpoint|compile|typescript|python|server|deploy\\w*)\\b/gi,\n light: tokens(\"#edf2f3\", \"#dde6e9\", \"#0b1a20\", \"#354c55\", \"#c0cfd4\", \"#0a6f6a\", \"#ffffff\", \"#ffb000\", \"#0b1a20\"),\n dark: tokens(\"#0a1114\", \"#131f24\", \"#e2ecef\", \"#97acb5\", \"#22333b\", \"#45dcc2\", \"#04201b\", \"#ffb000\", \"#0a1114\"),\n },\n chambers: {\n id: \"chambers\",\n name: \"Chambers\",\n topic: \"official\",\n description: \"legal documents, contracts, policy, regulation\",\n look: \"ivory, navy cover, gold\",\n fonts: \"classic\",\n formality: 0.9,\n chart: \"flat\",\n hero: \"block\",\n keywords: /\\b(agreement|contract|clause|shall|court|law|legal|policy|regulation|act|statute|party|parties|compliance|hereby|pursuant|terms)\\b/gi,\n light: tokens(\"#f6f1e4\", \"#ebe3cf\", \"#111a2e\", \"#3f485c\", \"#d1c7ad\", \"#1f3a6e\", \"#ffffff\", \"#c9a54f\", \"#111a2e\"),\n dark: tokens(\"#0e1526\", \"#18223b\", \"#efe9da\", \"#a8aebd\", \"#2b3654\", \"#d4b46a\", \"#1a1405\", \"#27468a\", \"#f4eee0\"),\n },\n academia: {\n id: \"academia\",\n name: \"Academia\",\n topic: \"official\",\n description: \"scholarly papers, research, theses, lecture notes, science explainers\",\n look: \"parchment, oxblood red\",\n fonts: \"scholarly\",\n formality: 0.9,\n chart: \"linework\",\n hero: \"wash\",\n keywords: /\\b(research|study|abstract|hypothesis|methodology|findings|literature|thesis|theorem|proof|citation|journal|university|experiment)\\b/gi,\n light: tokens(\"#f3ebd6\", \"#e8dec2\", \"#1c1710\", \"#4d4536\", \"#d1c5a3\", \"#7b1e22\", \"#ffffff\"),\n dark: tokens(\"#1c1410\", \"#2a1e18\", \"#f1e8d3\", \"#b7aa8f\", \"#42322a\", \"#f09a94\", \"#240808\"),\n },\n blueprint: {\n id: \"blueprint\",\n name: \"Blueprint\",\n topic: \"technology\",\n description: \"engineering specs, architecture, hardware, proposals\",\n look: \"pale drafting blue, cobalt cover, marker yellow\",\n fonts: \"geometric\",\n formality: 0.8,\n chart: \"flat\",\n hero: \"block\",\n keywords: /\\b(specification|architecture|system|design doc|requirements?|protocol|diagram|engineering|hardware|sensor|circuit|tolerance|proposal|rfc)\\b/gi,\n light: tokens(\"#dee8fb\", \"#f4f8ff\", \"#0a1836\", \"#394a6f\", \"#b7caee\", \"#1140c0\", \"#ffffff\", \"#ffd54a\", \"#0a1836\"),\n dark: tokens(\"#0a1d4d\", \"#122a68\", \"#e6eeff\", \"#aabce3\", \"#24408c\", \"#8fb4ff\", \"#05102a\", \"#ffd54a\", \"#0a1d4d\"),\n },\n midnight: {\n id: \"midnight\",\n name: \"Midnight\",\n topic: \"culture\",\n description: \"night-time, space, astronomy, science fiction, games, nightlife\",\n look: \"periwinkle, deep indigo cover, electric cyan, magenta\",\n fonts: \"geometric\",\n formality: 0.4,\n chart: \"instrument\",\n hero: \"ink\",\n keywords: /\\b(space|galaxy|stars?|orbit|planet|astronom\\w+|game|gaming|cyber\\w*|future|sci-?fi|night|dark|dusk|cinematic|neon|milky way)\\b/gi,\n light: tokens(\"#e3e3fa\", \"#f5f5ff\", \"#100f2e\", \"#464572\", \"#c1c0ed\", \"#3a2bd0\", \"#ffffff\", \"#ff5ad6\", \"#100f2e\"),\n dark: tokens(\"#060620\", \"#101038\", \"#ecebff\", \"#a3a2d4\", \"#25256a\", \"#5ee6ff\", \"#03141a\", \"#ff5ad6\", \"#060620\"),\n },\n rose: {\n id: \"rose\",\n name: \"Rose\",\n topic: \"lifestyle\",\n description: \"weddings, beauty, skincare, fashion, celebrations\",\n look: \"blush pink page, deep rose\",\n fonts: \"luxe\",\n formality: 0.3,\n chart: \"soft\",\n hero: \"wash\",\n keywords: /\\b(wedding|bride|beauty|fashion|skincare|romance|love|invitation|bouquet|engagement|anniversary|bridal)\\b/gi,\n light: tokens(\"#fbdfe3\", \"#fff4f5\", \"#2b1218\", \"#673e4e\", \"#eebcc5\", \"#a8234f\", \"#ffffff\"),\n dark: tokens(\"#2a0f1a\", \"#3b1826\", \"#fdeaee\", \"#d1a3b1\", \"#55263a\", \"#ff9bb8\", \"#2a0a14\"),\n },\n sand: {\n id: \"sand\",\n name: \"Sand\",\n topic: \"lifestyle\",\n description: \"interiors, craft, slow living, quiet luxury\",\n look: \"stone beige, muted olive\",\n fonts: \"luxe\",\n formality: 0.7,\n chart: \"flat\",\n hero: \"wash\",\n keywords: /\\b(interior|furniture|ceramics?|craft|atelier|linen|slow living|minimalis[mt]|gallery|curated|artisan)\\b/gi,\n light: tokens(\"#e9e0cf\", \"#f6f1e6\", \"#25211a\", \"#4c4639\", \"#cdc1a8\", \"#525f27\", \"#ffffff\"),\n dark: tokens(\"#201d14\", \"#2d291d\", \"#f0e9d9\", \"#beb59c\", \"#433d2c\", \"#c3d184\", \"#171a08\"),\n },\n citrus: {\n id: \"citrus\",\n name: \"Citrus\",\n topic: \"culture\",\n description: \"children, schools, community events, playful guides\",\n look: \"sunny yellow page, bold orange cover\",\n fonts: \"rounded\",\n formality: 0.05,\n chart: \"instrument\",\n hero: \"block\",\n keywords: /\\b(kids?|children|school|classroom|play|fun|games?|party|club|camp|volunteers?|community|activities|learn\\w*)\\b/gi,\n light: tokens(\"#ffe98a\", \"#fff8d6\", \"#1f1900\", \"#564c14\", \"#efcf4c\", \"#9e3400\", \"#ffffff\"),\n dark: tokens(\"#1f1a02\", \"#302805\", \"#fff8d0\", \"#c7bb7c\", \"#4a3f0c\", \"#ffd23f\", \"#1c1600\"),\n },\n crimson: {\n id: \"crimson\",\n name: \"Crimson\",\n topic: \"official\",\n description: \"news, journalism, press releases, politics\",\n look: \"newsprint white, red masthead\",\n fonts: \"gazette\",\n formality: 0.85,\n chart: \"flat\",\n hero: \"block\",\n keywords: /\\b(news|report(ed|er|ing)?|press release|journalis\\w+|election|government|minister|breaking|investigation|headline|spokesperson|announced)\\b/gi,\n light: tokens(\"#ffffff\", \"#f4eded\", \"#110808\", \"#5a4c4c\", \"#dbcaca\", \"#ad0f1b\", \"#ffffff\"),\n dark: tokens(\"#120909\", \"#211313\", \"#f8efef\", \"#b9a6a6\", \"#3a2626\", \"#ff6b73\", \"#170204\"),\n },\n slate: {\n id: \"slate\",\n name: \"Slate\",\n topic: \"official\",\n description: \"operations manuals, industrial reports, safety procedures\",\n look: \"steel grey, safety orange cover, hazard yellow\",\n fonts: \"slab\",\n formality: 0.75,\n chart: \"flat\",\n hero: \"block\",\n keywords: /\\b(manual|procedure|maintenance|safety|inspection|operations?|runbook|checklist|equipment|construction|logistics|warehouse|incident)\\b/gi,\n light: tokens(\"#dfe4e8\", \"#f2f5f7\", \"#121b21\", \"#3c4a53\", \"#bac6cd\", \"#9a3a07\", \"#ffffff\", \"#ffd400\", \"#121b21\"),\n dark: tokens(\"#12181c\", \"#1d262c\", \"#e5ecf0\", \"#a4b2bb\", \"#313e47\", \"#ff9248\", \"#1e0d02\", \"#ffd400\", \"#12181c\"),\n },\n lagoon: {\n id: \"lagoon\",\n name: \"Lagoon\",\n topic: \"wellbeing\",\n description: \"healthcare, medicine, patient information, fitness, wellbeing\",\n look: \"aqua page, calm teal, coral\",\n fonts: \"modern\",\n formality: 0.45,\n chart: \"instrument\",\n hero: \"wash\",\n keywords: /\\b(health\\w*|medical|patients?|clinic\\w*|treatment|symptoms?|doctor|nurse|therapy|wellness|wellbeing|diagnos\\w+|care|vaccine)\\b/gi,\n light: tokens(\"#d6f0f1\", \"#f3fbfb\", \"#08242a\", \"#305258\", \"#acd9dc\", \"#086673\", \"#ffffff\", \"#ff7a66\", \"#08242a\"),\n dark: tokens(\"#062a31\", \"#0c3a43\", \"#e2f6f7\", \"#a4cbd0\", \"#18525b\", \"#5fdbe6\", \"#031a1d\", \"#ff8a78\", \"#062a31\"),\n },\n plum: {\n id: \"plum\",\n name: \"Plum\",\n topic: \"culture\",\n description: \"arts, music, theatre, film, exhibitions\",\n look: \"orchid mauve page, deep plum cover, gold\",\n fonts: \"elegant\",\n formality: 0.5,\n chart: \"soft\",\n hero: \"block\",\n keywords: /\\b(art|artist|music|concert|theatre|theater|film|exhibition|gallery|opera|dance|festival|programme|culture|orchestra)\\b/gi,\n light: tokens(\"#f0dcee\", \"#fbf3fa\", \"#24101f\", \"#5b3e55\", \"#dbbdd6\", \"#7a1f6b\", \"#ffffff\", \"#e2b23a\", \"#24101f\"),\n dark: tokens(\"#221023\", \"#331a35\", \"#f7e9f3\", \"#c6a6bf\", \"#4d2b4e\", \"#f3addc\", \"#2a0a22\", \"#e2b23a\", \"#221023\"),\n },\n poster: {\n id: \"poster\",\n name: \"Poster\",\n topic: \"culture\",\n description: \"sports, tournaments, events, bold announcements, manifestos\",\n look: \"stark black and white, electric blue block, neon yellow\",\n fonts: \"poster\",\n formality: 1,\n chart: \"flat\",\n hero: \"block\",\n keywords: /\\b(event|tickets?|match|league|team|championship|tournament|race|drop|lineup|kick-?off|season|score|win)\\b/gi,\n light: tokens(\"#ffffff\", \"#efefef\", \"#000000\", \"#4d4d4d\", \"#111111\", \"#1a3cff\", \"#ffffff\", \"#e8ff3a\", \"#000000\"),\n dark: tokens(\"#000000\", \"#151515\", \"#ffffff\", \"#b0b0b0\", \"#5a5a5a\", \"#e8ff3a\", \"#101400\", \"#1a3cff\", \"#ffffff\"),\n },\n espresso: {\n id: \"espresso\",\n name: \"Espresso\",\n topic: \"lifestyle\",\n description: \"food, recipes, coffee, restaurants, small makers\",\n look: \"latte page, dark roast cover, caramel\",\n fonts: \"slab\",\n formality: 0.5,\n chart: \"flat\",\n hero: \"ink\",\n keywords: /\\b(recipe|food|restaurant|cook\\w*|bak\\w+|coffee|cafe|menu|ingredients?|wine|taste|kitchen|dinner|chef|flavou?r)\\b/gi,\n light: tokens(\"#ecdcc6\", \"#f8efe2\", \"#2a180d\", \"#574031\", \"#d5bea1\", \"#8a4310\", \"#ffffff\"),\n dark: tokens(\"#1f130b\", \"#2e1e13\", \"#f5e8d9\", \"#c1a994\", \"#46311f\", \"#ecab66\", \"#241204\"),\n },\n console: {\n id: \"console\",\n name: \"Console\",\n topic: \"technology\",\n description: \"changelogs, release notes, incident reports, security write-ups, logs\",\n look: \"black screen, phosphor green, amber\",\n fonts: \"mono\",\n formality: 0.95,\n chart: \"linework\",\n hero: \"ink\",\n keywords: /\\b(changelog|release notes|patch|exploit|vulnerabilit\\w+|cve|payload|shell|kernel|stack trace|commit|binary|ctf|debug\\w*)\\b/gi,\n light: tokens(\"#e8f0e1\", \"#f5f9f1\", \"#0c160b\", \"#40543b\", \"#c2d3b6\", \"#17701a\", \"#ffffff\", \"#ffb000\", \"#0c160b\"),\n dark: tokens(\"#030803\", \"#0b150b\", \"#d7f5d0\", \"#88aa82\", \"#1d331d\", \"#5cf25c\", \"#021002\", \"#ffb000\", \"#030803\"),\n },\n}\n\nexport const themeList = Object.values(themes)\n\nexport type FontPairing = {\n id: FontPairingId\n name: string\n /** The headline typeface and its character, in a few words — read by the classifier. */\n look: string\n heading: string\n body: string\n mono: string\n /** Google Fonts `family=` parameters. */\n google: string[]\n headingWeight: number\n /** Heading letter-spacing in em. */\n tracking: number\n}\n\nconst MONO = `\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace`\nconst MONO_GOOGLE = \"JetBrains+Mono:wght@400;600\"\nconst SANS = \"system-ui, sans-serif\"\nconst SERIF = \"Georgia, serif\"\n\nexport const fontPairings: Record<FontPairingId, FontPairing> = {\n editorial: {\n id: \"editorial\",\n name: \"Editorial\",\n look: \"Fraunces, literary serif\",\n heading: `\"Fraunces\", ${SERIF}`,\n body: `\"Newsreader\", ${SERIF}`,\n mono: MONO,\n google: [\"Fraunces:opsz,wght@9..144,400..700\", \"Newsreader:ital,opsz,wght@0,6..72,400..600;1,6..72,400..600\", MONO_GOOGLE],\n headingWeight: 560,\n tracking: -0.02,\n },\n modern: {\n id: \"modern\",\n name: \"Modern\",\n look: \"Inter, neutral sans\",\n heading: `\"Inter Tight\", \"Inter\", ${SANS}`,\n body: `\"Inter\", ${SANS}`,\n mono: MONO,\n google: [\"Inter+Tight:wght@500..800\", \"Inter:wght@400..700\", MONO_GOOGLE],\n headingWeight: 680,\n tracking: -0.03,\n },\n technical: {\n id: \"technical\",\n name: \"Technical\",\n look: \"Space Grotesk, engineered sans\",\n heading: `\"Space Grotesk\", ${SANS}`,\n body: `\"IBM Plex Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Space+Grotesk:wght@400..700\", \"IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.03,\n },\n elegant: {\n id: \"elegant\",\n name: \"Elegant\",\n look: \"Playfair Display, display serif\",\n heading: `\"Playfair Display\", ${SERIF}`,\n body: `\"Source Sans 3\", ${SANS}`,\n mono: MONO,\n google: [\"Playfair+Display:ital,wght@0,400..800;1,400..800\", \"Source+Sans+3:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.015,\n },\n friendly: {\n id: \"friendly\",\n name: \"Friendly\",\n look: \"Bricolage Grotesque, warm sans\",\n heading: `\"Bricolage Grotesque\", ${SANS}`,\n body: `\"DM Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Bricolage+Grotesque:opsz,wght@12..96,400..800\", \"DM+Sans:ital,opsz,wght@0,9..40,400..700;1,9..40,400..700\", MONO_GOOGLE],\n headingWeight: 700,\n tracking: -0.03,\n },\n classic: {\n id: \"classic\",\n name: \"Classic\",\n look: \"Spectral, book serif\",\n heading: `\"Spectral\", ${SERIF}`,\n body: `\"Public Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Spectral:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500\", \"Public+Sans:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.012,\n },\n scholarly: {\n id: \"scholarly\",\n name: \"Scholarly\",\n look: \"EB Garamond, old-style serif\",\n heading: `\"EB Garamond\", ${SERIF}`,\n body: `\"EB Garamond\", ${SERIF}`,\n mono: MONO,\n google: [\"EB+Garamond:ital,wght@0,400..700;1,400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.01,\n },\n geometric: {\n id: \"geometric\",\n name: \"Geometric\",\n look: \"Sora, geometric sans\",\n heading: `\"Sora\", ${SANS}`,\n body: `\"Manrope\", ${SANS}`,\n mono: MONO,\n google: [\"Sora:wght@400..700\", \"Manrope:wght@400..700\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.035,\n },\n luxe: {\n id: \"luxe\",\n name: \"Luxe\",\n look: \"Cormorant Garamond, fashion serif\",\n heading: `\"Cormorant Garamond\", ${SERIF}`,\n body: `\"Jost\", ${SANS}`,\n mono: MONO,\n google: [\"Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500\", \"Jost:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 500,\n tracking: -0.01,\n },\n rounded: {\n id: \"rounded\",\n name: \"Rounded\",\n look: \"Nunito, rounded sans\",\n heading: `\"Nunito\", ${SANS}`,\n body: `\"Nunito Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Nunito:wght@400;600;700;800;900\", \"Nunito+Sans:ital,wght@0,400;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 800,\n tracking: -0.02,\n },\n gazette: {\n id: \"gazette\",\n name: \"Gazette\",\n look: \"DM Serif Display, newspaper serif\",\n heading: `\"DM Serif Display\", ${SERIF}`,\n body: `\"Libre Franklin\", ${SANS}`,\n mono: MONO,\n google: [\"DM+Serif+Display:ital@0;1\", \"Libre+Franklin:ital,wght@0,400;0,500;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 400,\n tracking: -0.01,\n },\n slab: {\n id: \"slab\",\n name: \"Slab\",\n look: \"Zilla Slab, sturdy slab serif\",\n heading: `\"Zilla Slab\", ${SERIF}`,\n body: `\"Work Sans\", ${SANS}`,\n mono: MONO,\n google: [\"Zilla+Slab:ital,wght@0,400;0,500;0,600;0,700;1,400\", \"Work+Sans:ital,wght@0,400;0,500;0,600;1,400\", MONO_GOOGLE],\n headingWeight: 600,\n tracking: -0.015,\n },\n poster: {\n id: \"poster\",\n name: \"Poster\",\n look: \"Archivo Black, heavy headlines\",\n heading: `\"Archivo Black\", \"Archivo\", ${SANS}`,\n body: `\"Archivo\", ${SANS}`,\n mono: MONO,\n google: [\"Archivo+Black\", \"Archivo:ital,wght@0,400;0,500;0,600;0,700;1,400\", MONO_GOOGLE],\n headingWeight: 400,\n tracking: -0.035,\n },\n mono: {\n id: \"mono\",\n name: \"Mono\",\n look: \"JetBrains Mono, monospace\",\n heading: MONO,\n body: `\"IBM Plex Sans\", ${SANS}`,\n mono: MONO,\n google: [\"JetBrains+Mono:wght@400;500;600;700\", \"IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;1,400\"],\n headingWeight: 600,\n tracking: -0.04,\n },\n}\n\nexport const fontPairingList = Object.values(fontPairings)\n\nexport function googleFontsUrl(pairing: FontPairing): string {\n return `https://fonts.googleapis.com/css2?${pairing.google.map((family) => `family=${family}`).join(\"&\")}&display=swap`\n}\n\n/**\n * What the classifier reads when choosing a theme: the subjects it suits, and\n * nothing else. Kept terse on purpose — classifier latency grows with every\n * character here, across every theme.\n */\nexport function describeTheme(theme: Theme): string {\n return theme.description\n}\n\n/** The complete default choice a theme stands for. */\nexport function themeChoice(id: PaletteId): ThemeChoice {\n const theme = themes[id]\n return { palette: id, fonts: theme.fonts, formality: theme.formality }\n}\n\n/**\n * The theme whose vocabulary stands out in the text, or `null` when none does.\n * This is evidence from the words themselves, independent of any classifier.\n */\nexport function matchTheme(text: string, stats: { codeBlocks: number; tables: number }): PaletteId | null {\n const words = Math.max(200, text.split(/\\s+/).length)\n let best: PaletteId | null = null\n let bestScore = 0.6\n for (const theme of themeList) {\n let score = ((text.match(theme.keywords) ?? []).length / words) * 100\n // Code and tables hint at a genre, but only words can confirm it.\n if (theme.id === \"terminal\") score += Math.min(3, stats.codeBlocks * 0.75)\n if (theme.id === \"ocean\" && score > 0) score += Math.min(0.6, stats.tables * 0.15)\n if (score > bestScore) [best, bestScore] = [theme.id, score]\n }\n return best\n}\n\n/**\n * Picks a theme from the words in the document — the fallback when no classifier\n * is configured, and what the loader is drawn in while the classifier decides.\n */\nexport function guessTheme(text: string, stats: { codeBlocks: number; tables: number }): ThemeChoice {\n return themeChoice(matchTheme(text, stats) ?? \"paper\")\n}\n\n/**\n * CSS custom properties for a theme. They use shadcn's token names, so every\n * shadcn component inside the scope picks the theme up without changes.\n */\nexport function themeVars(choice: ThemeChoice, appearance: Appearance): CSSProperties {\n const tokens = themes[choice.palette][appearance]\n const fonts = fontPairings[choice.fonts]\n const radius = 0.25 + (1 - choice.formality) * 0.75\n const soft = `color-mix(in oklab, ${tokens.accent} 12%, ${tokens.bg})`\n const vars: Record<string, string> = {\n \"--background\": tokens.bg,\n \"--foreground\": tokens.fg,\n \"--card\": tokens.surface,\n \"--card-foreground\": tokens.fg,\n \"--popover\": appearance === \"dark\" ? tokens.surface : tokens.bg,\n \"--popover-foreground\": tokens.fg,\n \"--primary\": tokens.accent,\n \"--primary-foreground\": tokens.accentFg,\n \"--secondary\": tokens.surface,\n \"--secondary-foreground\": tokens.fg,\n \"--muted\": tokens.surface,\n \"--muted-foreground\": tokens.muted,\n \"--accent\": soft,\n \"--accent-foreground\": tokens.fg,\n \"--border\": tokens.border,\n \"--input\": tokens.border,\n \"--ring\": tokens.accent,\n \"--radius\": `${radius.toFixed(3)}rem`,\n \"--smd-soft\": soft,\n \"--smd-bg\": tokens.bg,\n \"--smd-fg\": tokens.fg,\n \"--smd-surface\": tokens.surface,\n \"--smd-accent\": tokens.accent,\n \"--smd-accent-fg\": tokens.accentFg,\n ...(tokens.highlight ? { \"--smd-highlight\": tokens.highlight.bg, \"--smd-highlight-fg\": tokens.highlight.fg } : {}),\n // The other mode's accent is the one made to be read on this mode's text colour — which is what an `ink` cover is set on.\n \"--smd-hero-accent\": themes[choice.palette][appearance === \"dark\" ? \"light\" : \"dark\"].accent,\n \"--smd-font-heading\": fonts.heading,\n \"--smd-font-body\": fonts.body,\n \"--smd-font-mono\": fonts.mono,\n \"--smd-heading-weight\": String(fonts.headingWeight),\n \"--smd-tracking\": `${fonts.tracking}em`,\n colorScheme: appearance,\n }\n return vars as CSSProperties\n}\n","\"use client\"\n\nimport { ArrowUpIcon, SquareIcon } from \"lucide-react\"\nimport { useEffect, useMemo, useRef, useState } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport { toText } from \"../analyze/text\"\nimport { parseMarkdown } from \"../parse\"\nimport type { TocEntry } from \"../types\"\nimport { Inline } from \"./flow\"\nimport type { ChatNote, StreamItem } from \"./use-chat\"\n\n/** A remark from the assistant: a paragraph of markdown, shown inline. */\nfunction Remark({ text }: { text: string }) {\n const nodes = useMemo(() => parseMarkdown(text).root.children, [text])\n return (\n <>\n {nodes.map((node, index) =>\n node.type === \"paragraph\" ? (\n <p key={index}>\n <Inline nodes={node.children} />\n </p>\n ) : (\n <p key={index}>{toText(node)}</p>\n ),\n )}\n </>\n )\n}\n\nexport function TocList({\n entries,\n active,\n onNavigate,\n label,\n}: {\n entries: TocEntry[]\n active: string | null\n onNavigate: (id: string) => void\n label?: string\n}) {\n return (\n <ol className=\"smd-toc-list\" aria-label={label}>\n {entries.map((entry) => (\n <li key={entry.id} data-depth={entry.depth}>\n <a\n href={`#${entry.id}`}\n aria-current={entry.id === active ? \"location\" : undefined}\n onClick={(event) => {\n event.preventDefault()\n onNavigate(entry.id)\n }}\n >\n {entry.text}\n </a>\n </li>\n ))}\n </ol>\n )\n}\n\n/**\n * What sits beside the page: the document's contents, then the conversation.\n * The assistant's answers are not repeated here — each is represented by the\n * headings it put on the page, which jump to them.\n */\nexport function SidebarContents({\n document,\n chat,\n items,\n refsOf,\n active,\n busy,\n onNavigate,\n}: {\n document: { toc: TocEntry[]; meta: string } | null\n /** Whether the page takes requests; an empty conversation then says so. */\n chat: boolean\n items: StreamItem[]\n refsOf: (turnId: string) => TocEntry[]\n active: string | null\n busy: boolean\n onNavigate: (id: string) => void\n}) {\n return (\n <>\n {document && document.toc.length > 0 && (\n <>\n <p className=\"smd-sidebar-meta\">{document.meta}</p>\n <TocList entries={document.toc} active={active} onNavigate={onNavigate} label=\"Document\" />\n </>\n )}\n {chat && items.length === 0 && <p className=\"smd-chat-empty\">Chat is still empty</p>}\n {items.length > 0 && (\n <ol className=\"smd-chat\" aria-label=\"Conversation\">\n {items.map((item) => {\n if (item.type === \"user\") {\n return (\n <li key={item.id} className=\"smd-chat-user\">\n <span className=\"sr-only\">You: </span>\n {item.text}\n </li>\n )\n }\n if (item.type === \"commentary\") {\n return (\n <li key={item.id} className=\"smd-chat-remark\" data-failed={item.failed || undefined}>\n <Remark text={item.text} />\n </li>\n )\n }\n const refs = refsOf(item.turnId)\n return refs.length ? (\n <li key={item.id} className=\"smd-chat-refs\">\n <TocList entries={refs} active={active} onNavigate={onNavigate} label=\"Added to the page\" />\n </li>\n ) : null\n })}\n {busy && (\n <li className=\"smd-chat-typing\" aria-label=\"The assistant is writing\">\n <i />\n <i />\n <i />\n </li>\n )}\n </ol>\n )}\n </>\n )\n}\n\n/**\n * The chat input, floating at the bottom of the page, with the assistant's\n * latest remark shown briefly above it.\n */\nexport function ChatDock({\n notes,\n busy,\n quiet = false,\n over = false,\n accessory,\n style,\n onSend,\n onStop,\n}: {\n notes: ChatNote[]\n busy: boolean\n /** The conversation is in view beside the page, so remarks need not be shown here as well. */\n quiet?: boolean\n /** The conversation is open in a sheet over the page; the input floats above that too. */\n over?: boolean\n /** The look of the chat controls, which does not follow the page's theme. */\n style?: React.CSSProperties\n /** A control of the host's own, shown as a round button to the left of the input box. */\n accessory?: React.ReactNode\n onSend: (text: string) => void\n onStop: () => void\n}) {\n const [value, setValue] = useState(\"\")\n const field = useRef<HTMLTextAreaElement>(null)\n\n // Hand the focus back once a reply has finished, ready for the next request.\n const wasBusy = useRef(false)\n useEffect(() => {\n if (wasBusy.current && !busy && window.matchMedia(\"(pointer: fine)\").matches) field.current?.focus({ preventScroll: true })\n wasBusy.current = busy\n }, [busy])\n\n const submit = () => {\n if (busy || !value.trim()) return\n onSend(value)\n setValue(\"\")\n }\n\n return (\n <div className=\"smd-chat-dock\" data-accessory={accessory ? \"\" : undefined} data-over={over || undefined} style={style}>\n {/* Still announced when the conversation is in view; just not shown twice. */}\n <div className=\"smd-chat-notes\" data-quiet={quiet || undefined} aria-live=\"polite\">\n {notes.map((note) => (\n <div key={note.id} className=\"smd-chat-note\">\n <Remark text={note.text} />\n </div>\n ))}\n </div>\n <div className=\"smd-chat-row\">\n {accessory && <div className=\"smd-chat-accessory\">{accessory}</div>}\n <form\n className=\"smd-chat-form\"\n onSubmit={(event) => {\n event.preventDefault()\n submit()\n }}\n >\n {/* The field grows with its text: a hidden copy sets the height. */}\n <div className=\"smd-chat-field\" data-value={value}>\n <textarea\n ref={field}\n rows={1}\n value={value}\n placeholder=\"Ask for something ...\"\n aria-label=\"Message\"\n onChange={(event) => setValue(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault()\n submit()\n }\n }}\n />\n </div>\n {busy ? (\n <Button type=\"button\" size=\"icon\" className=\"size-9 rounded-full\" onClick={onStop} aria-label=\"Stop\" title=\"Stop\">\n <SquareIcon className=\"size-3\" fill=\"currentColor\" />\n </Button>\n ) : (\n <Button type=\"submit\" size=\"icon\" className=\"size-9 rounded-full\" disabled={!value.trim()} aria-label=\"Send\" title=\"Send\">\n <ArrowUpIcon />\n </Button>\n )}\n </form>\n </div>\n </div>\n )\n}\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import type { Image, Nodes, PhrasingContent } from \"mdast\"\n\n/** Plain text of any markdown node. Image alt text is not counted as prose. */\nexport function toText(node: Nodes | Nodes[] | undefined): string {\n if (!node) return \"\"\n if (Array.isArray(node)) return node.map(toText).join(\"\")\n if (node.type === \"text\" || node.type === \"inlineCode\" || node.type === \"code\") return node.value\n if (node.type === \"break\") return \" \"\n if (node.type === \"image\") return \"\"\n if (\"children\" in node) {\n const separator = node.type === \"paragraph\" || node.type === \"heading\" || node.type === \"listItem\" ? \" \" : \"\"\n return (node.children as Nodes[]).map(toText).join(separator)\n }\n return \"\"\n}\n\n/** Running prose only — no headings, code, tables or maths. This is what a reader would call \"the text\". */\nexport function proseOf(node: Nodes): string {\n if (node.type === \"heading\" || node.type === \"code\" || node.type === \"table\" || node.type === \"math\" || node.type === \"yaml\") return \"\"\n if (node.type === \"paragraph\") return toText(node)\n if (\"children\" in node) return (node.children as Nodes[]).map(proseOf).filter(Boolean).join(\" \")\n return \"\"\n}\n\nexport function countWords(text: string): number {\n const trimmed = text.trim()\n return trimmed ? trimmed.split(/\\s+/).length : 0\n}\n\nexport function wordsIn(node: Nodes | Nodes[] | undefined): number {\n if (!node) return 0\n if (Array.isArray(node)) return node.reduce((sum, child) => sum + wordsIn(child), 0)\n if (node.type === \"code\") return 0\n if (\"children\" in node && node.type !== \"paragraph\" && node.type !== \"heading\") {\n return (node.children as Nodes[]).reduce((sum, child) => sum + wordsIn(child), 0)\n }\n return countWords(toText(node))\n}\n\nexport function slugify(text: string, taken: Set<string>): string {\n const base =\n text\n .toLowerCase()\n .normalize(\"NFKD\")\n .replace(/[̀-ͯ]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60) || \"section\"\n let slug = base\n for (let n = 2; taken.has(slug); n++) slug = `${base}-${n}`\n taken.add(slug)\n return slug\n}\n\n/** The images a paragraph consists of, if it holds nothing but images (optionally linked). */\nexport function imagesOnly(children: PhrasingContent[]): { image: Image; href?: string }[] | null {\n const found: { image: Image; href?: string }[] = []\n for (const child of children) {\n if (child.type === \"image\") found.push({ image: child })\n else if (child.type === \"link\" && child.children.length === 1 && child.children[0].type === \"image\") {\n found.push({ image: child.children[0], href: child.url })\n } else if (child.type === \"break\" || (child.type === \"text\" && !child.value.trim())) continue\n else return null\n }\n return found.length ? found : null\n}\n","import type { Image, Paragraph, PhrasingContent, Root, RootContent } from \"mdast\"\nimport remarkFrontmatter from \"remark-frontmatter\"\nimport remarkGfm from \"remark-gfm\"\nimport remarkMath from \"remark-math\"\nimport remarkParse from \"remark-parse\"\nimport { unified } from \"unified\"\nimport { parse as parseYaml } from \"yaml\"\n\nexport type Frontmatter = Record<string, unknown>\n\nexport type ParsedMarkdown = {\n root: Root\n frontmatter: Frontmatter\n}\n\nconst processor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).use(remarkFrontmatter, [\"yaml\"])\n\nconst attr = (tag: string, name: string) =>\n new RegExp(`\\\\b${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, \"i\").exec(tag)?.slice(2).find((v) => v != null)\n\nconst decodeEntities = (text: string) =>\n text\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n\n/**\n * Raw HTML is never injected. The useful parts are recovered as markdown nodes —\n * images, line breaks and text — and everything else is dropped.\n */\nfunction htmlToPhrasing(html: string): PhrasingContent[] {\n const out: PhrasingContent[] = []\n const withoutComments = html.replace(/<!--[\\s\\S]*?-->/g, \"\").replace(/<(script|style)[\\s\\S]*?<\\/\\1>/gi, \"\")\n const tokens = withoutComments.split(/(<[^>]+>)/g)\n let href: string | undefined\n for (const token of tokens) {\n if (!token) continue\n if (token.startsWith(\"<\")) {\n if (/^<img\\b/i.test(token)) {\n const src = attr(token, \"src\")\n if (!src) continue\n const image: Image = { type: \"image\", url: src, alt: attr(token, \"alt\") ?? \"\", title: attr(token, \"title\") ?? null }\n out.push(href ? { type: \"link\", url: href, children: [image] } : image)\n } else if (/^<br\\b/i.test(token)) {\n out.push({ type: \"break\" })\n } else if (/^<a\\b/i.test(token)) {\n href = attr(token, \"href\")\n } else if (/^<\\/a/i.test(token)) {\n href = undefined\n }\n continue\n }\n const text = decodeEntities(token).replace(/\\s+/g, \" \")\n if (!text.trim()) continue\n out.push(href ? { type: \"link\", url: href, children: [{ type: \"text\", value: text }] } : { type: \"text\", value: text })\n }\n return out\n}\n\ntype Definitions = Map<string, { url: string; title?: string | null }>\n\nfunction collectDefinitions(nodes: RootContent[], into: Definitions = new Map()): Definitions {\n for (const node of nodes) {\n if (node.type === \"definition\") into.set(node.identifier, { url: node.url, title: node.title })\n else if (\"children\" in node) collectDefinitions(node.children as RootContent[], into)\n }\n return into\n}\n\nfunction cleanPhrasing(children: PhrasingContent[], defs: Definitions): PhrasingContent[] {\n return children.flatMap((child, index): PhrasingContent[] => {\n // \"$60M and $64M\" is money, not maths: as in Pandoc, the dollars must hug the\n // formula and the closing one must not run into a digit.\n if (child.type === \"inlineMath\") {\n const next = children[index + 1]\n const digitAfter = next?.type === \"text\" && /^\\d/.test(next.value)\n if (/^\\s|\\s$/.test(child.value) || digitAfter) return [{ type: \"text\", value: `$${child.value}$` }]\n }\n if (child.type === \"html\") return htmlToPhrasing(child.value)\n // Reference-style links and images are resolved so renderers only meet the direct forms.\n if (child.type === \"imageReference\") {\n const def = defs.get(child.identifier)\n return def ? [{ type: \"image\", url: def.url, alt: child.alt ?? \"\", title: def.title }] : []\n }\n if (child.type === \"linkReference\") {\n const def = defs.get(child.identifier)\n const inner = cleanPhrasing(child.children, defs)\n return def ? [{ type: \"link\", url: def.url, title: def.title, children: inner } as PhrasingContent] : inner\n }\n if (\"children\" in child) {\n return [{ ...child, children: cleanPhrasing(child.children as PhrasingContent[], defs) } as PhrasingContent]\n }\n return [child]\n })\n}\n\nfunction cleanBlocks(nodes: RootContent[], defs: Definitions): RootContent[] {\n return nodes.flatMap((node): RootContent[] => {\n if (node.type === \"html\") {\n // An HTML heading (`<h1 align=\"center\">`) keeps its role.\n const heading = /^\\s*<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>\\s*$/i.exec(node.value)\n if (heading) {\n const children = htmlToPhrasing(heading[2])\n return children.length ? [{ type: \"heading\", depth: Number(heading[1]) as 1, children }] : []\n }\n const children = htmlToPhrasing(node.value)\n return children.length ? [{ type: \"paragraph\", children } satisfies Paragraph] : []\n }\n if (node.type === \"yaml\" || node.type === \"definition\") return []\n if (node.type === \"paragraph\" || node.type === \"heading\") {\n const children = cleanPhrasing(node.children, defs)\n return children.length ? [{ ...node, children }] : []\n }\n if (node.type === \"tableCell\") return [{ ...node, children: cleanPhrasing(node.children, defs) }]\n if (\"children\" in node) {\n return [{ ...node, children: cleanBlocks(node.children as RootContent[], defs) } as RootContent]\n }\n return [node]\n })\n}\n\nexport function parseMarkdown(markdown: string): ParsedMarkdown {\n const tree = processor.parse(markdown) as Root\n let frontmatter: Frontmatter = {}\n const first = tree.children[0]\n if (first?.type === \"yaml\") {\n try {\n const data = parseYaml(first.value)\n if (data && typeof data === \"object\" && !Array.isArray(data)) frontmatter = data as Frontmatter\n } catch {\n // Malformed frontmatter is ignored rather than failing the whole document.\n }\n }\n return { root: { ...tree, children: cleanBlocks(tree.children, collectDefinitions(tree.children)) }, frontmatter }\n}\n","\"use client\"\n\nimport katex from \"katex\"\nimport type { PhrasingContent, RootContent } from \"mdast\"\nimport { Fragment, type ReactNode } from \"react\"\nimport { CodeBlock } from \"./code-block\"\nimport { useStunning } from \"./context\"\n\nconst SAFE_URL = /^(https?:|mailto:|tel:|#|\\/|\\.{0,2}\\/|blob:|data:image\\/)/i\n\n/** Links and images only ever point at ordinary web, mail or in-page targets. */\nexport function safeUrl(url: string): string | undefined {\n const trimmed = url.trim()\n if (SAFE_URL.test(trimmed) || !/^[a-z][a-z0-9+.-]*:/i.test(trimmed)) return trimmed\n return undefined\n}\n\nexport function MathView({ value, display }: { value: string; display?: boolean }) {\n const html = katex.renderToString(value, { displayMode: display, throwOnError: false, output: \"htmlAndMathml\" })\n return display ? (\n <div className=\"smd-math-block\" dangerouslySetInnerHTML={{ __html: html }} />\n ) : (\n <span dangerouslySetInnerHTML={{ __html: html }} />\n )\n}\n\nexport function Inline({ nodes }: { nodes: PhrasingContent[] }) {\n const { resolveUrl } = useStunning()\n const render = (node: PhrasingContent, key: number): ReactNode => {\n switch (node.type) {\n case \"text\":\n return node.value\n case \"emphasis\":\n return <em key={key}>{node.children.map(render)}</em>\n case \"strong\":\n return <strong key={key}>{node.children.map(render)}</strong>\n case \"delete\":\n return <del key={key}>{node.children.map(render)}</del>\n case \"inlineCode\":\n return <code key={key}>{node.value}</code>\n case \"break\":\n return <br key={key} />\n case \"link\": {\n const href = safeUrl(node.url)\n const external = !!href && /^https?:/i.test(href)\n return (\n <a key={key} href={href} title={node.title ?? undefined} {...(external ? { target: \"_blank\", rel: \"noreferrer noopener\" } : {})}>\n {node.children.map(render)}\n </a>\n )\n }\n case \"image\": {\n const src = safeUrl(resolveUrl(node.url))\n // eslint-disable-next-line @next/next/no-img-element\n return src ? <img key={key} src={src} alt={node.alt ?? \"\"} title={node.title ?? undefined} loading=\"lazy\" className=\"smd-inline-image\" /> : null\n }\n case \"inlineMath\":\n return <MathView key={key} value={node.value} />\n case \"footnoteReference\":\n return (\n <sup key={key}>\n <a href={`#fn-${node.identifier}`} id={`fnref-${node.identifier}`} aria-label={`Footnote ${node.label ?? node.identifier}`}>\n {node.label ?? node.identifier}\n </a>\n </sup>\n )\n default:\n return null\n }\n }\n return <>{nodes.map(render)}</>\n}\n\n/** Renders ordinary markdown block nodes — the content inside list items, quotes and cards. */\nexport function Flow({ nodes }: { nodes: RootContent[] }) {\n return (\n <>\n {nodes.map((node, index) => (\n <FlowNode key={index} node={node} />\n ))}\n </>\n )\n}\n\nexport function FlowNode({ node }: { node: RootContent }) {\n switch (node.type) {\n case \"paragraph\":\n return (\n <p>\n <Inline nodes={node.children} />\n </p>\n )\n case \"heading\": {\n const Tag = `h${Math.min(6, node.depth + 1)}` as \"h3\"\n return (\n <Tag className=\"smd-subheading\">\n <Inline nodes={node.children} />\n </Tag>\n )\n }\n case \"list\": {\n const Tag = node.ordered ? \"ol\" : \"ul\"\n const task = node.children.some((item) => item.checked != null)\n return (\n <Tag start={node.ordered ? (node.start ?? undefined) : undefined} className={task ? \"smd-tasks\" : undefined}>\n {node.children.map((item, index) => (\n <li key={index} data-checked={item.checked ?? undefined}>\n {item.checked != null && (\n <input type=\"checkbox\" checked={item.checked} readOnly disabled aria-label={item.checked ? \"Done\" : \"Not done\"} />\n )}\n <ItemBody nodes={item.children} />\n </li>\n ))}\n </Tag>\n )\n }\n case \"blockquote\":\n return (\n <blockquote>\n <Flow nodes={node.children} />\n </blockquote>\n )\n case \"code\":\n return <CodeBlock lang={node.lang ?? undefined} value={node.value} />\n case \"math\":\n return <MathView value={node.value} display />\n case \"thematicBreak\":\n return <hr />\n case \"footnoteDefinition\":\n return (\n <div className=\"smd-footnote\" id={`fn-${node.identifier}`}>\n <a href={`#fnref-${node.identifier}`} aria-label=\"Back to reference\">\n {node.label ?? node.identifier}\n </a>\n <div>\n <Flow nodes={node.children} />\n </div>\n </div>\n )\n case \"table\":\n return (\n <div className=\"smd-table-scroll\">\n <table>\n <tbody>\n {node.children.map((row, r) => (\n <tr key={r}>\n {row.children.map((cell, c) => {\n const Cell = r === 0 ? \"th\" : \"td\"\n return (\n <Cell key={c}>\n <Inline nodes={cell.children} />\n </Cell>\n )\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n default:\n return null\n }\n}\n\n/** A list item whose only content is one paragraph renders tight, without the paragraph wrapper. */\nexport function ItemBody({ nodes }: { nodes: RootContent[] }) {\n return (\n <>\n {nodes.map((node, index) =>\n node.type === \"paragraph\" ? (\n <Fragment key={index}>\n {index > 0 && <span className=\"smd-item-gap\" />}\n <Inline nodes={node.children} />\n </Fragment>\n ) : (\n <FlowNode key={index} node={node} />\n ),\n )}\n </>\n )\n}\n","\"use client\"\n\nimport type { Element, ElementContent, Root, RootContent } from \"hast\"\nimport { common, createLowlight } from \"lowlight\"\nimport { CheckIcon, CopyIcon } from \"lucide-react\"\nimport { useMemo, useState, type ReactNode } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport { cn } from \"@/lib/utils\"\n\nconst lowlight = createLowlight(common)\n\nconst ALIASES: Record<string, string> = { sh: \"bash\", shell: \"bash\", zsh: \"bash\", console: \"bash\", yml: \"yaml\", tsx: \"typescript\", jsx: \"javascript\", html: \"xml\", svg: \"xml\", vue: \"xml\" }\n\nfunction toReact(node: RootContent | ElementContent, key: number): ReactNode {\n if (node.type === \"text\") return node.value\n if (node.type !== \"element\") return null\n const element = node as Element\n const className = element.properties?.className\n return (\n <span key={key} className={Array.isArray(className) ? className.join(\" \") : undefined}>\n {element.children.map(toReact)}\n </span>\n )\n}\n\nexport function CopyButton({ text, label, className }: { text: string | (() => string); label: string; className?: string }) {\n const [copied, setCopied] = useState(false)\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(typeof text === \"function\" ? text() : text)\n setCopied(true)\n setTimeout(() => setCopied(false), 1600)\n } catch {\n // Clipboard access can be refused; the content stays selectable.\n }\n }\n return (\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={copy} aria-label={copied ? \"Copied\" : label} title={label} className={cn(\"text-muted-foreground\", className)}>\n {copied ? <CheckIcon /> : <CopyIcon />}\n <span className=\"sr-only\" role=\"status\">\n {copied ? \"Copied\" : \"\"}\n </span>\n </Button>\n )\n}\n\nexport function CodeBlock({ lang, value }: { lang?: string; value: string }) {\n const language = lang ? (ALIASES[lang.toLowerCase()] ?? lang.toLowerCase()) : undefined\n const tree = useMemo<Root | null>(() => {\n if (!language || !lowlight.registered(language)) return null\n try {\n return lowlight.highlight(language, value)\n } catch {\n return null\n }\n }, [language, value])\n\n return (\n <figure className=\"smd-code not-prose\">\n <figcaption>\n <span>{lang ?? \"text\"}</span>\n <CopyButton text={value} label=\"Copy code\" />\n </figcaption>\n <pre tabIndex={0}>\n <code className=\"hljs\">{tree ? tree.children.map(toReact) : value}</code>\n </pre>\n </figure>\n )\n}\n","\"use client\"\n\nimport { createContext, useContext, type CSSProperties } from \"react\"\nimport type { ChartTheme } from \"generative-charts\"\nimport type { Appearance, SectionLayout, ThemeChoice, VizKind } from \"../types\"\n\nexport type StunningContext = {\n /** Maps a URL from the markdown to one the browser can load. */\n resolveUrl: (url: string) => string\n appearance: Appearance\n theme: ThemeChoice\n chartTheme: ChartTheme\n /**\n * Popovers, menus and sheets render outside the themed root, so they are\n * handed the theme directly.\n */\n portal: { className: string; style: CSSProperties }\n /** Whether layout and form pickers are shown. */\n controls: boolean\n setLayout: (sectionId: string, layout: SectionLayout) => void\n setViz: (blockId: string, kind: VizKind) => void\n}\n\nconst Context = createContext<StunningContext | null>(null)\n\nexport const StunningProvider = Context.Provider\n\nexport function useStunning(): StunningContext {\n const value = useContext(Context)\n if (!value) throw new Error(\"stunning-md components must be rendered inside <StunningMarkdown>\")\n return value\n}\n","\"use client\"\n\nimport { CheckIcon, CodeIcon, FileTextIcon, MenuIcon, MoonIcon, PaletteIcon, PanelRightCloseIcon, PanelRightOpenIcon, SparklesIcon, SunIcon } from \"lucide-react\"\nimport { useEffect, useRef, useState } from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from \"@/components/ui/sheet\"\nimport { cn } from \"@/lib/utils\"\nimport { themeList, themeTopics } from \"../theme/themes\"\nimport type { Appearance, PaletteId } from \"../types\"\nimport { useStunning } from \"./context\"\n\nexport function scrollToId(id: string) {\n const target = document.getElementById(id)\n if (!target) return\n const reduce = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n target.scrollIntoView({ behavior: reduce ? \"auto\" : \"smooth\", block: \"start\" })\n // Move focus with the viewport so keyboard and screen-reader users land there too.\n target.setAttribute(\"tabindex\", \"-1\")\n target.setAttribute(\"data-jump\", \"\")\n target.focus({ preventScroll: true })\n history.replaceState(null, \"\", `#${id}`)\n}\n\n/** Tracks which section is being read and how far through the document the reader is. */\nexport function useReadingPosition(ids: string[], root: React.RefObject<HTMLElement | null>) {\n const [active, setActive] = useState<string | null>(null)\n const bar = useRef<HTMLDivElement>(null)\n const key = ids.join(\"|\")\n\n useEffect(() => {\n let frame = 0\n const update = () => {\n frame = 0\n const el = root.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n const span = rect.height - window.innerHeight\n const progress = span > 0 ? Math.min(1, Math.max(0, -rect.top / span)) : 0\n if (bar.current) bar.current.style.transform = `scaleX(${progress})`\n let current: string | null = null\n for (const id of key.split(\"|\")) {\n const node = id && document.getElementById(id)\n if (node && node.getBoundingClientRect().top <= window.innerHeight * 0.3) current = id\n }\n setActive(current)\n }\n const onScroll = () => {\n if (!frame) frame = requestAnimationFrame(update)\n }\n update()\n window.addEventListener(\"scroll\", onScroll, { passive: true })\n window.addEventListener(\"resize\", onScroll)\n // Content that arrives or reflows moves the sections without any scrolling.\n const resized = new ResizeObserver(onScroll)\n if (root.current) resized.observe(root.current)\n return () => {\n cancelAnimationFrame(frame)\n resized.disconnect()\n window.removeEventListener(\"scroll\", onScroll)\n window.removeEventListener(\"resize\", onScroll)\n }\n }, [key, root])\n\n return { active, bar }\n}\n\nexport type ReadingPosition = ReturnType<typeof useReadingPosition>\n\n/** How the contents are offered: beside the page when there is room, otherwise in a sheet. */\nexport type SidebarState = { available: boolean; open: boolean; toggle: () => void; id: string }\n\n/** The contents and conversation, pinned beside the page on wide screens. */\nexport function Sidebar({\n id,\n title,\n showTitle = true,\n active,\n tail,\n style,\n hidden = false,\n children,\n}: {\n id: string\n /** Names the sidebar for assistive technology. */\n title: string\n /** Whether the name is also shown as a heading. */\n showTitle?: boolean\n active: string | null\n /** Changes whenever the conversation gains something; empty while there is none. */\n tail: string\n /** A look of its own, when the sidebar should not follow the page's theme. */\n style?: React.CSSProperties\n /** Shut: still in the page, so it can slide open, but out of reach. */\n hidden?: boolean\n children: React.ReactNode\n}) {\n const scroller = useRef<HTMLElement>(null)\n\n // Keep the current entry in view as the reader moves through a long document.\n useEffect(() => {\n const box = scroller.current\n const current = box?.querySelector<HTMLElement>(\"[aria-current]\")\n if (!box || !current) return\n const top = current.getBoundingClientRect().top - box.getBoundingClientRect().top + box.scrollTop\n if (top < box.scrollTop + 48) box.scrollTop = Math.max(0, top - 48)\n else if (top + current.offsetHeight > box.scrollTop + box.clientHeight - 48) box.scrollTop = top + current.offsetHeight - box.clientHeight + 48\n }, [active])\n\n // Follow the conversation as it grows, to the end of each turn.\n useEffect(() => {\n const box = scroller.current\n if (box && tail) box.scrollTop = box.scrollHeight\n }, [tail])\n\n return (\n <nav ref={scroller} id={id} className=\"smd-sidebar\" aria-label={title} style={style} inert={hidden} aria-hidden={hidden || undefined}>\n {showTitle && <p className=\"smd-sidebar-title\">{title}</p>}\n {children}\n </nav>\n )\n}\n\n/** The same contents in the sheet used on narrow screens; it follows the conversation too. */\nfunction SheetBody({ tail, children }: { tail: string; children: React.ReactNode }) {\n const scroller = useRef<HTMLDivElement>(null)\n useEffect(() => {\n const box = scroller.current\n if (box && tail) box.scrollTop = box.scrollHeight\n }, [tail])\n return (\n <div ref={scroller} className=\"smd-toc-body\">\n {children}\n </div>\n )\n}\n\n/** How the document is shown: its raw text, an ordinary rendering, or the designed page. */\nexport type View = \"source\" | \"plain\" | \"designed\"\n\nconst VIEWS: { id: View; label: string; icon: typeof CodeIcon }[] = [\n { id: \"source\", label: \"Markdown text\", icon: CodeIcon },\n { id: \"plain\", label: \"Plain rendering\", icon: FileTextIcon },\n { id: \"designed\", label: \"Stunning\", icon: SparklesIcon },\n]\n\n/** A three-position switch between the views, with a thumb that slides to the chosen one. */\nfunction ViewSwitch({ view, onView }: { view: View; onView: (view: View) => void }) {\n const group = useRef<HTMLDivElement>(null)\n const index = VIEWS.findIndex((item) => item.id === view)\n const move = (step: number) => {\n const next = Math.min(VIEWS.length - 1, Math.max(0, index + step))\n onView(VIEWS[next].id)\n group.current?.querySelectorAll(\"button\")[next]?.focus()\n }\n return (\n <div ref={group} role=\"radiogroup\" aria-label=\"View\" className=\"smd-view-switch\" style={{ \"--smd-view-index\": index } as React.CSSProperties}>\n <span className=\"smd-view-thumb\" aria-hidden />\n {VIEWS.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n role=\"radio\"\n aria-checked={item.id === view}\n aria-label={item.label}\n title={item.label}\n tabIndex={item.id === view ? 0 : -1}\n onClick={() => onView(item.id)}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") move(1)\n else if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") move(-1)\n else return\n event.preventDefault()\n }}\n >\n <item.icon aria-hidden />\n </button>\n ))}\n </div>\n )\n}\n\nexport function Nav({\n title,\n titleTarget,\n crumb,\n contents,\n root,\n bar,\n sidebar,\n menu,\n view,\n onView,\n onPalette,\n autoTheme,\n onAutoTheme,\n onAppearance,\n}: {\n /** The title of what is being read, if it has one. */\n title: string\n /** The element the title leads back to; the top of the page if not given. */\n titleTarget?: string\n /** The section being read. */\n crumb: string | null\n /** What the contents menu holds on narrow screens, or `null` if there is nothing to list. */\n contents: {\n label: string\n description: string\n /** Whether the panel shows its name as a heading. */\n showTitle?: boolean\n /** A look of its own for the panel, when it should not follow the page's theme. */\n style?: React.CSSProperties\n /**\n * The chat input floats above the panel and stays in use while it is open:\n * the panel leaves room for it, and the rest of the page is not shut off.\n */\n docked?: boolean\n /** Changes whenever the conversation gains something, so the panel can keep its end in view. */\n tail?: string\n render: (navigate: (id: string) => void) => React.ReactNode\n } | null\n root: React.RefObject<HTMLElement | null>\n bar: React.RefObject<HTMLDivElement | null>\n sidebar: SidebarState\n /** Whether the contents sheet is open, on screens too narrow for the sidebar. */\n menu: { open: boolean; onOpenChange: (open: boolean) => void }\n view: View\n onView: (view: View) => void\n onPalette: (palette: PaletteId) => void\n /** Whether themes are chosen to suit the content, and the reader's switch for it. */\n autoTheme: boolean\n onAutoTheme: (auto: boolean) => void\n onAppearance: (appearance: Appearance) => void\n}) {\n const { portal, theme, appearance, controls } = useStunning()\n\n if (!contents && !controls) return null\n\n return (\n <nav className=\"smd-nav\" aria-label=\"Document\">\n {/* The title and the controls keep to the ends of the bar, whatever the width of the page beneath. */}\n <div className=\"smd-nav-row flex h-12 items-center gap-2\">\n {title && (\n <a\n href={`#${titleTarget ?? \"top\"}`}\n onClick={(event) => {\n event.preventDefault()\n if (titleTarget) scrollToId(titleTarget)\n else window.scrollTo({ top: (root.current?.getBoundingClientRect().top ?? 0) + window.scrollY, behavior: \"smooth\" })\n }}\n className=\"smd-nav-title min-w-0 truncate\"\n >\n {title}\n </a>\n )}\n {crumb && (\n <span className={cn(\"min-w-0 truncate text-sm text-muted-foreground\", title && \"hidden sm:inline\")} aria-hidden>\n {title && <span className=\"mx-1.5 opacity-50\">/</span>}\n {crumb}\n </span>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-0.5\">\n {controls && <ViewSwitch view={view} onView={onView} />}\n {controls && (\n <DropdownMenu>\n <DropdownMenuTrigger render={<Button variant=\"ghost\" size=\"icon\" aria-label=\"Choose theme\" title=\"Theme\" />}>\n <PaletteIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"max-h-[min(34rem,var(--available-height))] w-56 overflow-y-auto\")}>\n <DropdownMenuGroup>\n <DropdownMenuCheckboxItem checked={autoTheme} onCheckedChange={(checked) => onAutoTheme(checked)} title=\"Choose a theme to suit each document and answer\">\n Match the content\n </DropdownMenuCheckboxItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n {/* Arranged by subject, so a theme is found by what the document is about. */}\n {themeTopics.map((topic) => (\n <DropdownMenuGroup key={topic.id}>\n <DropdownMenuLabel>{topic.name}</DropdownMenuLabel>\n {themeList\n .filter((item) => item.topic === topic.id)\n .map((item) => (\n <DropdownMenuItem key={item.id} onClick={() => onPalette(item.id)}>\n <span\n aria-hidden\n className=\"size-4 shrink-0 rounded-full ring-1 ring-foreground/15\"\n style={{ background: `linear-gradient(135deg, ${item[appearance].bg} 50%, ${item[appearance].accent} 50%)` }}\n />\n {item.name}\n {item.id === theme.palette && <CheckIcon className=\"ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => onAppearance(appearance === \"dark\" ? \"light\" : \"dark\")}\n aria-label={appearance === \"dark\" ? \"Switch to light mode\" : \"Switch to dark mode\"}\n title={appearance === \"dark\" ? \"Light mode\" : \"Dark mode\"}\n >\n {appearance === \"dark\" ? <SunIcon /> : <MoonIcon />}\n </Button>\n {sidebar.available && contents && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 gap-1.5 px-2.5\"\n onClick={sidebar.toggle}\n aria-expanded={sidebar.open}\n aria-controls={sidebar.id}\n aria-label={sidebar.open ? `Hide ${contents.label.toLowerCase()}` : `Show ${contents.label.toLowerCase()}`}\n >\n {sidebar.open ? <PanelRightCloseIcon /> : <PanelRightOpenIcon />}\n <span>{contents.label}</span>\n </Button>\n )}\n {contents && !sidebar.available && (\n <Sheet\n open={menu.open}\n modal={!contents.docked}\n onOpenChange={(next, details) => {\n // Using the chat input, which floats above the panel, is not a reason to close it.\n if (!next && contents.docked && (details.reason === \"outside-press\" || details.reason === \"focus-out\")) {\n const event = details.event as Event & { relatedTarget?: EventTarget | null }\n const inDock = (node: EventTarget | null | undefined) => node instanceof Element && !!node.closest(\".smd-chat-dock\")\n if (inDock(event.target) || inDock(event.relatedTarget)) {\n details.cancel()\n return\n }\n }\n menu.onOpenChange(next)\n }}\n >\n {/* On a phone the button is the icon alone: pulled out so the icon, not its padding, meets the page margin. */}\n <SheetTrigger render={<Button variant=\"ghost\" size=\"sm\" className=\"h-8 gap-1.5 px-2.5 max-sm:-mr-2.5\" aria-label={`Open ${contents.label.toLowerCase()}`} />}>\n <MenuIcon />\n <span className=\"hidden sm:inline\">{contents.label}</span>\n </SheetTrigger>\n <SheetContent\n style={contents.style ?? portal.style}\n className={cn(portal.className, \"smd-toc gap-0\")}\n data-headless={(contents.showTitle === false && !contents.description) || undefined}\n data-docked={contents.docked || undefined}\n >\n <SheetHeader className={contents.showTitle === false && !contents.description ? \"sr-only\" : undefined}>\n <SheetTitle className={contents.showTitle === false ? \"sr-only\" : undefined}>{contents.label}</SheetTitle>\n <SheetDescription className={contents.description ? undefined : \"sr-only\"}>\n {contents.description || \"Jump to a part of the page.\"}\n </SheetDescription>\n </SheetHeader>\n <SheetBody tail={contents.tail ?? \"\"}>\n {contents.render((id) => {\n menu.onOpenChange(false)\n // Wait for the sheet to release its scroll lock.\n setTimeout(() => scrollToId(id), 60)\n })}\n </SheetBody>\n </SheetContent>\n </Sheet>\n )}\n </div>\n </div>\n <div className=\"smd-progress\" aria-hidden>\n <div ref={bar} />\n </div>\n </nav>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { cn } from \"@/lib/utils\"\nimport { ChevronRightIcon, CheckIcon } from \"lucide-react\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\"z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\"w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\", className )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n inset,\n ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n inset,\n ...props\n}: MenuPrimitive.RadioItem.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n data-inset={inset}\n className={cn(\n \"relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon\n />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\nimport { cn } from \"@/lib/utils\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/10 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\n \"fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-3 right-3\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-0.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\n \"font-heading text-base font-medium text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { probeImages } from \"../analyze/images\"\nimport { collectImageUrls, planDocument, type ImageMetaMap } from \"../analyze/plan\"\nimport { proseOf, toText } from \"../analyze/text\"\nimport { judgeDocument, type Classify } from \"../classifier\"\nimport { parseMarkdown } from \"../parse\"\nimport { chartThemeFor } from \"../theme/chart\"\nimport { fontPairings, googleFontsUrl, matchTheme, themeChoice, themes, themeVars } from \"../theme/themes\"\nimport type { Appearance, DocumentPlan, Judgements, PaletteId, SectionLayout, ThemeChoice, VizKind } from \"../types\"\nimport { StunningProvider, type StunningContext } from \"./context\"\nimport { HeroView } from \"./hero\"\nimport type { View } from \"./nav\"\nimport { PlainDocument, SourceView } from \"./plain\"\nimport { SectionView } from \"./section\"\n\n/** What a turn tells the page about itself: its layout plan and the theme it settled on — `null` until it has. */\nexport type TurnReport = { plan: DocumentPlan; theme: ThemeChoice | null }\n\nexport type TurnViewProps = {\n /** Identifies the turn; its element is `#<id>-turn`. */\n id: string\n /** Put in front of the turn's section ids, so turns sharing a page cannot collide. */\n prefix: string\n markdown: string\n /** More of this turn is still being written. */\n streaming?: boolean\n /** Nothing has come back from the model yet. */\n waiting?: boolean\n /**\n * Not known to be writing anything for the page — the reply may be conversation\n * alone. The request is still shown while `waiting`, then the spinner alone.\n */\n idle?: boolean\n /** What was asked, shown as a chat bubble while `waiting`. */\n asked?: string\n /** The section being written, shown while `streaming`. */\n writing?: string | null\n /** Choose the theme once, from the first content, and keep it as the turn grows. */\n lockTheme?: boolean\n /** What the turn was written in answer to; it helps the classifier place its subject. */\n themeContext?: string\n /**\n * The text to choose the theme from, when that is not simply the turn's first\n * content — `null` for as long as there is too little of it to choose by.\n */\n opening?: string | null\n /** The look the turn wears until it has chosen its own. */\n pendingStyle?: React.CSSProperties\n /** Take up at least a full window, so the turn can be scrolled to the top before it has much in it. */\n fill?: boolean\n /** Report when the top of the turn has stopped moving, so a page loader can lift. */\n onReady?: () => void\n classifier?: Classify\n fixedTheme?: Partial<ThemeChoice>\n /** A theme chosen by hand for this turn. */\n palettePick?: PaletteId | null\n /**\n * Choose the theme from the content. When off, nothing is asked or guessed:\n * the turn wears `palettePick`.\n */\n autoTheme?: boolean\n appearance: Appearance\n resolveUrl: (url: string) => string\n controls: boolean\n editable?: boolean\n loadFonts: boolean\n settleMs: number\n maxWaitMs: number\n view: View\n onReport: (id: string, report: TurnReport) => void\n onMarkdownChange?: (markdown: string) => void\n}\n\n/**\n * Loads the theme's typefaces and reports when text set in them has stopped\n * reflowing. Resolves on its own after `capMs`, so a slow font host never holds the page.\n */\nexport function useFonts(href: string, enabled: boolean, capMs = 1800): boolean {\n const [loaded, setLoaded] = useState<string | null>(null)\n useEffect(() => {\n if (!enabled) return\n let live = true\n const done = () => live && setLoaded(href)\n // Fonts are only requested once styled text has been laid out, so give layout two frames first.\n const settle = () => requestAnimationFrame(() => requestAnimationFrame(() => document.fonts.ready.then(done, done)))\n const cap = setTimeout(done, capMs)\n\n let link = document.head.querySelector<HTMLLinkElement>(`link[data-smd-fonts=\"${href}\"]`)\n if (link?.dataset.smdLoaded) settle()\n else {\n if (!link) {\n link = document.createElement(\"link\")\n link.rel = \"stylesheet\"\n link.href = href\n link.dataset.smdFonts = href\n document.head.appendChild(link)\n }\n const target = link\n const onLoad = () => {\n target.dataset.smdLoaded = \"true\"\n settle()\n }\n target.addEventListener(\"load\", onLoad, { once: true })\n target.addEventListener(\"error\", done, { once: true })\n }\n return () => {\n live = false\n clearTimeout(cap)\n }\n }, [href, enabled, capMs])\n return !enabled || loaded === href\n}\n\nconst NONE: string[] = []\n\n/** Longest a chat answer waits for the classifier's choice of theme before going ahead, in ms. */\nconst THEME_PATIENCE = 5000\n\n/** The score at which the classifier's theme is accepted for an opening that gives no hint of its own. */\nconst SEED_CONFIDENCE = 0.22\n\n/** How long the request shown in place of an answer takes to fade once the answer starts, in ms. */\nconst ASKED_FADE = 450\n\n/** How far down the page counts as \"the first sections\", in viewport heights. */\nconst FIRST_SCREENS = 2\n\n/**\n * One document on the page — the opened file, or the content of one chat turn —\n * taken through the whole pipeline (parse, measure, judge, plan) and rendered in\n * its own theme.\n */\nexport function TurnView({\n id,\n prefix,\n markdown: given,\n streaming = false,\n waiting = false,\n idle = false,\n asked,\n writing,\n lockTheme = false,\n themeContext,\n opening,\n pendingStyle,\n fill = false,\n onReady,\n classifier,\n fixedTheme,\n palettePick,\n autoTheme = true,\n appearance,\n resolveUrl,\n controls,\n editable = false,\n loadFonts,\n settleMs,\n maxWaitMs,\n view,\n onReport,\n onMarkdownChange,\n}: TurnViewProps) {\n const element = useRef<HTMLElement>(null)\n\n // The reader's edits, once applied, take the place of the text that was given.\n const [edited, setEdited] = useState<string | null>(null)\n const markdown = edited ?? given\n const [draft, setDraft] = useState<string | null>(null)\n // Edits are applied on leaving the editor, not per keystroke: re-planning and\n // re-asking the classifier for every character would be wasteful and jumpy.\n const [seenView, setSeenView] = useState(view)\n if (view !== seenView) {\n setSeenView(view)\n if (draft !== null && draft !== markdown) setEdited(draft)\n }\n useEffect(() => {\n if (edited !== null) onMarkdownChange?.(edited)\n }, [edited, onMarkdownChange])\n\n const parsed = useMemo(() => parseMarkdown(markdown), [markdown])\n const bodyText = useMemo(() => toText(parsed.root), [parsed])\n const prose = useMemo(() => proseOf(parsed.root), [parsed])\n // What the document's own vocabulary suggests, before any classifier is asked.\n const keywordTheme = useMemo(() => {\n const stats = { codeBlocks: (markdown.match(/^```/gm) ?? []).length / 2, tables: (markdown.match(/^\\|?\\s*:?-{3,}/gm) ?? []).length }\n return matchTheme(bodyText, stats)\n }, [markdown, bodyText])\n\n const [images, setImages] = useState<ImageMetaMap | null>(null)\n const [judged, setJudged] = useState<Judgements | null>(null)\n // Classifier questions still unanswered; `null` until the first have been asked.\n const [pending, setPending] = useState<string[] | null>(null)\n const [revealed, setRevealed] = useState(false)\n const [layouts, setLayouts] = useState<Record<string, SectionLayout>>({})\n const [vizPicks, setVizPicks] = useState<Record<string, VizKind>>({})\n const [locked, setLocked] = useState<ThemeChoice | null>(null)\n const hasText = markdown.trim().length > 0\n\n // 1. Measure images — their size decides hero, full-bleed and split layouts.\n useEffect(() => {\n let live = true\n const urls = collectImageUrls(parsed.root)\n const cover = [\"image\", \"cover\", \"banner\"].map((key) => parsed.frontmatter[key]).filter((v): v is string => typeof v === \"string\")\n probeImages([...urls, ...cover], resolveUrl, settleMs).then((result) => live && setImages(result))\n return () => {\n live = false\n }\n }, [parsed, resolveUrl, settleMs])\n\n // 2. Ask the classifier, once sizes are known, about what rules cannot decide.\n // Every question is asked straight away, top of the page first, and each\n // answer is applied as it lands — nothing waits for the reader to scroll.\n // A turn that grows asks about its theme separately, once (see below).\n // One that chooses its look first lets that question go ahead of the rest.\n // Whether this turn picks its look from its opening and holds it; with the theme set from outside, there is nothing to pick.\n const locking = lockTheme && autoTheme\n const awaitingTheme = locking && locked === null\n useEffect(() => {\n if (!images || !classifier || !hasText || awaitingTheme) return\n const abort = new AbortController()\n const structural = planDocument({ root: parsed.root, frontmatter: parsed.frontmatter, images, idPrefix: prefix })\n judgeDocument(structural, prose, classifier, {\n signal: abort.signal,\n themeHint: keywordTheme ?? undefined,\n skipTheme: lockTheme || !autoTheme,\n onProgress: (progress) => {\n setJudged(progress.judgements)\n setPending(progress.pending)\n },\n }).catch((error) => {\n if (abort.signal.aborted) return\n console.warn(\"[stunning-md] classifier unavailable; using rules only\", error)\n setPending([])\n })\n return () => abort.abort()\n }, [images, classifier, parsed, prose, keywordTheme, prefix, hasText, lockTheme, autoTheme, awaitingTheme])\n\n const plan = useMemo(\n () =>\n planDocument({\n root: parsed.root,\n frontmatter: parsed.frontmatter,\n images: images ?? {},\n judgements: { ...judged, viz: { ...judged?.viz, ...vizPicks }, layouts },\n idPrefix: prefix,\n }),\n [parsed, images, judged, vizPicks, layouts, prefix],\n )\n\n const measured = images !== null\n const outstanding = classifier ? pending : NONE\n // A theme is a whole look — colours, typefaces and corner style travel together —\n // whether it was guessed from keywords, chosen by the classifier or picked by hand.\n const suggested = useMemo<ThemeChoice>(() => ({ ...themeChoice(keywordTheme ?? \"paper\"), ...judged?.theme }), [keywordTheme, judged])\n // A turn that is still being written chooses its look once, from its opening,\n // and keeps it — rather than changing its mind with every section that arrives.\n // `seed` is that opening: the turn's text when it first had any.\n const [seed, setSeed] = useState<string | null>(null)\n // A document already on the page that starts to grow keeps the look it has.\n const [wasLocking, setWasLocking] = useState(locking)\n if (locking !== wasLocking) {\n setWasLocking(locking)\n if (locking && !locked && hasText) setLocked(suggested)\n }\n // Frontmatter alone says too little to choose by: wait for the first words of the text itself.\n const seedSource = opening === undefined ? (bodyText.trim() ? markdown : null) : opening\n if (locking && seed === null && seedSource) setSeed(seedSource)\n const seedTheme = useMemo<ThemeChoice | null>(() => {\n if (seed === null) return null\n const words = `${toText(parseMarkdown(seed).root)} ${themeContext ?? \"\"}`\n return themeChoice(matchTheme(words, { codeBlocks: (seed.match(/^```/gm) ?? []).length / 2, tables: 0 }) ?? \"paper\")\n }, [seed, themeContext])\n // Without a classifier the opening's own words decide.\n if (locking && !locked && seedTheme && !classifier) setLocked(seedTheme)\n useEffect(() => {\n if (!locking || seed === null || !seedTheme || !classifier) return\n let live = true\n const settle = (choice: ThemeChoice) => live && setLocked((current) => current ?? choice)\n // An answer should not sit unseen while a slow classifier makes up its mind.\n const timer = setTimeout(() => settle(seedTheme), Math.min(maxWaitMs, THEME_PATIENCE))\n const opening = parseMarkdown(seed)\n judgeDocument(planDocument({ root: opening.root, frontmatter: opening.frontmatter, idPrefix: prefix }), proseOf(opening.root), classifier, {\n themeOnly: true,\n themeHint: seedTheme.palette === \"paper\" ? undefined : seedTheme.palette,\n // An opening is short and often has no telling words of its own; with nothing\n // else to go on, the classifier's leading choice is taken on less certainty.\n confidence: seedTheme.palette === \"paper\" ? SEED_CONFIDENCE : undefined,\n context: themeContext,\n }).then(\n (judgement) => settle({ ...seedTheme, ...judgement.theme }),\n () => settle(seedTheme),\n )\n return () => {\n live = false\n clearTimeout(timer)\n }\n }, [locking, seed, seedTheme, classifier, prefix, themeContext, maxWaitMs])\n\n const theme = useMemo<ThemeChoice>(() => {\n const fromFrontmatter = parsed.frontmatter.theme\n const picked = palettePick ?? (typeof fromFrontmatter === \"string\" && fromFrontmatter in themes ? (fromFrontmatter as PaletteId) : null)\n const base = picked ? themeChoice(picked) : locking ? (locked ?? suggested) : suggested\n return { ...base, ...fixedTheme }\n }, [parsed, palettePick, locking, locked, suggested, fixedTheme])\n\n const fontsReady = useFonts(googleFontsUrl(fontPairings[theme.fonts]), loadFonts)\n // A turn that chooses its look from its opening has none until that choice is made.\n const themed = !locking || locked !== null\n const visible = measured && hasText && themed\n\n // 3. Say when the top of the turn has stopped moving: the theme and its fonts\n // are in, and no unanswered question concerns a block near the top. The turn\n // is already laid out (under the page's loader), so this is measured, not guessed.\n useEffect(() => {\n if (!onReady || revealed || !measured) return\n const frame = requestAnimationFrame(() => {\n const el = element.current\n if (!el || !outstanding || !fontsReady) return\n if (outstanding.includes(\"theme\") || outstanding.includes(\"hero\")) return\n const top = el.getBoundingClientRect().top\n const limit = window.innerHeight * FIRST_SCREENS\n const shifting = outstanding.some((block) => {\n const node = el.querySelector(`[data-block-id=\"${CSS.escape(block)}\"]`)\n return !!node && node.getBoundingClientRect().top - top < limit\n })\n if (!shifting) setRevealed(true)\n })\n return () => cancelAnimationFrame(frame)\n }, [onReady, revealed, measured, outstanding, fontsReady, plan, theme])\n\n // A slow classifier or font host must not hold the page back indefinitely.\n useEffect(() => {\n if (!onReady || !measured) return\n const timer = setTimeout(() => setRevealed(true), maxWaitMs)\n return () => clearTimeout(timer)\n }, [onReady, measured, maxWaitMs])\n\n useEffect(() => {\n if (revealed) onReady?.()\n }, [revealed, onReady])\n\n useEffect(() => {\n onReport(id, { plan, theme: themed ? theme : null })\n }, [id, plan, theme, themed, onReport])\n\n // The request stands in for the answer until the first of it arrives, then fades away.\n const pendingRequest = streaming && waiting && asked ? asked : null\n const [bubble, setBubble] = useState<{ text: string; leaving: boolean } | null>(null)\n if (pendingRequest && (bubble?.text !== pendingRequest || bubble.leaving)) setBubble({ text: pendingRequest, leaving: false })\n else if (!pendingRequest && bubble && !bubble.leaving) setBubble({ ...bubble, leaving: true })\n useEffect(() => {\n if (!bubble?.leaving) return\n const timer = setTimeout(() => setBubble(null), ASKED_FADE)\n return () => clearTimeout(timer)\n }, [bubble])\n\n const style = useMemo(() => themeVars(theme, appearance), [theme, appearance])\n const chartTheme = useMemo(() => chartThemeFor(theme), [theme])\n const setLayout = useCallback((section: string, layout: SectionLayout) => setLayouts((prev) => ({ ...prev, [section]: layout })), [])\n const setViz = useCallback((block: string, kind: VizKind) => setVizPicks((prev) => ({ ...prev, [block]: kind })), [])\n\n const context = useMemo<StunningContext>(\n () => ({\n resolveUrl,\n appearance,\n theme,\n chartTheme,\n portal: { className: cn(\"smd-portal\", appearance === \"dark\" && \"dark\"), style },\n controls,\n setLayout,\n setViz,\n }),\n [resolveUrl, appearance, theme, chartTheme, style, controls, setLayout, setViz],\n )\n\n return (\n <StunningProvider value={context}>\n <article\n ref={element}\n id={`${id}-turn`}\n className=\"smd-turn\"\n style={visible ? style : pendingStyle}\n data-theme={visible ? theme.palette : undefined}\n // Themes with a second colour set their quotations in it.\n data-highlight={visible && themes[theme.palette][appearance].highlight ? \"\" : undefined}\n data-fill={fill || undefined}\n // A turn that is written while you watch brings each new part in gently.\n data-grows={lockTheme || undefined}\n >\n {visible &&\n (view === \"source\" ? (\n <SourceView value={draft ?? markdown} onChange={editable ? setDraft : undefined} />\n ) : view === \"plain\" ? (\n <PlainDocument root={parsed.root} toc={plan.toc} />\n ) : (\n <>\n <HeroView plan={plan} id={`${prefix}top`} />\n <div className=\"smd-sections\">\n {plan.sections.map((section) => (\n <SectionView key={section.id} section={section} />\n ))}\n </div>\n </>\n ))}\n {/* Shown while the turn is being written — and after, if what was written is still waiting for its look. */}\n {(streaming || (hasText && !visible)) && (\n <div className=\"smd-writing\" role=\"status\">\n {/* The spinner stays where it is from the first moment to the last; only what stands beside it changes. */}\n <span className=\"smd-loader-mark\" aria-hidden />\n {bubble ? (\n <p className=\"smd-asked\" data-leaving={bubble.leaving || undefined}>\n <span className=\"sr-only\">Waiting for a response to: </span>\n <span>{bubble.text}</span>\n </p>\n ) : idle && streaming ? (\n // Nothing is known to be on its way to the page, so there is no progress to name.\n <span className=\"sr-only\">Waiting for the reply</span>\n ) : (\n <p>{waiting ? \"Waiting for first response ...\" : writing ? `Writing “${writing}” ...` : \"Stunnifying ...\"}</p>\n )}\n </div>\n )}\n </article>\n </StunningProvider>\n )\n}\n","import type { ImageMeta } from \"../types\"\nimport type { ImageMetaMap } from \"./plan\"\n\nconst cache = new Map<string, Promise<ImageMeta | null>>()\n\nfunction probe(url: string, timeoutMs: number): Promise<ImageMeta | null> {\n const hit = cache.get(url)\n if (hit) return hit\n const pending = new Promise<ImageMeta | null>((resolve) => {\n const image = new Image()\n const timer = setTimeout(() => resolve(null), timeoutMs)\n image.onload = () => {\n clearTimeout(timer)\n // SVGs without intrinsic size report 0; treat them as unmeasured.\n resolve(image.naturalWidth > 0 ? { width: image.naturalWidth, height: image.naturalHeight } : null)\n }\n image.onerror = () => {\n clearTimeout(timer)\n resolve(null)\n }\n image.src = url\n })\n cache.set(url, pending)\n return pending\n}\n\n/**\n * Loads each image far enough to learn its natural size. Images that fail or\n * take longer than the timeout come back as `null` and are laid out conservatively.\n */\nexport async function probeImages(urls: string[], resolveUrl: (url: string) => string, timeoutMs = 2500): Promise<ImageMetaMap> {\n const entries = await Promise.all(urls.map(async (url) => [url, await probe(resolveUrl(url), timeoutMs)] as const))\n return Object.fromEntries(entries)\n}\n","import type { PhrasingContent, Table } from \"mdast\"\nimport type { ChartSpec, ColumnType, TableColumn, TableModel, TableRow, VizKind, VizPlan } from \"../types\"\nimport { toText } from \"./text\"\n\ntype Unit = { prefix: string; suffix: string }\ntype ParsedNumber = { value: number } & Unit\n\nconst MISSING = /^(|-|–|—|n\\/?a|na|null|none|tbd|\\?)$/i\nconst CURRENCY = \"[$€£¥₹₩₽]|[A-Z]{1,3}\\\\$|(?:USD|EUR|GBP|SGD|JPY|CHF|AUD|CAD|INR|CNY)\\\\b\"\nconst NUMBER = new RegExp(\n `^([(]?)\\\\s*([-−–+]?)\\\\s*(${CURRENCY})?\\\\s*([-−–+]?)\\\\s*(\\\\d[\\\\d,' ]*(?:\\\\.\\\\d+)?|\\\\.\\\\d+)\\\\s*` +\n `(k|K|M|B|T|bn|mn|m|thousand|million|billion|trillion)?\\\\s*(%|‰|[a-zA-Z°µ²³/]{1,8})?\\\\s*([)]?)$`,\n)\nconst MAGNITUDE: Record<string, number> = {\n k: 1e3, K: 1e3, thousand: 1e3,\n M: 1e6, m: 1e6, mn: 1e6, million: 1e6,\n B: 1e9, bn: 1e9, billion: 1e9,\n T: 1e12, trillion: 1e12,\n}\n\nexport function parseNumber(raw: string): ParsedNumber | null {\n const text = raw.trim()\n const match = NUMBER.exec(text)\n if (!match) return null\n const [, open, signA, currency = \"\", signB, digits, magnitude, suffixRaw = \"\", close] = match\n let suffix = suffixRaw\n let scale = 1\n if (magnitude) {\n // A bare lowercase \"m\" is metres unless money is involved (\"$5m\").\n if (magnitude === \"m\" && !currency) suffix = `m${suffix}`\n else scale = MAGNITUDE[magnitude]\n }\n const value = Number(digits.replace(/[,' ]/g, \"\")) * scale\n if (!Number.isFinite(value)) return null\n const negative = (open && close) || /[-−–]/.test(signA + signB)\n return { value: negative ? -value : value, prefix: currency.trim(), suffix }\n}\n\nconst MONTHS = [\"jan\", \"feb\", \"mar\", \"apr\", \"may\", \"jun\", \"jul\", \"aug\", \"sep\", \"oct\", \"nov\", \"dec\"]\nconst monthIndex = (name: string) => MONTHS.indexOf(name.slice(0, 3).toLowerCase())\nconst MONTH_NAME = \"(jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|june?|july?|aug(?:ust)?|sep(?:t(?:ember)?)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)\\\\.?\"\nconst fullYear = (y: string) => (y.length === 2 ? 2000 + Number(y) : Number(y))\nconst validYear = (y: number) => y >= 1000 && y <= 2200\n\n/** Parses the date shapes that show up in tables. Returns UTC epoch milliseconds. */\nexport function parseDate(raw: string): number | null {\n const text = raw.trim().replace(/\\s+/g, \" \")\n let m: RegExpExecArray | null\n if ((m = /^(\\d{4})$/.exec(text))) return validYear(+m[1]) ? Date.UTC(+m[1], 0, 1) : null\n if ((m = /^(\\d{4})[-/.](\\d{1,2})(?:[-/.](\\d{1,2}))?(?:[T ][\\d:.]+Z?)?$/.exec(text))) {\n return +m[2] >= 1 && +m[2] <= 12 ? Date.UTC(+m[1], +m[2] - 1, +(m[3] ?? 1)) : null\n }\n if ((m = /^(?:FY|CY) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[1]), 0, 1)\n if ((m = /^Q([1-4]) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[2]), (+m[1] - 1) * 3, 1)\n if ((m = /^'?(\\d{2}|\\d{4}) ?Q([1-4])$/i.exec(text))) return Date.UTC(fullYear(m[1]), (+m[2] - 1) * 3, 1)\n if ((m = /^H([12]) ?'?(\\d{2}|\\d{4})$/i.exec(text))) return Date.UTC(fullYear(m[2]), (+m[1] - 1) * 6, 1)\n if ((m = new RegExp(`^${MONTH_NAME}$`, \"i\").exec(text))) return Date.UTC(2000, monthIndex(m[1]), 1)\n if ((m = new RegExp(`^${MONTH_NAME} '?(\\\\d{2}|\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(fullYear(m[2]), monthIndex(m[1]), 1)\n }\n if ((m = new RegExp(`^${MONTH_NAME} (\\\\d{1,2})(?:st|nd|rd|th)?,? (\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(+m[3], monthIndex(m[1]), +m[2])\n }\n if ((m = new RegExp(`^(\\\\d{1,2})(?:st|nd|rd|th)? ${MONTH_NAME},? (\\\\d{4})$`, \"i\").exec(text))) {\n return Date.UTC(+m[3], monthIndex(m[2]), +m[1])\n }\n if ((m = /^(\\d{1,2})[/.](\\d{1,2})[/.](\\d{2}|\\d{4})$/.exec(text))) {\n const [a, b] = [+m[1], +m[2]]\n const [month, day] = a > 12 ? [b, a] : [a, b]\n return month >= 1 && month <= 12 && day <= 31 ? Date.UTC(fullYear(m[3]), month - 1, day) : null\n }\n return null\n}\n\nconst ID_HEADER = /^(#|no\\.?|nr\\.?|id|rank|pos(ition)?|s\\/n|index|ref)$/i\nconst TIME_HEADER = /\\b(years?|dates?|when|periods?|months?|quarters?|fy|time|days?|weeks?)\\b/i\nconst SHARE_HEADER = /\\b(share|allocation|mix|breakdown|distribution|portion|weight|split|composition)\\b/i\nconst SUMMARY_LABEL = /^(grand )?(total|sum|overall|subtotal|average|avg|mean|median|all)\\b/i\n\n/** Reads \"Revenue ($M)\" → { prefix: \"$\", suffix: \"M\" }. */\nfunction unitFromHeader(label: string): Unit | undefined {\n const match = /[([]\\s*([^)\\]]{1,10})\\s*[)\\]]\\s*$/.exec(label)\n if (!match) return label.trim().endsWith(\"%\") ? { prefix: \"\", suffix: \"%\" } : undefined\n const hint = match[1].trim()\n const currency = new RegExp(`^(${CURRENCY})`).exec(hint)\n if (currency) return { prefix: currency[1], suffix: hint.slice(currency[1].length).trim() }\n if (/^in /i.test(hint)) return { prefix: \"\", suffix: ` ${hint.slice(3)}` }\n return { prefix: \"\", suffix: hint === \"%\" ? \"%\" : ` ${hint}` }\n}\n\nconst mostCommon = (values: string[]) => {\n const counts = new Map<string, number>()\n for (const v of values) counts.set(v, (counts.get(v) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? \"\"\n}\n\nexport function buildTableModel(node: Table): TableModel {\n const [head, ...body] = node.children\n const headers = (head?.children ?? []).map((cell) => toText(cell).trim())\n const width = Math.max(headers.length, ...body.map((row) => row.children.length))\n const cellText = body.map((row) => Array.from({ length: width }, (_, c) => toText(row.children[c]).trim()))\n\n const columns: TableColumn[] = []\n const parsed: (number | string | null)[][] = body.map(() => [])\n\n for (let c = 0; c < width; c++) {\n const label = headers[c] || \"\"\n const cells = cellText.map((row) => row[c])\n const present = cells.filter((text) => !MISSING.test(text))\n const numbers = cells.map((text) => (MISSING.test(text) ? null : parseNumber(text)))\n const dates = cells.map((text) => (MISSING.test(text) ? null : parseDate(text)))\n const numericCount = numbers.filter(Boolean).length\n const dateCount = dates.filter((d) => d != null).length\n const enough = (count: number) => present.length > 0 && count >= Math.max(1, Math.ceil(present.length * 0.9))\n\n const allYears = enough(dateCount) && present.every((text) => /^\\d{4}$/.test(text))\n let type: ColumnType = \"text\"\n // Bare four-digit numbers are years only where a time axis is expected.\n if (enough(dateCount) && (!allYears || c === 0 || TIME_HEADER.test(label))) type = \"date\"\n else if (enough(numericCount) && !ID_HEADER.test(label)) type = \"number\"\n\n let unit: Unit | undefined\n if (type === \"number\") {\n const found = numbers.filter((n): n is ParsedNumber => n != null)\n const prefix = mostCommon(found.map((n) => n.prefix))\n const suffix = mostCommon(found.map((n) => n.suffix))\n unit = prefix || suffix ? { prefix, suffix } : unitFromHeader(label)\n }\n\n const align = node.align?.[c] ?? (type === \"number\" ? \"right\" : \"left\")\n columns.push({ key: `c${c}`, label: label || `Column ${c + 1}`, type, unit, align })\n cellText.forEach((row, r) => {\n parsed[r][c] = type === \"number\" ? (numbers[r]?.value ?? null) : type === \"date\" ? dates[r] : row[c]\n })\n }\n\n const rows: TableRow[] = body.map((row, r) => ({\n text: Object.fromEntries(columns.map((col, c) => [col.key, cellText[r][c]])),\n value: Object.fromEntries(columns.map((col, c) => [col.key, parsed[r][c]])),\n cells: Array.from({ length: width }, (_, c) => (row.children[c]?.children ?? []) as PhrasingContent[]),\n }))\n\n return { node, columns, rows }\n}\n\nconst unitKey = (unit?: Unit) => `${unit?.prefix ?? \"\"}|${unit?.suffix ?? \"\"}`\n\n/**\n * Series are only plotted together when they share a unit and a comparable scale.\n * Anything else gets its own chart — two scales on one plot mislead.\n */\nfunction groupSeries(model: TableModel, numeric: TableColumn[], rowIndices: number[]): ChartSpec[] {\n const byUnit = new Map<string, TableColumn[]>()\n for (const column of numeric) {\n const key = unitKey(column.unit)\n byUnit.set(key, [...(byUnit.get(key) ?? []), column])\n }\n const charts: ChartSpec[] = []\n for (const group of byUnit.values()) {\n const peak = (column: TableColumn) =>\n Math.max(0, ...rowIndices.map((r) => Math.abs((model.rows[r].value[column.key] as number | null) ?? 0)))\n const sorted = [...group].sort((a, b) => peak(b) - peak(a))\n let cluster: TableColumn[] = []\n for (const column of sorted) {\n if (cluster.length && peak(cluster[0]) > peak(column) * 30) {\n charts.push({ seriesKeys: cluster.map((c) => c.key), unit: cluster[0].unit })\n cluster = []\n }\n cluster.push(column)\n }\n if (cluster.length) charts.push({ seriesKeys: cluster.map((c) => c.key), unit: cluster[0].unit })\n }\n // Keep the document's column order within and across charts.\n const order = (key: string) => model.columns.findIndex((c) => c.key === key)\n for (const chart of charts) chart.seriesKeys.sort((a, b) => order(a) - order(b))\n return charts.sort((a, b) => order(a.seriesKeys[0]) - order(b.seriesKeys[0]))\n}\n\n/** Chooses how a table is best shown, from its shape and the types of its columns. */\nexport function planViz(model: TableModel): VizPlan {\n const { columns, rows } = model\n const all = rows.map((_, i) => i)\n const table = (reason: string, candidates: VizKind[] = []): VizPlan => ({\n kind: \"table\",\n charts: [],\n rowIndices: all,\n candidates: [\"table\", ...candidates],\n reason,\n })\n\n if (rows.length === 0 || columns.length < 2) return table(\"too small to visualise\")\n\n let numeric = columns.filter((c) => c.type === \"number\")\n const dateColumn = columns.find((c) => c.type === \"date\")\n const texts = columns.filter((c) => c.type === \"text\")\n let label: TableColumn | undefined = dateColumn ?? texts[0]\n // A leading numeric column that only ever rises (1, 4, 8, 16…) is an ordered axis, not a measure.\n let ordinal = false\n if (!label && rows.length >= 3 && numeric.length >= 2 && numeric[0] === columns[0]) {\n const steps = rows.map((row) => row.value[columns[0].key] as number | null)\n if (steps.every((v, i) => v != null && (i === 0 || v > steps[i - 1]!))) {\n label = columns[0]\n numeric = numeric.slice(1)\n ordinal = true\n }\n }\n const otherTexts = texts.filter((c) => c !== label)\n const avgLength = (column: TableColumn) =>\n rows.reduce((sum, row) => sum + row.text[column.key].length, 0) / rows.length\n\n // A single row of numbers is a row of headline figures.\n if (rows.length === 1 && numeric.length >= 2 && numeric.length <= 6) {\n return {\n kind: \"stats\",\n labelKey: label?.key,\n charts: [{ seriesKeys: numeric.map((c) => c.key) }],\n rowIndices: all,\n candidates: [\"stats\", \"table\"],\n reason: \"one row of figures\",\n }\n }\n if (rows.length < 2) return table(\"single row\")\n\n if (numeric.length === 0) {\n if (dateColumn && otherTexts.length + (texts.includes(label!) ? 0 : texts.length) >= 1 && rows.length >= 3) {\n return {\n kind: \"timeline\",\n labelKey: dateColumn.key,\n charts: [],\n rowIndices: all,\n candidates: [\"timeline\", \"table\"],\n reason: \"dated events without figures\",\n }\n }\n if (columns.length === 2 && rows.length <= 12 && avgLength(columns[0]) <= 28) {\n return {\n kind: \"facts\",\n labelKey: columns[0].key,\n charts: [],\n rowIndices: all,\n candidates: [\"facts\", \"table\"],\n reason: \"short key–value pairs\",\n }\n }\n return table(\"no numeric columns\")\n }\n\n if (!label) {\n if (numeric.length >= 2 && rows.length >= 5) {\n return {\n kind: \"scatter\",\n labelKey: numeric[0].key,\n charts: [{ seriesKeys: [numeric[1].key], unit: numeric[1].unit }],\n rowIndices: all,\n candidates: [\"scatter\", \"table\"],\n reason: \"two measures and no category\",\n }\n }\n return table(\"no label column\")\n }\n\n // A lone column of bare years, in order, beside descriptions is a sequence of\n // events. Drawn as bars it would compare the years as if they were amounts.\n if (!dateColumn && numeric.length === 1 && label.type === \"text\" && rows.length >= 3 && avgLength(label) >= 16) {\n const years = rows.map((row) => (/^\\d{4}$/.test(row.text[numeric[0].key]) ? (row.value[numeric[0].key] as number) : NaN))\n const plausible = years.every((year) => year >= 1000 && year <= 2100)\n const ordered = years.every((year, i) => i === 0 || year >= years[i - 1]) || years.every((year, i) => i === 0 || year <= years[i - 1])\n if (plausible && ordered) {\n return {\n kind: \"timeline\",\n labelKey: numeric[0].key,\n charts: [],\n rowIndices: all,\n candidates: [\"timeline\", \"table\"],\n reason: \"years in order beside descriptions\",\n }\n }\n }\n\n // Records with as much description as measurement read better as a table.\n if (otherTexts.length >= numeric.length || otherTexts.some((c) => avgLength(c) > 40)) {\n // …unless they are dated, in which case they are a sequence of events.\n if (dateColumn && rows.length >= 3 && numeric.length <= 1) {\n return {\n kind: \"timeline\",\n labelKey: dateColumn.key,\n charts: [],\n rowIndices: all,\n candidates: [\"timeline\", \"table\"],\n reason: \"dated events with descriptions\",\n }\n }\n return table(\"descriptive columns outweigh figures\", dateColumn ? [\"timeline\"] : [])\n }\n\n const labels = rows.map((row) => row.text[label.key])\n let rowIndices = all.filter((r) => !(rows.length > 2 && SUMMARY_LABEL.test(labels[r])))\n if (new Set(rowIndices.map((r) => labels[r])).size < rowIndices.length) {\n return table(\"repeated labels — these are records, not categories\")\n }\n if (rowIndices.length < 2) return table(\"too few rows\")\n\n const charts = groupSeries(model, numeric, rowIndices)\n if (charts.length > 3 || charts.some((c) => c.seriesKeys.length > 8)) {\n return table(\"too many unrelated measures\", [\"bar\"])\n }\n const single = charts.length === 1 && charts[0].seriesKeys.length === 1\n const count = rowIndices.length\n\n if (label.type === \"date\" || ordinal) {\n const axis = label.key\n const times = rowIndices.map((r) => rows[r].value[axis] as number)\n if (times[0] > times[times.length - 1]) rowIndices = [...rowIndices].reverse()\n // One measure per plot: a trend once there are enough periods, bars to compare a few.\n const alone = charts.every((chart) => chart.seriesKeys.length === 1)\n const kind: VizKind = alone ? (count >= 8 ? \"area\" : \"bar\") : count >= 4 ? \"line\" : \"bar\"\n return {\n kind,\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [...new Set<VizKind>([kind, \"line\", \"bar\", \"area\", \"table\"])],\n reason: `${count} ${ordinal ? \"steps\" : \"periods\"} × ${numeric.length} measure(s)`,\n }\n }\n\n if (count > 30) return table(\"too many categories for a readable chart\", [\"bar\"])\n\n if (single) {\n const column = columns.find((c) => c.key === charts[0].seriesKeys[0])!\n const values = rowIndices.map((r) => (rows[r].value[column.key] as number | null) ?? 0)\n if (count <= 4 && otherTexts.length === 0) {\n return {\n kind: \"stats\",\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [\"stats\", \"bar\", \"table\"],\n reason: \"a handful of headline figures\",\n }\n }\n const sum = values.reduce((a, b) => a + b, 0)\n const wholeOf100 = column.unit?.suffix === \"%\" && sum > 98 && sum < 102\n if (count >= 3 && count <= 6 && values.every((v) => v >= 0) && (wholeOf100 || SHARE_HEADER.test(column.label))) {\n return {\n kind: \"donut\",\n labelKey: label.key,\n charts,\n rowIndices,\n candidates: [\"donut\", \"bar\", \"table\"],\n reason: \"parts of a whole\",\n }\n }\n }\n\n const cells = count * numeric.length\n if (!single && cells > 48) return table(\"too dense to chart\", [\"bar\"])\n const longest = Math.max(...rowIndices.map((r) => labels[r].length))\n return {\n kind: \"bar\",\n labelKey: label.key,\n charts,\n horizontal: single && (count > 7 || longest > 14),\n rowIndices,\n candidates: single && count <= 6 ? [\"bar\", \"donut\", \"stats\", \"table\"] : [\"bar\", \"table\"],\n reason: `${count} categories × ${numeric.length} measure(s)`,\n }\n}\n\n/** Re-plans a table as a specific form, when that form is one of its candidates. */\nexport function withVizKind(plan: VizPlan, model: TableModel, kind: VizKind): VizPlan {\n if (kind === plan.kind || !plan.candidates.includes(kind)) return plan\n const next: VizPlan = { ...plan, kind, reason: `${plan.reason} → overridden to ${kind}` }\n if (kind === \"timeline\") {\n next.labelKey = model.columns.find((c) => c.type === \"date\")?.key ?? plan.labelKey\n next.rowIndices = model.rows.map((_, i) => i)\n }\n if (kind === \"bar\" && plan.charts.length === 0) {\n const numeric = model.columns.filter((c) => c.type === \"number\")\n const label = model.columns.find((c) => c.type !== \"number\")\n if (!numeric.length || !label) return plan\n next.labelKey = label.key\n next.charts = groupSeries(model, numeric, plan.rowIndices)\n }\n if (kind === \"bar\") {\n const longest = Math.max(...next.rowIndices.map((r) => model.rows[r].text[next.labelKey ?? \"\"]?.length ?? 0))\n const single = next.charts.length === 1 && next.charts[0].seriesKeys.length === 1\n next.horizontal = single && (next.rowIndices.length > 7 || longest > 14)\n }\n return next\n}\n\n/** Compact, unit-aware number formatting for axes, tooltips and stat tiles. */\nexport function formatValue(value: number, unit?: Unit): string {\n const abs = Math.abs(value)\n const body =\n abs >= 10000\n ? new Intl.NumberFormat(\"en\", { notation: \"compact\", maximumFractionDigits: 1 }).format(value)\n : new Intl.NumberFormat(\"en\", { maximumFractionDigits: abs < 10 ? 2 : abs < 100 ? 1 : 0 }).format(value)\n const sign = body.startsWith(\"-\") ? \"−\" : \"\"\n return `${sign}${unit?.prefix ?? \"\"}${body.replace(/^-/, \"\")}${unit?.suffix ?? \"\"}`\n}\n","import type { Blockquote, Heading, List, Paragraph, PhrasingContent, Root, RootContent } from \"mdast\"\nimport type { Frontmatter } from \"../parse\"\nimport type {\n Block,\n DocumentPlan,\n Hero,\n ImageMeta,\n ImageRef,\n Judgements,\n ListVariant,\n Section,\n SectionLayout,\n TocEntry,\n} from \"../types\"\nimport { buildTableModel, planViz, withVizKind } from \"./tables\"\nimport { countWords, imagesOnly, slugify, toText, wordsIn } from \"./text\"\n\nexport type ImageMetaMap = Record<string, ImageMeta | null | undefined>\n\nexport type PlanInput = {\n root: Root\n frontmatter?: Frontmatter\n /** Natural image sizes keyed by the URL written in the markdown. */\n images?: ImageMetaMap\n judgements?: Judgements\n /**\n * Put in front of every id the plan generates. Needed when several documents\n * share one page, so their section anchors cannot collide.\n */\n idPrefix?: string\n}\n\nconst BADGE_URL = /shields\\.io|badgen\\.net|badge\\.fury\\.io|\\/badge(s)?[./]|badge\\.svg|travis-ci|circleci\\.com|codecov\\.io|coveralls\\.io|img\\.shields/i\nconst LOGO_NAME = /logo|icon|brand|wordmark|avatar|emblem/i\nconst BANNER_NAME = /banner|cover|hero|header|splash|masthead/i\n\n/** Every image URL in the document, for size probing. */\nexport function collectImageUrls(root: Root): string[] {\n const urls = new Set<string>()\n const visit = (node: unknown) => {\n const n = node as { type?: string; url?: string; children?: unknown[] }\n if (n.type === \"image\" && n.url) urls.add(n.url)\n n.children?.forEach(visit)\n }\n visit(root)\n return [...urls]\n}\n\nfunction isBadge(image: ImageRef): boolean {\n if (BADGE_URL.test(image.src)) return true\n return !!image.meta && image.meta.height <= 40 && image.meta.width <= 320\n}\n\nfunction classifyHeroImage(image: ImageRef): Hero[\"variant\"] | null {\n const meta = image.meta\n // An image that could not be measured cannot be trusted to carry the page.\n if (!meta || meta.width < 48) return null\n const aspect = meta.width / meta.height\n const name = `${image.src.split(/[?#]/)[0]} ${image.alt}`\n const vector = /\\.svg$/i.test(image.src.split(/[?#]/)[0])\n if (LOGO_NAME.test(name) && !(meta.width >= 1600 && aspect >= 1.8)) return \"logo\"\n if (meta.width >= 1200 && aspect >= 1.5 && !vector) return \"banner\"\n if (BANNER_NAME.test(name) && meta.width >= 900 && aspect >= 1.5) return \"banner\"\n if (vector || Math.max(meta.width, meta.height) <= 640) return \"logo\"\n return \"figure\"\n}\n\ntype Context = {\n images: ImageMetaMap\n judgements: Judgements\n slugs: Set<string>\n prefix: string\n sectionDepth: number\n splitCount: number\n dataCount: number\n}\n\nfunction imageRef(found: { image: { url: string; alt?: string | null; title?: string | null }; href?: string }, ctx: Context): ImageRef {\n return {\n src: found.image.url,\n alt: found.image.alt ?? \"\",\n title: found.image.title ?? undefined,\n href: found.href,\n meta: ctx.images[found.image.url] ?? undefined,\n }\n}\n\nfunction planList(node: List): { variant: ListVariant; columns: 1 | 2 } {\n const items = node.children\n if (items.some((item) => item.checked != null)) return { variant: \"checklist\", columns: 1 }\n const nested = items.some((item) => item.children.some((child) => child.type === \"list\" || child.type === \"code\"))\n const words = items.map((item) => wordsIn(item))\n const total = words.reduce((a, b) => a + b, 0)\n const longest = Math.max(0, ...words)\n // Short lists are a moment of emphasis; long ones are body copy that happens to be bulleted.\n if (!nested && items.length >= 2 && items.length <= 8 && longest <= 28 && total <= 130) {\n return { variant: \"feature\", columns: items.length >= 4 && longest <= 12 ? 2 : 1 }\n }\n return { variant: \"body\", columns: 1 }\n}\n\nconst ATTRIBUTION = /^\\s*(?:[—–]|--|~)\\s*(.+)$/\n\nfunction planQuote(node: Blockquote): Extract<Block, { kind: \"quote\" }> {\n let children = node.children as RootContent[]\n const first = children[0]\n\n // GitHub-style alerts: > [!NOTE]\n if (first?.type === \"paragraph\" && first.children[0]?.type === \"text\") {\n const match = /^\\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\]\\s*/i.exec(first.children[0].value)\n if (match) {\n const rest: PhrasingContent[] = [\n { type: \"text\", value: first.children[0].value.slice(match[0].length) },\n ...first.children.slice(1),\n ]\n const body = rest.some((child) => toText(child).trim()) ? [{ ...first, children: rest }] : []\n return { kind: \"quote\", variant: \"callout\", calloutType: match[1].toLowerCase(), children: [...body, ...children.slice(1)] }\n }\n }\n\n let attribution: string | undefined\n const last = children[children.length - 1]\n if (last?.type === \"paragraph\") {\n const whole = ATTRIBUTION.exec(toText(last))\n if (whole && children.length > 1) {\n attribution = whole[1].trim()\n children = children.slice(0, -1)\n } else {\n // Attribution on the final line of the same paragraph.\n const breakAt = last.children.findLastIndex((child) => child.type === \"break\")\n const tail = breakAt >= 0 ? last.children.slice(breakAt + 1) : []\n const lineMatch = tail.length ? ATTRIBUTION.exec(toText(tail)) : /\\n\\s*(?:[—–]|--|~)\\s*([^\\n]+)$/.exec(toText(last))\n if (lineMatch && breakAt >= 0) {\n attribution = lineMatch[1].trim()\n children = [...children.slice(0, -1), { ...last, children: last.children.slice(0, breakAt) }]\n } else if (lineMatch && last.children.length === 1 && last.children[0].type === \"text\") {\n attribution = lineMatch[1].trim()\n const value = last.children[0].value.replace(/\\n\\s*(?:[—–]|--|~)\\s*[^\\n]+$/, \"\")\n children = [...children.slice(0, -1), { ...last, children: [{ type: \"text\", value }] }]\n }\n }\n }\n\n const words = wordsIn(children)\n const simple = children.every((child) => child.type === \"paragraph\")\n return { kind: \"quote\", variant: simple && words <= 45 ? \"pull\" : \"aside\", children, attribution }\n}\n\nfunction buildBlocks(nodes: RootContent[], ctx: Context, sectionId: string): Block[] {\n const blocks: Block[] = []\n for (const node of nodes) {\n switch (node.type) {\n case \"heading\":\n blocks.push({\n kind: \"heading\",\n depth: Math.max(1, node.depth - ctx.sectionDepth),\n id: ctx.prefix + slugify(toText(node), ctx.slugs),\n children: node.children,\n })\n break\n case \"paragraph\": {\n const found = imagesOnly(node.children)\n const refs = found?.map((f) => imageRef(f, ctx))\n if (refs && !refs.every(isBadge)) {\n const previous = blocks[blocks.length - 1]\n const images = previous?.kind === \"media\" ? [...previous.images, ...refs] : refs\n const media: Block = {\n kind: \"media\",\n images,\n variant: images.length >= 3 ? \"slideshow\" : images.length === 2 ? \"pair\" : \"single\",\n }\n if (previous?.kind === \"media\") blocks[blocks.length - 1] = media\n else blocks.push(media)\n } else blocks.push({ kind: \"content\", node })\n break\n }\n case \"list\":\n blocks.push({ kind: \"list\", node, ...planList(node) })\n break\n case \"blockquote\":\n blocks.push(planQuote(node))\n break\n case \"code\":\n blocks.push({ kind: \"code\", lang: node.lang ?? undefined, value: node.value })\n break\n case \"table\": {\n const id = `${sectionId}-data-${++ctx.dataCount}`\n const table = buildTableModel(node)\n const viz = planViz(table)\n const wanted = ctx.judgements.viz?.[id]\n blocks.push({ kind: \"data\", id, table, viz: wanted ? withVizKind(viz, table, wanted) : viz })\n break\n }\n case \"thematicBreak\":\n blocks.push({ kind: \"rule\" })\n break\n default:\n blocks.push({ kind: \"content\", node })\n }\n }\n // A rule earns its place only between two pieces of content. At the start or\n // end of a section or card — where the layout draws its own line — or beside\n // a heading, which is a break already, it is one line too many.\n const breaks = (block?: Block) => !block || block.kind === \"rule\" || block.kind === \"heading\"\n return blocks.filter((block, index) => block.kind !== \"rule\" || !(breaks(blocks[index - 1]) || breaks(blocks[index + 1])))\n}\n\ntype RawSection = { heading?: Heading; nodes: RootContent[] }\n\ntype Shape = {\n words: number\n images: ImageRef[]\n heavy: boolean\n quoteOnly: boolean\n cards: { heading: Heading; nodes: RootContent[] }[] | null\n cardIntro: RootContent[]\n}\n\nfunction measure(raw: RawSection, ctx: Context): Shape {\n const { nodes } = raw\n const images = nodes.flatMap((node) =>\n node.type === \"paragraph\" ? (imagesOnly(node.children) ?? []).map((f) => imageRef(f, ctx)).filter((i) => !isBadge(i)) : [],\n )\n const prose = nodes.filter((node) => node.type !== \"table\" && node.type !== \"code\")\n const heavy = nodes.some((node) => node.type === \"table\" || node.type === \"code\" || node.type === \"math\")\n const quotes = nodes.filter((node) => node.type === \"blockquote\")\n const quoteOnly =\n quotes.length === 1 &&\n !heavy &&\n images.length === 0 &&\n wordsIn(quotes[0]) <= 70 &&\n wordsIn(nodes.filter((node) => node !== quotes[0])) <= 25 &&\n !/^\\[!/.test(toText(quotes[0]).trim())\n\n // Sub-sections that are each a short blurb read as a set of cards.\n const subDepth = ctx.sectionDepth + 1\n const firstSub = nodes.findIndex((node) => node.type === \"heading\" && node.depth === subDepth)\n let cards: Shape[\"cards\"] = null\n if (firstSub >= 0 && !nodes.some((node) => node.type === \"heading\" && node.depth > subDepth)) {\n const groups: { heading: Heading; nodes: RootContent[] }[] = []\n for (const node of nodes.slice(firstSub)) {\n if (node.type === \"heading\") groups.push({ heading: node, nodes: [] })\n else groups[groups.length - 1].nodes.push(node)\n }\n const blurb = (group: { nodes: RootContent[] }) =>\n group.nodes.length > 0 &&\n wordsIn(group.nodes) <= 70 &&\n group.nodes.every(\n (node) => node.type === \"paragraph\" || (node.type === \"list\" && node.children.length <= 5 && wordsIn(node) <= 50),\n ) &&\n group.nodes.filter((node) => node.type === \"paragraph\" && imagesOnly(node.children)).length <= 1\n if (groups.length >= 2 && groups.length <= 12 && groups.every(blurb)) cards = groups\n }\n\n return {\n words: wordsIn(prose),\n images,\n heavy,\n quoteOnly,\n cards,\n cardIntro: firstSub >= 0 ? nodes.slice(0, firstSub) : nodes,\n }\n}\n\n/** Layouts the content can fill, best fit first. `prose` always works. */\nfunction rankLayouts(raw: RawSection, shape: Shape): { layouts: SectionLayout[]; reason: string } {\n const { words, images, heavy } = shape\n const layouts: SectionLayout[] = []\n let reason = \"default reading layout\"\n const pick = (layout: SectionLayout, why: string) => {\n if (!layouts.length) reason = why\n if (!layouts.includes(layout)) layouts.push(layout)\n }\n const lead = images[0]?.meta\n const aspect = lead ? lead.width / lead.height : 0\n const simple = !heavy && !shape.cards\n\n if (shape.quoteOnly) pick(\"quote\", \"a single short quotation\")\n if (simple && images.length === 1 && lead && lead.width >= 1400 && aspect >= 1.3 && words <= 90) {\n pick(\"fullbleed\", `large ${lead.width}×${lead.height} image with ${words} words`)\n }\n if (simple && images.length === 1 && lead && lead.width >= 320 && words >= 20 && words <= 260) {\n pick(\"split\", `one image beside ${words} words`)\n }\n // A long run of prose before the sub-sections is an article with asides, not a card deck.\n const cardsLead = !!shape.cards && (wordsIn(shape.cardIntro) <= 90 || shape.cards.length >= 4)\n if (cardsLead) pick(\"cards\", `${shape.cards!.length} short sub-sections`)\n if (!heavy && images.length >= 2 && words <= 80) pick(\"showcase\", `${images.length} images, little text`)\n // Only a titled section is promoted to a statement: untitled opening text that\n // was not made a hero should not be dressed up as one.\n if (simple && raw.heading && images.length === 0 && words <= 45 && raw.nodes.length <= 3) {\n pick(\"statement\", `only ${words} words — give it room`)\n }\n pick(\"prose\", reason)\n\n // Looser fits: not the first choice, but still valid when picked by hand.\n if (shape.cards) pick(\"cards\", \"\")\n if (simple && images.length >= 1 && lead && lead.width >= 1000 && aspect >= 1.2 && words <= 160) pick(\"fullbleed\", \"\")\n if (simple && images.length >= 1 && lead && words >= 8 && words <= 400) pick(\"split\", \"\")\n if (!heavy && images.length >= 1 && words <= 160) pick(\"showcase\", \"\")\n if (simple && images.length === 0 && words > 0 && words <= 110 && raw.nodes.length <= 5) pick(\"statement\", \"\")\n return { layouts, reason }\n}\n\nfunction buildSection(raw: RawSection, ctx: Context, index: number): Section {\n const titleText = raw.heading ? toText(raw.heading).trim() : \"\"\n const id = ctx.prefix + (raw.heading ? slugify(titleText, ctx.slugs) : slugify(\"introduction\", ctx.slugs))\n const shape = measure(raw, ctx)\n const { layouts, reason } = rankLayouts(raw, shape)\n const wanted = ctx.judgements.layouts?.[id]\n const layout = wanted && layouts.includes(wanted) ? wanted : layouts[0]\n\n let blocks: Block[]\n let feature: ImageRef | undefined\n let flip: boolean | undefined\n\n if (layout === \"cards\" && shape.cards) {\n blocks = [\n ...buildBlocks(shape.cardIntro, ctx, id),\n {\n kind: \"cards\",\n items: shape.cards.map((card) => ({\n id: ctx.prefix + slugify(toText(card.heading), ctx.slugs),\n title: card.heading.children,\n blocks: buildBlocks(card.nodes, ctx, id),\n })),\n },\n ]\n } else if (layout === \"split\" || layout === \"fullbleed\") {\n feature = shape.images[0]\n // The feature image leaves the flow; any further images stay where they were.\n let taken = false\n const rest = raw.nodes.filter((node) => {\n if (taken || node.type !== \"paragraph\") return true\n const found = imagesOnly(node.children)\n if (found?.length === 1 && found[0].image.url === feature!.src) return !(taken = true)\n return true\n })\n blocks = buildBlocks(rest, ctx, id)\n if (layout === \"split\") flip = ctx.splitCount++ % 2 === 1\n } else {\n blocks = buildBlocks(raw.nodes, ctx, id)\n }\n\n const tone = layout === \"quote\" ? \"invert\" : layout === \"statement\" ? \"tint\" : \"plain\"\n return {\n id,\n title: raw.heading?.children ?? [],\n titleText,\n layout,\n tone,\n blocks,\n feature,\n flip,\n words: shape.words,\n reason: wanted && layout === wanted ? `chosen: ${wanted}` : `${reason}${index === 0 && !raw.heading ? \" (introduction)\" : \"\"}`,\n alternatives: layouts,\n }\n}\n\nconst asString = (value: unknown) => (typeof value === \"string\" && value.trim() ? value.trim() : undefined)\n\n/**\n * Turns a parsed document into a layout plan. Pure and deterministic: the same\n * tree, image sizes and judgements always yield the same plan.\n */\nexport function planDocument(input: PlanInput): DocumentPlan {\n const { root } = input\n const frontmatter = input.frontmatter ?? {}\n const nodes = root.children\n const headings = nodes.filter((node): node is Heading => node.type === \"heading\")\n\n // The title is a leading H1 — one that comes before any other heading.\n const titleNode = headings[0]?.depth === 1 ? headings[0] : undefined\n const sectionHeadings = headings.filter((h) => h !== titleNode)\n const sectionDepth = sectionHeadings.length ? Math.min(...sectionHeadings.map((h) => h.depth)) : 2\n\n const ctx: Context = {\n images: input.images ?? {},\n judgements: input.judgements ?? {},\n slugs: new Set([\"top\"]),\n prefix: input.idPrefix ?? \"\",\n sectionDepth,\n splitCount: 0,\n dataCount: 0,\n }\n\n const firstSection = nodes.findIndex((node) => node.type === \"heading\" && node !== titleNode && node.depth === sectionDepth)\n const preamble = (firstSection >= 0 ? nodes.slice(0, firstSection) : nodes).filter((node) => node !== titleNode)\n const body = firstSection >= 0 ? nodes.slice(firstSection) : []\n\n // --- Hero -----------------------------------------------------------------\n const badges: ImageRef[] = []\n const lead: PhrasingContent[][] = []\n let heroImage: ImageRef | undefined\n let heroVariant: Hero[\"variant\"] = \"plain\"\n const intro: RootContent[] = []\n let leadOpen = true\n let leadWords = 0\n\n const coverUrl = asString(frontmatter.image) ?? asString(frontmatter.cover) ?? asString(frontmatter.banner)\n if (coverUrl) {\n const candidate: ImageRef = { src: coverUrl, alt: \"\", meta: ctx.images[coverUrl] ?? undefined }\n const variant = classifyHeroImage(candidate)\n if (variant) [heroImage, heroVariant] = [candidate, variant]\n }\n\n for (const node of preamble) {\n if (node.type === \"paragraph\") {\n const found = imagesOnly(node.children)\n if (found) {\n const refs = found.map((f) => imageRef(f, ctx))\n if (refs.every(isBadge)) {\n badges.push(...refs)\n continue\n }\n if (!heroImage && refs.length === 1 && ctx.judgements.heroImageUsable !== false) {\n const variant = classifyHeroImage(refs[0])\n if (variant) {\n ;[heroImage, heroVariant] = [refs[0], variant]\n continue\n }\n }\n } else if (leadOpen && lead.length < 2) {\n const words = countWords(toText(node))\n if (leadWords + words <= 70) {\n lead.push((node as Paragraph).children)\n leadWords += words\n continue\n }\n }\n }\n // The lead is the opening run of short paragraphs; anything else ends it.\n if (!(node.type === \"paragraph\" && imagesOnly(node.children))) leadOpen = false\n intro.push(node)\n }\n\n // A hero is never forced: without a title or an image fit to lead the page,\n // the opening paragraphs are simply the start of the text.\n const frontTitle = asString(frontmatter.title)\n const hasHero = !!titleNode || !!frontTitle || !!heroImage\n if (!hasHero) {\n intro.splice(0, intro.length, ...preamble)\n lead.length = 0\n badges.length = 0\n leadWords = 0\n }\n\n const description = asString(frontmatter.description) ?? asString(frontmatter.subtitle) ?? asString(frontmatter.summary)\n if (hasHero && description && !lead.length) lead.push([{ type: \"text\", value: description }])\n\n const title: PhrasingContent[] = titleNode?.children ?? (frontTitle ? [{ type: \"text\", value: frontTitle }] : [])\n const eyebrowParts = [asString(frontmatter.category), asString(frontmatter.author)]\n const date = frontmatter.date\n if (date instanceof Date) eyebrowParts.push(date.toISOString().slice(0, 10))\n else if (asString(date)) eyebrowParts.push(asString(date))\n\n const hero: Hero = {\n variant: heroImage ? heroVariant : \"plain\",\n title,\n titleText: toText(title).trim(),\n lead,\n image: heroImage,\n badges,\n eyebrow: (hasHero && eyebrowParts.filter(Boolean).join(\" · \")) || undefined,\n }\n\n // --- Sections ---------------------------------------------------------------\n const raws: RawSection[] = []\n if (intro.length) raws.push({ nodes: intro })\n for (const node of body) {\n if (node.type === \"heading\" && node.depth === sectionDepth) raws.push({ heading: node, nodes: [] })\n else raws[raws.length - 1].nodes.push(node)\n }\n const sections = raws.map((raw, index) => buildSection(raw, ctx, index))\n\n // Two tinted bands in a row would merge into one; keep the rhythm.\n for (let i = 1; i < sections.length; i++) {\n if (sections[i].tone === \"tint\" && sections[i - 1].tone === \"tint\") sections[i].tone = \"plain\"\n }\n\n // --- Navigation ---------------------------------------------------------------\n const toc: TocEntry[] = []\n for (const section of sections) {\n if (!section.titleText) continue\n toc.push({ id: section.id, text: section.titleText, depth: 0 })\n const subs: { id: string; text: string }[] = []\n for (const block of section.blocks) {\n if (block.kind === \"heading\" && block.depth === 1) subs.push({ id: block.id, text: toText(block.children) })\n if (block.kind === \"cards\") for (const item of block.items) subs.push({ id: item.id, text: toText(item.title) })\n }\n for (const sub of subs) toc.push({ ...sub, depth: 1 })\n }\n const titled = sections.filter((s) => s.titleText).length\n const words = sections.reduce((sum, s) => sum + s.words, 0) + leadWords\n\n return {\n hero,\n sections,\n toc: toc.length > 40 ? toc.filter((entry) => entry.depth === 0) : toc,\n showToc: titled >= 3,\n words,\n readingTime: Math.max(1, Math.round(words / 220)),\n }\n}\n","import { toText } from \"./analyze/text\"\nimport { describeTheme, themeList, themes } from \"./theme/themes\"\nimport type { DocumentPlan, Judgements, PaletteId, VizKind } from \"./types\"\n\n/**\n * Question shapes of a \"jev\"-compatible classifier endpoint: the request carries\n * a `state` (the text to judge) and named questions, each answered independently.\n */\nexport type ClassifierQuestion =\n | { type: \"choice\"; criteria: Record<string, string> }\n | { type: \"noul\"; criteria: { true: string; false: string } }\n | { type: \"score\"; criteria: string[] }\n\nexport type ClassifierRequest = {\n state: string\n questions: Record<string, ClassifierQuestion>\n}\n\nexport type ClassifierAnswer =\n | { type: \"choice\"; choice: string; confidence: number; probabilities?: Record<string, number> }\n | { type: \"noul\"; noul: number }\n | { type: \"score\"; score: number; confidence?: number }\n\nexport type ClassifierAnswers = Record<string, ClassifierAnswer>\n\n/** Anything that can answer a classifier request — usually a call to your own proxy route. */\nexport type Classify = (request: ClassifierRequest, signal?: AbortSignal) => Promise<ClassifierAnswers>\n\nconst cache = new Map<string, Promise<ClassifierAnswers>>()\n\n/**\n * A classifier that posts to `endpoint`. Point it at a route on your own server\n * that adds the API key (see `createClassifierHandler` in `stunning-md/server`) —\n * a key placed in browser code is public.\n */\nexport function createClassifier(options: { endpoint: string; headers?: Record<string, string> }): Classify {\n return (request) => {\n // Identical questions share one request, so it is never aborted on behalf of a single caller.\n const key = `${options.endpoint}\\n${JSON.stringify(request)}`\n const hit = cache.get(key)\n if (hit) return hit\n const pending = fetch(options.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...options.headers },\n body: JSON.stringify(request),\n }).then(async (response) => {\n if (!response.ok) throw new Error(`classifier responded ${response.status}`)\n const data = (await response.json()) as { answers?: ClassifierAnswers }\n if (!data.answers) throw new Error(\"classifier response has no answers\")\n return data.answers\n })\n cache.set(key, pending)\n pending.catch(() => cache.delete(key))\n return pending\n }\n}\n\n/** Viz forms that plot figures against each other, as opposed to listing them. */\nconst COMPARATIVE: VizKind[] = [\"bar\", \"line\", \"area\", \"donut\", \"scatter\", \"stats\"]\n\nconst COMPARE_QUESTION: ClassifierQuestion = {\n type: \"noul\",\n criteria: {\n true: \"the numbers are measurements meant to be compared with each other, ranked, or read as a trend\",\n false: \"the numbers are identifiers, codes, settings, prices or specifications that are looked up one at a time\",\n },\n}\n\nconst WHOLE_QUESTION: ClassifierQuestion = {\n type: \"noul\",\n criteria: {\n true: \"the rows are parts that together make up one whole, such as shares of a total or a budget breakdown\",\n false: \"the rows are independent items that do not add up to a meaningful whole\",\n },\n}\n\n/**\n * A compact summary of the document: enough for tone and topic, small enough to\n * be cheap. `prose` should be running text only — code and table cells mislead.\n */\nexport function documentDigest(plan: DocumentPlan, prose: string): string {\n const headings = plan.sections.map((s) => s.titleText).filter(Boolean).slice(0, 12)\n return [\n plan.hero.titleText && `Title: ${plan.hero.titleText}`,\n headings.length && `Sections: ${headings.join(\" | \")}`,\n `Excerpt: ${prose.replace(/\\s+/g, \" \").slice(0, 400)}`,\n ]\n .filter(Boolean)\n .join(\"\\n\")\n}\n\n/** How much probability a keyword match is worth when weighing the classifier's theme options. */\nconst HINT_WEIGHT = 0.25\n\nexport type JudgeOptions = {\n /** Minimum score before the classifier's theme is accepted over the keyword guess. */\n confidence?: number\n /** The theme the document's own keywords point to, if any (see `matchTheme`). */\n themeHint?: PaletteId\n /** Leave the theme question out — for a document whose theme is already settled. */\n skipTheme?: boolean\n /** Ask the theme question and nothing else. */\n themeOnly?: boolean\n /** What the document was written in answer to, if anything — it helps place the subject. */\n context?: string\n /** Requests in flight at once. Default 3. */\n concurrency?: number\n /** Upper bound on tables sent for a form judgement. */\n maxTables?: number\n signal?: AbortSignal\n /**\n * Called as each answer lands, with the judgements so far and what is still\n * outstanding: `\"theme\"`, `\"hero\"`, or the id of a data block.\n */\n onProgress?: (progress: JudgeProgress) => void\n}\n\nexport type JudgeProgress = { judgements: Judgements; pending: string[] }\n\n/**\n * Asks the classifier the questions structure cannot answer: which theme —\n * colours and typefaces together — suits the content, whether a table's numbers\n * are there to be compared or just looked up, and whether the leading image\n * deserves to be the hero.\n * Questions are asked top-down — theme, hero, then tables in document order —\n * so the top of the page settles first. A failed request simply leaves its\n * judgement unset.\n */\nexport async function judgeDocument(\n plan: DocumentPlan,\n prose: string,\n classify: Classify,\n options: JudgeOptions = {},\n): Promise<Judgements> {\n const threshold = options.confidence ?? 0.4\n const judgements: Judgements = {}\n // A few requests at a time, in order, so small classifier deployments are not\n // flooded by a document full of tables.\n const queue: (() => Promise<void>)[] = []\n const pending = new Set<string>()\n const report = () =>\n options.onProgress?.({ judgements: { ...judgements, viz: judgements.viz && { ...judgements.viz } }, pending: [...pending] })\n const attempt = (key: string, request: ClassifierRequest, apply: (answers: ClassifierAnswers) => void) => {\n pending.add(key)\n queue.push(() =>\n classify(request, options.signal)\n .then(apply, () => undefined)\n .then(() => {\n pending.delete(key)\n if (!options.signal?.aborted) report()\n }),\n )\n }\n\n // One question settles the whole look. Each option spells out the theme's\n // colours and typefaces as well as the content it suits.\n if (!options.skipTheme) attempt(\n \"theme\",\n {\n state: documentDigest(plan, prose) + (options.context ? `\\nWritten in answer to: ${options.context.replace(/\\s+/g, \" \").slice(0, 300)}` : \"\"),\n questions: { theme: { type: \"choice\", criteria: Object.fromEntries(themeList.map((t) => [t.id, describeTheme(t)])) } },\n },\n ({ theme }) => {\n if (theme?.type !== \"choice\") return\n // The document's own vocabulary counts as evidence too: it settles close\n // calls, but cannot overturn a classifier that is sure of itself.\n const odds: Record<string, number> = theme.probabilities ?? { [theme.choice]: theme.confidence }\n let best = \"\"\n let bestScore = 0\n for (const id of Object.keys(odds)) {\n const score = odds[id] + (id === options.themeHint ? HINT_WEIGHT : 0)\n if (id in themes && score > bestScore) [best, bestScore] = [id, score]\n }\n if (!best || bestScore < threshold) return\n const chosen = themes[best as PaletteId]\n judgements.theme = { palette: chosen.id, fonts: chosen.fonts, formality: chosen.formality }\n },\n )\n\n const image = plan.hero.image\n if (image && !options.themeOnly) {\n attempt(\n \"hero\",\n {\n state: [\n `Document: ${plan.hero.titleText}`,\n `First image — alt text: \"${image.alt}\", file: ${image.src.split(/[?#]/)[0].split(\"/\").pop()}`,\n image.meta && `size: ${image.meta.width}×${image.meta.height}px`,\n `Text right after it: ${toText(plan.hero.lead.flat()).slice(0, 200)}`,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n questions: {\n hero: {\n type: \"noul\",\n criteria: {\n true: \"the image is a logo, banner, cover photo or key visual that represents the whole document\",\n false: \"the image is a badge, screenshot, diagram, chart or incidental illustration that belongs in the body\",\n },\n },\n },\n },\n ({ hero }) => {\n // Only a clear \"no\" demotes the image; the structural checks already vouched for it.\n if (hero?.type === \"noul\" && hero.noul < 0.2) judgements.heroImageUsable = false\n },\n )\n }\n\n const tables = plan.sections\n .flatMap((section) =>\n section.blocks\n .flatMap((block) => (block.kind === \"cards\" ? block.items.flatMap((item) => item.blocks) : [block]))\n .flatMap((block) => (block.kind === \"data\" ? [{ section, block }] : [])),\n )\n .filter(({ block }) => block.viz.candidates.length > 1)\n .slice(0, options.themeOnly ? 0 : (options.maxTables ?? 8))\n\n for (const { section, block } of tables) {\n const { columns, rows } = block.table\n const { viz } = block\n if (!COMPARATIVE.includes(viz.kind)) continue\n const lines = [\n columns.map((c) => c.label).join(\" | \"),\n ...rows.slice(0, 12).map((row) => columns.map((c) => row.text[c.key]).join(\" | \")),\n ]\n // Whether numbers are measurements or mere reference values, and whether rows\n // form a whole, depends on what they mean — which the column types cannot say.\n const partsPossible = viz.candidates.includes(\"donut\") && viz.rowIndices.length >= 3\n attempt(\n block.id,\n {\n state: `Section: ${section.titleText || plan.hero.titleText}\\n${lines.join(\"\\n\")}`,\n questions: { compare: COMPARE_QUESTION, ...(partsPossible ? { whole: WHOLE_QUESTION } : {}) },\n },\n ({ compare, whole }) => {\n const set = (kind: VizKind) => ((judgements.viz ??= {})[block.id] = kind)\n if (compare?.type === \"noul\" && compare.noul < 0.12) return set(\"table\")\n if (whole?.type !== \"noul\") return\n if (whole.noul >= 0.9 && viz.kind !== \"donut\") set(\"donut\")\n else if (whole.noul <= 0.12 && viz.kind === \"donut\") set(\"bar\")\n },\n )\n }\n\n const worker = async () => {\n for (let task = queue.shift(); task; task = queue.shift()) {\n if (options.signal?.aborted) return\n await task()\n }\n }\n report()\n // The theme question is by far the heaviest and everything visible depends on\n // it, so it runs alone; the lighter questions then share the connection.\n await queue.shift()?.()\n await Promise.all(Array.from({ length: options.concurrency ?? 3 }, worker))\n return judgements\n}\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type CarouselApi } from \"@/components/ui/carousel\"\nimport { Dialog, DialogContent, DialogTitle } from \"@/components/ui/dialog\"\nimport { cn } from \"@/lib/utils\"\nimport type { ImageRef, MediaVariant } from \"../types\"\nimport { useStunning } from \"./context\"\nimport { safeUrl } from \"./flow\"\n\n/** Alt text doubles as a caption only when it reads like one. */\nexport function captionOf(image: ImageRef): string | undefined {\n if (image.title) return image.title\n const alt = image.alt.trim()\n return alt.split(/\\s+/).length >= 3 && !/\\.(png|jpe?g|gif|webp|svg)$/i.test(alt) ? alt : undefined\n}\n\nexport function Picture({\n image,\n className,\n eager,\n sizes,\n}: {\n image: ImageRef\n className?: string\n eager?: boolean\n sizes?: string\n}) {\n const { resolveUrl } = useStunning()\n const [broken, setBroken] = useState(false)\n const src = safeUrl(resolveUrl(image.src))\n if (!src || broken) {\n return image.alt ? <span className={cn(\"smd-image-missing\", className)}>{image.alt}</span> : null\n }\n return (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={src}\n alt={image.alt}\n width={image.meta?.width}\n height={image.meta?.height}\n loading={eager ? \"eager\" : \"lazy\"}\n decoding=\"async\"\n sizes={sizes}\n onError={() => setBroken(true)}\n className={className}\n />\n )\n}\n\nfunction Lightbox({ image, onClose }: { image: ImageRef | null; onClose: () => void }) {\n const { portal } = useStunning()\n return (\n <Dialog open={!!image} onOpenChange={(open) => !open && onClose()}>\n <DialogContent\n style={portal.style}\n className={cn(portal.className, \"w-auto max-w-[96vw] gap-2 p-2 sm:max-w-[min(96vw,1500px)]\")}\n >\n <DialogTitle className=\"sr-only\">{image?.alt || \"Image\"}</DialogTitle>\n {image && <Picture image={image} eager className=\"max-h-[86svh] w-auto max-w-full rounded-md object-contain\" />}\n {image && captionOf(image) && <p className=\"px-2 pb-1 text-center text-sm text-muted-foreground\">{captionOf(image)}</p>}\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction Zoomable({ image, onOpen, className, children }: { image: ImageRef; onOpen: (image: ImageRef) => void; className?: string; children: React.ReactNode }) {\n const href = image.href && safeUrl(image.href)\n if (href) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer noopener\" className={className}>\n {children}\n </a>\n )\n }\n return (\n <button type=\"button\" onClick={() => onOpen(image)} aria-label={`Enlarge image${image.alt ? `: ${image.alt}` : \"\"}`} className={cn(\"cursor-zoom-in\", className)}>\n {children}\n </button>\n )\n}\n\nfunction Slideshow({ images, onOpen }: { images: ImageRef[]; onOpen: (image: ImageRef) => void }) {\n const [api, setApi] = useState<CarouselApi>()\n const [index, setIndex] = useState(0)\n useEffect(() => {\n if (!api) return\n const update = () => setIndex(api.selectedScrollSnap())\n update()\n api.on(\"select\", update)\n return () => {\n api.off(\"select\", update)\n }\n }, [api])\n\n // Photographs fill the frame; small or tall images are shown whole.\n const landscape = images.filter((i) => i.meta && i.meta.width / i.meta.height >= 1.2 && i.meta.width >= 800).length\n const cover = landscape >= images.length * 0.6\n const caption = captionOf(images[index])\n\n return (\n <figure className=\"smd-media\">\n <Carousel setApi={setApi} opts={{ loop: images.length > 2 }} aria-label={`Slideshow of ${images.length} images`}>\n <CarouselContent className=\"ml-0\">\n {images.map((image, i) => (\n <CarouselItem key={i} className=\"pl-0\" aria-label={`${i + 1} of ${images.length}`}>\n <Zoomable image={image} onOpen={onOpen} className=\"block w-full\">\n <span className=\"smd-frame block aspect-[4/3] w-full overflow-hidden sm:aspect-[16/9]\">\n <Picture image={image} eager={i === 0} className={cn(\"size-full\", cover && image.meta && image.meta.width >= 800 ? \"object-cover\" : \"object-contain p-4\")} />\n </span>\n </Zoomable>\n </CarouselItem>\n ))}\n </CarouselContent>\n <CarouselPrevious className=\"left-3 bg-background/85 backdrop-blur\" />\n <CarouselNext className=\"right-3 bg-background/85 backdrop-blur\" />\n </Carousel>\n <figcaption className=\"flex items-start justify-between gap-4\">\n <span aria-live=\"polite\">{caption}</span>\n <span className=\"flex shrink-0 items-center gap-3\">\n <span className=\"flex gap-1.5\" role=\"tablist\" aria-label=\"Choose slide\">\n {images.length <= 12 &&\n images.map((_, i) => (\n <button\n key={i}\n type=\"button\"\n role=\"tab\"\n aria-selected={i === index}\n aria-label={`Slide ${i + 1}`}\n onClick={() => api?.scrollTo(i)}\n className={cn(\"h-1.5 rounded-full transition-all\", i === index ? \"w-5 bg-primary\" : \"w-1.5 bg-foreground/25 hover:bg-foreground/50\")}\n />\n ))}\n </span>\n <span className=\"tabular-nums\">\n {index + 1} / {images.length}\n </span>\n </span>\n </figcaption>\n </figure>\n )\n}\n\nexport function Media({ images, variant }: { images: ImageRef[]; variant: MediaVariant }) {\n const [open, setOpen] = useState<ImageRef | null>(null)\n let body: React.ReactNode\n\n if (variant === \"slideshow\") {\n body = <Slideshow images={images} onOpen={setOpen} />\n } else if (variant === \"pair\") {\n body = (\n <div className=\"smd-media grid gap-4 sm:grid-cols-2\">\n {images.map((image, i) => (\n <figure key={i}>\n <Zoomable image={image} onOpen={setOpen} className=\"block w-full\">\n <span className=\"smd-frame block aspect-[4/3] overflow-hidden\">\n <Picture image={image} className=\"size-full object-cover\" />\n </span>\n </Zoomable>\n {captionOf(image) && <figcaption>{captionOf(image)}</figcaption>}\n </figure>\n ))}\n </div>\n )\n } else {\n const image = images[0]\n const meta = image.meta\n // Small images keep their natural size instead of being blown up.\n const small = !!meta && meta.width < 560\n const tall = !!meta && meta.height > meta.width * 1.15\n body = (\n <figure className={cn(\"smd-media\", (small || tall) && \"mx-auto w-fit\")}>\n <Zoomable image={image} onOpen={setOpen} className=\"block\">\n <Picture\n image={image}\n className={cn(\"smd-frame h-auto max-w-full\", !small && !tall && \"w-full\", tall && \"max-h-[80svh] w-auto\")}\n />\n </Zoomable>\n {captionOf(image) && <figcaption>{captionOf(image)}</figcaption>}\n </figure>\n )\n }\n\n return (\n <>\n {body}\n <Lightbox image={open} onClose={() => setOpen(null)} />\n </>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\ntype CarouselProps = {\n opts?: CarouselOptions\n plugins?: CarouselPlugin\n orientation?: \"horizontal\" | \"vertical\"\n setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\n api: ReturnType<typeof useEmblaCarousel>[1]\n scrollPrev: () => void\n scrollNext: () => void\n canScrollPrev: boolean\n canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext)\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\")\n }\n\n return context\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n )\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\n const [canScrollNext, setCanScrollNext] = React.useState(false)\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return\n setCanScrollPrev(api.canScrollPrev())\n setCanScrollNext(api.canScrollNext())\n }, [])\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev()\n }, [api])\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext()\n }, [api])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault()\n scrollPrev()\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault()\n scrollNext()\n }\n },\n [scrollPrev, scrollNext]\n )\n\n React.useEffect(() => {\n if (!api || !setApi) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing with the carousel engine once it exists\n onSelect(api)\n api.on(\"reInit\", onSelect)\n api.on(\"select\", onSelect)\n\n return () => {\n api?.off(\"select\", onSelect)\n }\n }, [api, onSelect])\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute touch-manipulation rounded-full\",\n orientation === \"horizontal\"\n ? \"inset-y-0 -left-12 my-auto\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <ChevronLeftIcon />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute touch-manipulation rounded-full\",\n orientation === \"horizontal\"\n ? \"inset-y-0 -right-12 my-auto\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <ChevronRightIcon />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n useCarousel,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\nimport { cn } from \"@/lib/utils\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Dialog({ ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />\n}\n\nfunction DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />\n}\n\nfunction DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />\n}\n\nfunction DialogClose({ ...props }: DialogPrimitive.Close.Props) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\n \"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: DialogPrimitive.Popup.Props & {\n showCloseButton?: boolean\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n \"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-2 right-2\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n )\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nfunction DialogFooter({\n className,\n showCloseButton = false,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showCloseButton?: boolean\n}) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close render={<Button variant=\"outline\" />}>\n Close\n </DialogPrimitive.Close>\n )}\n </div>\n )\n}\n\nfunction DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\n \"font-heading text-base leading-none font-medium\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: DialogPrimitive.Description.Props) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\n \"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n}\n","\"use client\"\n\nimport { themes } from \"../theme/themes\"\nimport type { DocumentPlan } from \"../types\"\nimport { useStunning } from \"./context\"\nimport { Inline, safeUrl } from \"./flow\"\nimport { Picture } from \"./media\"\n\nexport function HeroView({ plan, id = \"top\" }: { plan: DocumentPlan; id?: string }) {\n const { resolveUrl, theme } = useStunning()\n const { hero } = plan\n if (!hero.titleText && !hero.lead.length && !hero.image) return null\n\n const sections = plan.sections.filter((s) => s.titleText).length\n const meta = [plan.words >= 150 && `${plan.readingTime} min read`, sections >= 3 && `${sections} sections`].filter(Boolean).join(\" · \")\n\n const badges = hero.badges.length > 0 && (\n <p className=\"smd-badges\">\n {hero.badges.map((badge, index) => {\n const src = safeUrl(resolveUrl(badge.src))\n if (!src) return null\n // eslint-disable-next-line @next/next/no-img-element\n const image = <img src={src} alt={badge.alt} loading=\"lazy\" />\n const href = badge.href && safeUrl(badge.href)\n return href ? (\n <a key={index} href={href} target=\"_blank\" rel=\"noreferrer noopener\">\n {image}\n </a>\n ) : (\n <span key={index}>{image}</span>\n )\n })}\n </p>\n )\n\n const text = (\n <div className=\"smd-hero-text\">\n {hero.variant === \"logo\" && hero.image && <Picture image={hero.image} eager className=\"smd-hero-logo\" />}\n {hero.eyebrow && <p className=\"smd-eyebrow\">{hero.eyebrow}</p>}\n {hero.titleText && (\n <h1 className=\"smd-display\">\n <Inline nodes={hero.title} />\n </h1>\n )}\n {hero.lead.map((paragraph, index) => (\n <p key={index} className=\"smd-lead\">\n <Inline nodes={paragraph} />\n </p>\n ))}\n {meta && <p className=\"smd-hero-meta\">{meta}</p>}\n {badges}\n </div>\n )\n\n return (\n <header\n className=\"smd-hero\"\n data-variant={hero.variant}\n // A cover is for a hero led by its text; a photograph is its own cover, and a logo is drawn for the page behind it.\n data-tone={hero.variant === \"plain\" || hero.variant === \"figure\" ? themes[theme.palette].hero : undefined}\n id={id}\n >\n {hero.variant === \"banner\" && hero.image && (\n <>\n <Picture image={hero.image} eager className=\"smd-cover\" />\n <div className=\"smd-scrim\" aria-hidden />\n </>\n )}\n <div className=\"smd-container smd-hero-inner\">\n {text}\n {hero.variant === \"figure\" && hero.image && (\n <div className=\"smd-hero-figure\">\n <Picture image={hero.image} eager className=\"smd-frame h-auto w-full\" />\n </div>\n )}\n </div>\n </header>\n )\n}\n","\"use client\"\n\nimport type { Root, Table } from \"mdast\"\nimport { toText } from \"../analyze/text\"\nimport type { TocEntry } from \"../types\"\nimport { CopyButton } from \"./code-block\"\nimport { FlowNode, Inline } from \"./flow\"\n\nfunction PlainTable({ node }: { node: Table }) {\n const [head, ...body] = node.children\n const align = (index: number) => node.align?.[index] ?? undefined\n return (\n <div className=\"smd-plain-table\">\n <table>\n {head && (\n <thead>\n <tr>\n {head.children.map((cell, c) => (\n <th key={c} scope=\"col\" style={{ textAlign: align(c) }}>\n <Inline nodes={cell.children} />\n </th>\n ))}\n </tr>\n </thead>\n )}\n <tbody>\n {body.map((row, r) => (\n <tr key={r}>\n {row.children.map((cell, c) => (\n <td key={c} style={{ textAlign: align(c) }}>\n <Inline nodes={cell.children} />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\n/**\n * The document as an ordinary markdown renderer would show it: one column,\n * headings as written, tables as tables, images where they fall. Headings keep\n * the ids used by the contents list, so navigation works in either view.\n */\nexport function PlainDocument({ root, toc }: { root: Root; toc: TocEntry[] }) {\n const remaining = [...toc]\n return (\n <div className=\"smd-plain\">\n {root.children.map((node, index) => {\n if (node.type === \"heading\") {\n const text = toText(node).trim()\n const match = remaining.findIndex((entry) => entry.text.trim() === text)\n const id = match >= 0 ? remaining.splice(0, match + 1)[match].id : undefined\n const Tag = `h${node.depth}` as \"h1\"\n return (\n <Tag key={index} id={id}>\n <Inline nodes={node.children} />\n </Tag>\n )\n }\n if (node.type === \"table\") return <PlainTable key={index} node={node} />\n return <FlowNode key={index} node={node} />\n })}\n </div>\n )\n}\n\n/**\n * The markdown exactly as written — and, when `onChange` is given, editable in\n * place. The field grows with its content: a hidden copy of the text sizes the\n * box and the textarea is laid over it.\n */\nexport function SourceView({ value, onChange }: { value: string; onChange?: (value: string) => void }) {\n return (\n <div className=\"smd-source\">\n <div className=\"smd-source-tools\">\n {onChange && <p>Edit the text, then switch view to see it rendered.</p>}\n <CopyButton text={() => value} label=\"Copy markdown\" />\n </div>\n {onChange ? (\n <div className=\"smd-source-edit\" data-value={value}>\n <textarea\n value={value}\n onChange={(event) => onChange(event.target.value)}\n aria-label=\"Edit markdown\"\n spellCheck={false}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n />\n </div>\n ) : (\n <pre tabIndex={0}>{value}</pre>\n )}\n </div>\n )\n}\n","\"use client\"\n\nimport { CheckIcon, EllipsisIcon } from \"lucide-react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { cn } from \"@/lib/utils\"\nimport type { Section, SectionLayout } from \"../types\"\nimport { Blocks } from \"./blocks\"\nimport { useStunning } from \"./context\"\nimport { Inline } from \"./flow\"\nimport { captionOf, Picture } from \"./media\"\n\nexport const LAYOUT_LABEL: Record<SectionLayout, { name: string; hint: string }> = {\n prose: { name: \"Article\", hint: \"Heading beside a reading column\" },\n statement: { name: \"Statement\", hint: \"Large, centred, room to breathe\" },\n split: { name: \"Side by side\", hint: \"Text next to the image\" },\n fullbleed: { name: \"Full-screen image\", hint: \"Text over the image\" },\n cards: { name: \"Cards\", hint: \"Sub-sections as a grid\" },\n showcase: { name: \"Showcase\", hint: \"Images lead, text follows\" },\n quote: { name: \"Quotation\", hint: \"One highlighted quote\" },\n}\n\nfunction LayoutMenu({ section }: { section: Section }) {\n const { portal, setLayout } = useStunning()\n return (\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"smd-section-menu\"\n aria-label={`Change layout of ${section.titleText || \"this section\"}`}\n title=\"Change layout\"\n />\n }\n >\n <EllipsisIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"w-64\")}>\n <DropdownMenuGroup>\n <DropdownMenuLabel>Section layout</DropdownMenuLabel>\n {section.alternatives.map((layout) => (\n <DropdownMenuItem key={layout} onClick={() => setLayout(section.id, layout)} className=\"items-start\">\n <span className=\"flex flex-col\">\n <span className=\"font-medium\">{LAYOUT_LABEL[layout].name}</span>\n <span className=\"text-xs text-muted-foreground\">{LAYOUT_LABEL[layout].hint}</span>\n </span>\n {layout === section.layout && <CheckIcon className=\"mt-0.5 ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nexport function SectionView({ section }: { section: Section }) {\n const { controls } = useStunning()\n const headingId = `${section.id}-title`\n const heading = section.titleText ? (\n <h2 id={headingId} className=\"smd-h2\">\n <Inline nodes={section.title} />\n </h2>\n ) : null\n const flow = section.blocks.length > 0 && (\n <div className=\"smd-flow\">\n <Blocks blocks={section.blocks} />\n </div>\n )\n\n let body: React.ReactNode\n switch (section.layout) {\n case \"statement\":\n case \"quote\":\n body = (\n <div className=\"smd-container smd-center\">\n {heading}\n {flow}\n </div>\n )\n break\n case \"split\":\n body = (\n <div className=\"smd-container smd-split\" data-flip={section.flip || undefined}>\n <div className=\"smd-split-text\">\n {heading}\n {flow}\n </div>\n {section.feature && (\n <figure className=\"smd-split-media\">\n <Picture image={section.feature} className=\"smd-frame h-auto w-full\" />\n {captionOf(section.feature) && <figcaption>{captionOf(section.feature)}</figcaption>}\n </figure>\n )}\n </div>\n )\n break\n case \"fullbleed\":\n body = (\n <>\n {section.feature && <Picture image={section.feature} className=\"smd-cover\" />}\n <div className=\"smd-scrim\" aria-hidden />\n <div className=\"smd-container smd-over\">\n {heading}\n {flow}\n </div>\n </>\n )\n break\n case \"cards\":\n case \"showcase\":\n body = (\n <div className=\"smd-container smd-stack\">\n {heading}\n {flow}\n </div>\n )\n break\n default:\n body = (\n <div className={cn(\"smd-container\", heading ? \"smd-prose-grid\" : \"smd-prose-solo\")}>\n {heading && <header>{heading}</header>}\n {flow}\n </div>\n )\n }\n\n return (\n <section\n id={section.id}\n aria-labelledby={heading ? headingId : undefined}\n aria-label={heading ? undefined : \"Introduction\"}\n className=\"smd-section\"\n data-layout={section.layout}\n data-tone={section.tone}\n data-intro={heading ? undefined : \"\"}\n >\n {controls && section.alternatives.length > 1 && <LayoutMenu section={section} />}\n {body}\n </section>\n )\n}\n","\"use client\"\n\nimport { AlertTriangleIcon, InfoIcon, LightbulbIcon, OctagonAlertIcon, MessageSquareWarningIcon } from \"lucide-react\"\nimport type { Block } from \"../types\"\nimport { CodeBlock } from \"./code-block\"\nimport { DataBlock } from \"./data-block\"\nimport { Flow, FlowNode, Inline, ItemBody } from \"./flow\"\nimport { Media } from \"./media\"\n\nconst CALLOUTS: Record<string, { label: string; icon: typeof InfoIcon }> = {\n note: { label: \"Note\", icon: InfoIcon },\n tip: { label: \"Tip\", icon: LightbulbIcon },\n important: { label: \"Important\", icon: MessageSquareWarningIcon },\n warning: { label: \"Warning\", icon: AlertTriangleIcon },\n caution: { label: \"Caution\", icon: OctagonAlertIcon },\n}\n\nfunction BlockView({ block }: { block: Block }) {\n switch (block.kind) {\n case \"content\":\n return <FlowNode node={block.node} />\n case \"heading\": {\n const Tag = `h${Math.min(6, block.depth + 2)}` as \"h3\"\n return (\n <Tag id={block.id} className=\"smd-subheading\" data-depth={block.depth}>\n <Inline nodes={block.children} />\n </Tag>\n )\n }\n case \"list\": {\n if (block.variant !== \"feature\") return <FlowNode node={block.node} />\n const Tag = block.node.ordered ? \"ol\" : \"ul\"\n return (\n <Tag className=\"smd-list-feature\" data-columns={block.columns} start={block.node.ordered ? (block.node.start ?? undefined) : undefined}>\n {block.node.children.map((item, index) => (\n <li key={index}>\n <span className=\"smd-list-marker\" aria-hidden>\n {block.node.ordered ? String((block.node.start ?? 1) + index).padStart(2, \"0\") : \"\"}\n </span>\n <div>\n <ItemBody nodes={item.children} />\n </div>\n </li>\n ))}\n </Tag>\n )\n }\n case \"quote\": {\n if (block.variant === \"callout\") {\n const callout = CALLOUTS[block.calloutType ?? \"note\"] ?? CALLOUTS.note\n return (\n <aside className=\"smd-callout\" data-type={block.calloutType}>\n <p className=\"smd-callout-label\">\n <callout.icon aria-hidden />\n {callout.label}\n </p>\n <Flow nodes={block.children} />\n </aside>\n )\n }\n return (\n <figure className={block.variant === \"pull\" ? \"smd-pull\" : \"smd-aside\"}>\n <blockquote>\n <Flow nodes={block.children} />\n </blockquote>\n {block.attribution && <figcaption>{block.attribution}</figcaption>}\n </figure>\n )\n }\n case \"code\":\n return <CodeBlock lang={block.lang} value={block.value} />\n case \"media\":\n return <Media images={block.images} variant={block.variant} />\n case \"data\":\n return <DataBlock id={block.id} table={block.table} viz={block.viz} />\n case \"cards\":\n return (\n <div className=\"smd-cards\" data-count={block.items.length}>\n {block.items.map((item, index) => (\n <article key={item.id} id={item.id} className=\"smd-card\">\n <span className=\"smd-card-index\" aria-hidden>\n {String(index + 1).padStart(2, \"0\")}\n </span>\n <h3>\n <Inline nodes={item.title} />\n </h3>\n <div className=\"smd-flow\">\n <Blocks blocks={item.blocks} />\n </div>\n </article>\n ))}\n </div>\n )\n case \"rule\":\n return <hr className=\"smd-rule\" />\n }\n}\n\nexport function Blocks({ blocks }: { blocks: Block[] }) {\n return (\n <>\n {blocks.map((block, index) => (\n <BlockView key={index} block={block} />\n ))}\n </>\n )\n}\n","\"use client\"\n\nimport { AreaChart, BarChart, LineChart, PieChart, ScatterChart, type Series } from \"generative-charts\"\nimport { ChartNoAxesColumnIcon, CheckIcon, Table2Icon } from \"lucide-react\"\nimport { Button } from \"@/components/ui/button\"\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from \"@/components/ui/dropdown-menu\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/components/ui/popover\"\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"@/components/ui/table\"\nimport { cn } from \"@/lib/utils\"\nimport { formatValue } from \"../analyze/tables\"\nimport type { ChartSpec, TableModel, VizKind, VizPlan } from \"../types\"\nimport { CopyButton } from \"./code-block\"\nimport { useStunning } from \"./context\"\nimport { Inline } from \"./flow\"\n\nconst VIZ_LABEL: Record<VizKind, string> = {\n table: \"Table\",\n bar: \"Bar chart\",\n line: \"Line chart\",\n area: \"Area chart\",\n donut: \"Donut chart\",\n scatter: \"Scatter plot\",\n stats: \"Key figures\",\n timeline: \"Timeline\",\n facts: \"Fact sheet\",\n}\n\n/** Tab-separated text — pastes straight into a spreadsheet. */\nexport function toTsv(table: TableModel): string {\n const clean = (text: string) => text.replace(/[\\t\\n\\r]+/g, \" \").trim()\n return [\n table.columns.map((c) => clean(c.label)).join(\"\\t\"),\n ...table.rows.map((row) => table.columns.map((c) => clean(row.text[c.key])).join(\"\\t\")),\n ].join(\"\\n\")\n}\n\nexport function DataTable({ table, dense }: { table: TableModel; dense?: boolean }) {\n // Give each column room in proportion to its content, so a narrow screen scrolls instead of crushing prose.\n const minWidth = (key: string) => {\n const longest = Math.max(0, ...table.rows.map((row) => row.text[key].length))\n return `${Math.min(24, Math.max(3, Math.round(longest * 0.55)))}ch`\n }\n const alignClass = (align: string) => (align === \"right\" ? \"text-right tabular-nums\" : align === \"center\" ? \"text-center\" : \"text-left\")\n return (\n <Table className={cn(\"smd-table\", dense && \"text-[0.8125rem]\")}>\n <TableHeader>\n <TableRow>\n {table.columns.map((column) => (\n <TableHead key={column.key} scope=\"col\" className={alignClass(column.align)}>\n {column.label}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {table.rows.map((row, r) => (\n <TableRow key={r}>\n {table.columns.map((column, c) => (\n <TableCell key={column.key} className={cn(alignClass(column.align), \"whitespace-normal\")} style={r === 0 ? { minWidth: minWidth(column.key) } : undefined}>\n <Inline nodes={row.cells[c]} />\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )\n}\n\n/** The most characters a category name can have and still fit beside a horizontal bar in the chart library's plot. */\nconst AXIS_LABEL_FITS = 16\n\n/**\n * Ranked bars for categories with long names. A plot has a fixed gutter for\n * its labels and cuts off what does not fit; here each name gets the full\n * width above its bar, and wraps.\n */\nfunction BarList({ table, viz, spec }: { table: TableModel; viz: VizPlan; spec: ChartSpec }) {\n const { chartTheme, appearance } = useStunning()\n const tokens = chartTheme.modes[appearance]\n const measure = table.columns.find((c) => c.key === spec.seriesKeys[0])!\n const labelIndex = table.columns.findIndex((c) => c.key === viz.labelKey)\n const values = viz.rowIndices.map((r) => table.rows[r].value[measure.key] as number | null)\n const peak = Math.max(0, ...values.map((v) => Math.abs(v ?? 0)))\n const style = {\n \"--smd-bar\": tokens.palette[0],\n \"--smd-bar-negative\": tokens.negative,\n \"--smd-bar-radius\": `${tokens.markRadius}px`,\n } as React.CSSProperties\n return (\n <div className=\"smd-barlist\" style={style} data-style={chartTheme.id === \"mono-editorial\" ? \"linework\" : undefined}>\n <p className=\"smd-barlist-caption\">\n <span>{table.columns[labelIndex]?.label}</span>\n <span>{measure.label}</span>\n </p>\n {/* Not a list element: the document's own list styling — numbers, markers — has no place here. */}\n <div className=\"smd-barlist-rows\" role=\"list\">\n {viz.rowIndices.map((r, i) => {\n const value = values[i]\n return (\n <div key={r} role=\"listitem\">\n <div className=\"smd-barlist-row\">\n <span>{labelIndex >= 0 ? <Inline nodes={table.rows[r].cells[labelIndex]} /> : String(r + 1)}</span>\n <span className=\"smd-barlist-value\">{value == null ? \"—\" : formatValue(value, spec.unit)}</span>\n </div>\n <div className=\"smd-barlist-track\" aria-hidden>\n {value != null && peak > 0 && <div data-negative={value < 0 || undefined} style={{ width: `${(Math.abs(value) / peak) * 100}%` }} />}\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\nfunction Chart({ table, viz, spec, titled }: { table: TableModel; viz: VizPlan; spec: ChartSpec; titled: boolean }) {\n const { chartTheme, appearance } = useStunning()\n const columnOf = (key: string) => table.columns.find((c) => c.key === key)!\n const labelColumn = viz.labelKey ? columnOf(viz.labelKey) : undefined\n const series: Series[] = spec.seriesKeys.map((key) => ({ dataKey: key, label: columnOf(key).label }))\n const data = viz.rowIndices.map((r) => {\n const row = table.rows[r]\n const datum: Record<string, unknown> = { label: labelColumn ? row.text[labelColumn.key] : String(r + 1) }\n for (const key of spec.seriesKeys) datum[key] = row.value[key]\n if (viz.kind === \"scatter\" && labelColumn) datum.x = row.value[labelColumn.key]\n return datum\n })\n const names = series.map((s) => s.label).join(\", \")\n const common = {\n data,\n theme: chartTheme,\n appearance,\n title: titled ? names : undefined,\n figureLabel: \"\",\n ariaLabel: `${VIZ_LABEL[viz.kind]} of ${names}${labelColumn ? ` by ${labelColumn.label}` : \"\"}`,\n valueFormatter: (value: number) => formatValue(value, spec.unit),\n showLegend: series.length > 1,\n }\n\n switch (viz.kind) {\n case \"line\":\n return <LineChart {...common} xKey=\"label\" series={series} showPoints={data.length <= 24} height={340} />\n case \"area\":\n return <AreaChart {...common} xKey=\"label\" series={series} height={340} />\n case \"donut\":\n return <PieChart {...common} showLegend nameKey=\"label\" valueKey={spec.seriesKeys[0]} variant=\"donut\" height={340} />\n case \"scatter\":\n return <ScatterChart {...common} xKey=\"x\" series={series} height={360} />\n default:\n if (viz.horizontal && series.length === 1 && data.some((datum) => String(datum.label).length > AXIS_LABEL_FITS)) {\n return <BarList table={table} viz={viz} spec={spec} />\n }\n return (\n <BarChart\n {...common}\n categoryKey=\"label\"\n series={series}\n variant={viz.horizontal ? \"horizontal\" : \"vertical\"}\n height={viz.horizontal ? Math.max(260, data.length * 34 + 90) : 340}\n />\n )\n }\n}\n\nfunction Stats({ table, viz }: { table: TableModel; viz: VizPlan }) {\n const keys = viz.charts[0]?.seriesKeys ?? []\n const tiles =\n table.rows.length === 1\n ? keys.map((key) => ({ label: table.columns.find((c) => c.key === key)!.label, value: table.rows[0].text[key] }))\n : viz.rowIndices.map((r) => ({ label: table.rows[r].text[viz.labelKey ?? \"\"], value: table.rows[r].text[keys[0]] }))\n return (\n <dl className=\"smd-stats\">\n {tiles.map((tile, i) => (\n <div key={i}>\n <dd>{tile.value}</dd>\n <dt>{tile.label}</dt>\n </div>\n ))}\n </dl>\n )\n}\n\nfunction Timeline({ table, viz }: { table: TableModel; viz: VizPlan }) {\n const dateIndex = table.columns.findIndex((c) => c.key === viz.labelKey)\n const rest = table.columns.map((column, index) => ({ column, index })).filter(({ index }) => index !== dateIndex)\n return (\n <ol className=\"smd-timeline\">\n {viz.rowIndices.map((r) => {\n const row = table.rows[r]\n const filled = rest.filter(({ column }) => row.text[column.key])\n // The first descriptive column names the event; figures and the rest are details.\n const head = filled.find(({ column }) => column.type === \"text\") ?? filled[0]\n const details = filled.filter((entry) => entry !== head)\n return (\n <li key={r}>\n <time>{row.text[table.columns[dateIndex].key]}</time>\n <div>\n {head && (\n <p className=\"smd-timeline-title\">\n <Inline nodes={row.cells[head.index]} />\n </p>\n )}\n {details.map(({ column, index }) => (\n <p key={column.key}>\n {(details.length > 1 || column.type !== \"text\") && <span className=\"smd-timeline-key\">{column.label}: </span>}\n <Inline nodes={row.cells[index]} />\n </p>\n ))}\n </div>\n </li>\n )\n })}\n </ol>\n )\n}\n\nfunction Facts({ table }: { table: TableModel }) {\n return (\n <dl className=\"smd-facts\">\n {table.rows.map((row, r) => (\n <div key={r}>\n <dt>\n <Inline nodes={row.cells[0]} />\n </dt>\n <dd>\n <Inline nodes={row.cells[1]} />\n </dd>\n </div>\n ))}\n </dl>\n )\n}\n\nexport function DataBlock({ id, table, viz }: { id: string; table: TableModel; viz: VizPlan }) {\n const { portal, controls, setViz } = useStunning()\n const isTable = viz.kind === \"table\"\n const multiple = viz.charts.length > 1\n\n let body: React.ReactNode\n if (isTable) body = <div className=\"smd-table-scroll\">{<DataTable table={table} />}</div>\n else if (viz.kind === \"stats\") body = <Stats table={table} viz={viz} />\n else if (viz.kind === \"timeline\") body = <Timeline table={table} viz={viz} />\n else if (viz.kind === \"facts\") body = <Facts table={table} />\n else {\n body = (\n <div className={cn(\"grid gap-6\", multiple && \"xl:grid-cols-2\")}>\n {viz.charts.map((spec) => (\n <div key={spec.seriesKeys.join()} className=\"smd-chart min-w-0\" data-multi={spec.seriesKeys.length > 1 || undefined}>\n <Chart table={table} viz={viz} spec={spec} titled={multiple} />\n </div>\n ))}\n </div>\n )\n }\n\n return (\n <figure className=\"smd-data\" data-viz={viz.kind} data-block-id={id}>\n <div className=\"smd-data-tools\">\n {controls && viz.candidates.length > 1 && (\n <DropdownMenu>\n <DropdownMenuTrigger render={<Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground\" aria-label=\"Change how this data is shown\" title=\"Change form\" />}>\n <ChartNoAxesColumnIcon />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" style={portal.style} className={cn(portal.className, \"w-44\")}>\n <DropdownMenuGroup>\n <DropdownMenuLabel>Show as</DropdownMenuLabel>\n {viz.candidates.map((kind) => (\n <DropdownMenuItem key={kind} onClick={() => setViz(id, kind)}>\n {VIZ_LABEL[kind]}\n {kind === viz.kind && <CheckIcon className=\"ml-auto\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n {!isTable && (\n <Popover>\n <PopoverTrigger render={<Button variant=\"ghost\" size=\"icon-sm\" className=\"text-muted-foreground\" aria-label=\"View the underlying data table\" title=\"View data\" />}>\n <Table2Icon />\n </PopoverTrigger>\n <PopoverContent align=\"end\" style={portal.style} className={cn(portal.className, \"max-h-[70svh] w-[min(92vw,44rem)] overflow-auto p-0\")}>\n <div className=\"sticky top-0 z-10 flex items-center justify-between border-b bg-popover px-3 py-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {table.rows.length} rows × {table.columns.length} columns\n </span>\n <CopyButton text={() => toTsv(table)} label=\"Copy table for spreadsheets\" />\n </div>\n <DataTable table={table} dense />\n </PopoverContent>\n </Popover>\n )}\n {isTable && <CopyButton text={() => toTsv(table)} label=\"Copy table for spreadsheets\" />}\n </div>\n {body}\n </figure>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Popover({ ...props }: PopoverPrimitive.Root.Props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({ ...props }: PopoverPrimitive.Trigger.Props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n ...props\n}: PopoverPrimitive.Popup.Props &\n Pick<\n PopoverPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <PopoverPrimitive.Popup\n data-slot=\"popover-content\"\n className={cn(\n \"z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-0.5 text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {\n return (\n <PopoverPrimitive.Title\n data-slot=\"popover-title\"\n className={cn(\"font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: PopoverPrimitive.Description.Props) {\n return (\n <PopoverPrimitive.Description\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverContent,\n PopoverDescription,\n PopoverHeader,\n PopoverTitle,\n PopoverTrigger,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({ className, ...props }: React.ComponentProps<\"table\">) {\n return (\n <div\n data-slot=\"table-container\"\n className=\"relative w-full overflow-x-auto\"\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<\"thead\">) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\"[&_tr]:border-b\", className)}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({ className, ...props }: React.ComponentProps<\"th\">) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({ className, ...props }: React.ComponentProps<\"td\">) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","\"use client\"\n\nimport { useCallback, useEffect, useRef, useState } from \"react\"\nimport { CHAT_INSTRUCTIONS, documentContext, sortReply, wantsContent, type Chat, type ChatMessage } from \"../chat\"\nimport type { Classify } from \"../classifier\"\n\n/** The content of one assistant reply, as it accumulates. */\nexport type ChatTurn = {\n id: string\n /** The answer so far — complete sections only, commentary removed. */\n markdown: string\n streaming: boolean\n /** Nothing has come back from the model yet. */\n waiting: boolean\n /** The section being written right now. */\n writing: string | null\n /** What the reader asked for. */\n request: string\n /**\n * The turn has no place on the page: the message was only conversation, or the\n * model opened without an answer. Content, if any follows, gives it one.\n */\n unanswered: boolean\n}\n\n/** One entry in the conversation, in the order it happened. */\nexport type StreamItem =\n | { id: string; type: \"user\"; text: string }\n | { id: string; type: \"commentary\"; text: string; failed?: boolean }\n /** Stands for a turn's content, which is on the page rather than in the conversation. */\n | { id: string; type: \"contents\"; turnId: string }\n\nexport type ChatNote = { id: string; text: string }\n\n/**\n * Longest the page waits to hear whether a message asks for content before\n * making room for the answer anyway, in ms.\n */\nconst PROMPT_PATIENCE = 1500\n\n/** How long a remark stays above the input before it fades, in ms. */\nconst NOTE_LIFETIME = 7000\n\n/**\n * A conversation whose answers become page content. Each reply is sorted as it\n * streams: remarks go to the conversation (and briefly above the input), and\n * the answer itself is handed to the page a section at a time.\n */\nexport function useChatSession(options: {\n chat?: Chat\n classifier?: Classify\n document: string\n /** A turn has a place on the page and is about to be written. */\n onTurnStart?: (turnId: string) => void\n /** A turn turned out to have nothing for the page; its place is given up. */\n onTurnEmpty?: (turnId: string) => void\n}) {\n const { chat, classifier, document, onTurnStart, onTurnEmpty } = options\n const [turns, setTurns] = useState<ChatTurn[]>([])\n const [items, setItems] = useState<StreamItem[]>([])\n const [notes, setNotes] = useState<ChatNote[]>([])\n const [busy, setBusy] = useState(false)\n\n const history = useRef<ChatMessage[]>([])\n const counter = useRef(0)\n const abort = useRef<AbortController | null>(null)\n const timers = useRef(new Set<ReturnType<typeof setTimeout>>())\n\n useEffect(() => {\n const pending = timers.current\n return () => {\n abort.current?.abort()\n for (const timer of pending) clearTimeout(timer)\n }\n }, [])\n\n const send = useCallback(\n (text: string) => {\n const request = text.trim()\n if (!chat || !request || abort.current) return\n const turnId = `t${++counter.current}`\n const controller = new AbortController()\n abort.current = controller\n let sequence = 0\n let referenced = false\n // Whether the turn has a place on the page, and whether that place has since been given up.\n let placed = false\n let vacated = false\n\n const patch = (change: Partial<ChatTurn>) => setTurns((all) => all.map((turn) => (turn.id === turnId ? { ...turn, ...change } : turn)))\n const remark = (remarkText: string, failed = false) => {\n const id = `${turnId}-c${++sequence}`\n setItems((all) => [...all, { id, type: \"commentary\", text: remarkText, failed }])\n setNotes((all) => [...all.slice(-1), { id, text: remarkText }])\n const timer = setTimeout(() => {\n timers.current.delete(timer)\n setNotes((all) => all.filter((note) => note.id !== id))\n }, NOTE_LIFETIME)\n timers.current.add(timer)\n }\n\n // Room is made on the page once the message is known to ask for something —\n // or the answer shows that it did. Small talk never gets any.\n const place = () => {\n if (placed || controller.signal.aborted) return\n placed = true\n vacated = false\n patch({ unanswered: false })\n onTurnStart?.(turnId)\n }\n const vacate = () => {\n if (!placed || vacated) return\n vacated = true\n patch({ unanswered: true })\n onTurnEmpty?.(turnId)\n }\n\n setBusy(true)\n setItems((all) => [...all, { id: `${turnId}-u`, type: \"user\", text: request }])\n setTurns((all) => [...all, { id: turnId, markdown: \"\", streaming: true, waiting: true, writing: null, request, unanswered: true }])\n\n // A slow classifier must not hold the page back: without word in time, assume content is wanted.\n const asksForContent = Promise.race([\n wantsContent(request, classifier, controller.signal),\n new Promise<boolean>((resolve) => setTimeout(() => resolve(true), PROMPT_PATIENCE)),\n ])\n asksForContent.then((wanted) => wanted && place())\n\n const messages: ChatMessage[] = [{ role: \"system\", content: CHAT_INSTRUCTIONS + documentContext(document) }, ...history.current, { role: \"user\", content: request }]\n\n // The first text to come back ends the wait, well before a whole paragraph is ready to be sorted.\n const reply = chat(messages, controller.signal)\n const heard = (async function* () {\n let first = true\n for await (const chunk of reply) {\n if (first && chunk) {\n first = false\n patch({ waiting: false })\n }\n yield chunk\n }\n })()\n\n sortReply({\n stream: heard,\n request,\n smallTalk: asksForContent.then((wanted) => !wanted),\n classify: classifier,\n signal: controller.signal,\n onEvent: (event) => {\n if (controller.signal.aborted) return\n if (event.type === \"commentary\") remark(event.text)\n else if (event.type === \"writing\") patch({ writing: event.heading })\n else if (event.type === \"answer\") {\n if (event.answered) {\n placed = false\n place()\n } else vacate()\n } else {\n place()\n // The content lives on the page; the conversation only points to it.\n if (!referenced) {\n referenced = true\n setItems((all) => [...all, { id: `${turnId}-r`, type: \"contents\", turnId }])\n }\n patch({ markdown: event.markdown })\n }\n },\n })\n .then(\n (result) => {\n if (result.raw.trim()) history.current.push({ role: \"user\", content: request }, { role: \"assistant\", content: result.raw })\n },\n (error: unknown) => {\n if (!controller.signal.aborted) remark(`The chat request failed. ${error instanceof Error ? error.message : \"\"}`.trim(), true)\n },\n )\n .finally(() => {\n if (abort.current === controller) abort.current = null\n patch({ streaming: false, waiting: false, writing: null })\n // A reply that was all conversation leaves nothing on the page.\n if (!referenced) vacate()\n setBusy(false)\n })\n },\n [chat, classifier, document, onTurnStart, onTurnEmpty],\n )\n\n const stop = useCallback(() => abort.current?.abort(), [])\n\n return { turns, items, notes, busy, send, stop }\n}\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useState","opening","answers","tokens","tokens","useMemo","useState","tokens","children","jsx","Fragment","jsx","jsxs","Fragment","jsx","jsxs","useMemo","document","useState","CheckIcon","useEffect","useRef","useState","CheckIcon","jsx","jsxs","jsx","jsxs","jsx","CheckIcon","jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","useState","useRef","useEffect","CheckIcon","useCallback","useEffect","useMemo","useRef","useState","cache","words","cache","useEffect","useState","ChevronRightIcon","jsx","jsxs","api","XIcon","jsx","jsxs","jsx","jsx","jsxs","XIcon","jsx","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","jsx","jsxs","CheckIcon","CheckIcon","jsx","jsx","jsx","jsx","jsxs","tokens","measure","common","CheckIcon","Fragment","jsx","jsxs","Fragment","jsx","jsxs","CheckIcon","Fragment","jsx","jsxs","useState","useEffect","opening","useRef","useMemo","useCallback","useCallback","useEffect","useRef","useState","document","useState","history","useRef","useEffect","useCallback","jsx","jsxs","useState","useEffect","useRef","useMemo","useCallback","title","identity"]}
|