pptx-ts 0.0.1
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/LICENSE +22 -0
- package/README.md +319 -0
- package/dist/autopage-DkjYZUFD.js +423 -0
- package/dist/autopage-DkjYZUFD.js.map +1 -0
- package/dist/browser.d.ts +31 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +110 -0
- package/dist/browser.js.map +1 -0
- package/dist/diagnostics-Du_s75MT.d.ts +829 -0
- package/dist/diagnostics-Du_s75MT.d.ts.map +1 -0
- package/dist/enums-CvRYniUA.d.ts +463 -0
- package/dist/enums-CvRYniUA.d.ts.map +1 -0
- package/dist/errors-Bvln0H-7.js +112 -0
- package/dist/errors-Bvln0H-7.js.map +1 -0
- package/dist/errors-PflMPWBn.d.ts +182 -0
- package/dist/errors-PflMPWBn.d.ts.map +1 -0
- package/dist/fit-BKs0zxMI.js +1356 -0
- package/dist/fit-BKs0zxMI.js.map +1 -0
- package/dist/html-dom-B0I0QSbU.js +679 -0
- package/dist/html-dom-B0I0QSbU.js.map +1 -0
- package/dist/html.d.ts +26 -0
- package/dist/html.d.ts.map +1 -0
- package/dist/html.js +63 -0
- package/dist/html.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect.d.ts +197 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +317 -0
- package/dist/inspect.js.map +1 -0
- package/dist/math.d.ts +37 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +203 -0
- package/dist/math.js.map +1 -0
- package/dist/measure.d.ts +313 -0
- package/dist/measure.d.ts.map +1 -0
- package/dist/measure.js +3 -0
- package/dist/namespaces-BVnNu7sg.js +666 -0
- package/dist/namespaces-BVnNu7sg.js.map +1 -0
- package/dist/node.d.ts +20 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +55 -0
- package/dist/node.js.map +1 -0
- package/dist/notes-RLCwdlTE.js +1703 -0
- package/dist/notes-RLCwdlTE.js.map +1 -0
- package/dist/package-CaOLXSNi.d.ts +193 -0
- package/dist/package-CaOLXSNi.d.ts.map +1 -0
- package/dist/pres-C5__xkDh.d.ts +202 -0
- package/dist/pres-C5__xkDh.d.ts.map +1 -0
- package/dist/presentation-Cp7vzlAw.js +5427 -0
- package/dist/presentation-Cp7vzlAw.js.map +1 -0
- package/dist/presentation-types-DP_8jog7.d.ts +4872 -0
- package/dist/presentation-types-DP_8jog7.d.ts.map +1 -0
- package/dist/read.d.ts +55 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/read.js +4 -0
- package/dist/script.d.ts +581 -0
- package/dist/script.d.ts.map +1 -0
- package/dist/script.js +3741 -0
- package/dist/script.js.map +1 -0
- package/dist/shapes-BemroU-z.js +6951 -0
- package/dist/shapes-BemroU-z.js.map +1 -0
- package/dist/slide-js0QpRV-.d.ts +3873 -0
- package/dist/slide-js0QpRV-.d.ts.map +1 -0
- package/dist/text-CyetbF6p.js +11278 -0
- package/dist/text-CyetbF6p.js.map +1 -0
- package/dist/units-1kRzYShk.js +231 -0
- package/dist/units-1kRzYShk.js.map +1 -0
- package/dist/units-internal-Dg95w_YD.js +753 -0
- package/dist/units-internal-Dg95w_YD.js.map +1 -0
- package/dist/zip.d.ts +68 -0
- package/dist/zip.d.ts.map +1 -0
- package/dist/zip.js +163 -0
- package/dist/zip.js.map +1 -0
- package/package.json +152 -0
- package/skills/ts-pptx-upstream/SKILL.md +340 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script.js","names":["#seen","#notes","ANCHOR","WRITABLE_DASHES","#byPartName","#assets","#counts","printSlides"],"sources":["../src/script/fidelity.ts","../src/script/ir.ts","../src/script/from-read/values.ts","../src/script/from-read/surface-fill.ts","../src/script/from-read/picture-fill.ts","../src/script/from-read/detect.ts","../src/script/from-read/text.ts","../src/script/from-read/table.ts","../src/script/from-read/chart.ts","../src/script/from-read/shape.ts","../src/script/from-read/chrome.ts","../src/script/from-read/transition.ts","../src/script/from-read/deck.ts","../src/script/print/literal.ts","../src/script/print/common.ts","../src/script/print/script.ts","../src/script/print/standalone.ts","../src/script/verify/canonical.ts","../src/script/verify/diff.ts"],"sourcesContent":["/**\n * Fidelity notes — the declared, machine-checkable list of what a deck loses on the way\n * to a script.\n *\n * A converter that warns about losses to a log has no way to be tested: the warnings are\n * prose, nothing consumes them, and a missing one looks exactly like a clean run. Making\n * the notes part of the IR inverts that. A note says \"field X of shape Y will not come\n * back\", so a round-trip check can exclude precisely those fields and treat **any**\n * remaining difference as a defect. Both directions then have teeth:\n *\n * - an *undeclared* loss fails the round-trip, because nothing excluded it;\n * - a *declared* loss that actually survives is a stale note, and the check can say so.\n *\n * That is the whole reason notes are first-class rather than a side channel. It also\n * means {@link FidelityNote.construct} is an identifier, not a sentence: it has to be\n * matchable against a field path, so it is a stable dotted key and the human explanation\n * lives in {@link FidelityNote.detail}.\n */\n\n/** What happened to the construct. */\nexport type Disposition =\n\t/** Gone: nothing in the output carries it. */\n\t| 'dropped'\n\t/**\n\t * Present but structurally simplified — a value survives while the structure around\n\t * it does not (threaded comment replies flattened into separate comments, a per-script\n\t * font scheme reduced to latin, a placeholder demoted to a plain shape).\n\t */\n\t| 'flattened'\n\t/**\n\t * Present and structurally intact, but not the same value — a re-encoding that a\n\t * viewer may or may not be able to tell apart (a modern transition mapped to the\n\t * nearest named one, a chart rebuilt from cached points rather than its workbook).\n\t */\n\t| 'approximated'\n\n/**\n * Which side of the library is responsible. Recording this is what makes the notes\n * actionable rather than merely honest: `unread` and `unwritable` are bugs waiting to be\n * fixed in a specific subsystem, while `unsupported` is a property of OOXML or of the\n * chosen output tier and will not be fixed by more converter work.\n */\nexport type Cause =\n\t/** The read API exposes no accessor for it, so the converter never saw it. */\n\t| 'unread'\n\t/** Read fine, but the write API has no option that expresses it. */\n\t| 'unwritable'\n\t/** Both sides can handle it; this output tier structurally cannot carry it. */\n\t| 'unsupported'\n\n/** One declared loss. */\nexport interface FidelityNote {\n\t/** 1-based source slide, or `null` for a deck-level loss. */\n\tslideNumber: number | null\n\t/** Source shape name (`p:cNvPr/@name`), or `null` when the loss is not shape-scoped. */\n\tshapeName: string | null\n\t/**\n\t * Stable dotted identifier for the lost construct — `line.width`, `text.tabStops`,\n\t * `chart.workbook`. Matched mechanically by the round-trip check, so it must name a\n\t * field path rather than describe one. Reuse an existing key for the same construct\n\t * instead of coining a synonym.\n\t */\n\tconstruct: string\n\tdisposition: Disposition\n\tcause: Cause\n\t/** Why, in a sentence, for a human reading the emitted script's header. */\n\tdetail: string\n}\n\n/**\n * Accumulates notes while a deck is walked, so the walk itself stays a plain\n * read-model → IR mapping and does not thread a growing array through every function.\n *\n * Deduplicates on the full note identity. Without that, a construct that is lost on every\n * run of a 400-run text body would produce 400 identical notes and bury the one-off losses\n * that actually need reading.\n */\nexport class NoteCollector {\n\treadonly #seen = new Set<string>()\n\treadonly #notes: FidelityNote[] = []\n\n\t/** Record a loss. A repeat of an identical note is ignored. */\n\tadd(note: FidelityNote): void {\n\t\tconst key = `${note.slideNumber}\\0${note.shapeName}\\0${note.construct}\\0${note.disposition}\\0${note.cause}\\0${note.detail}`\n\t\tif (this.#seen.has(key)) return\n\t\tthis.#seen.add(key)\n\t\tthis.#notes.push(note)\n\t}\n\n\t/**\n\t * The notes, in the order first recorded — which is deck order, since the walk is\n\t * ordered, so a reader meets them the way they meet the slides.\n\t */\n\tget notes(): FidelityNote[] {\n\t\treturn this.#notes\n\t}\n}\n\n/**\n * Namespace for a loss recorded against a shape on a **slide layout** rather than on a slide,\n * prepended to the construct by {@link layoutShapeScope}.\n *\n * The chrome mapper reuses the slide shape mapper wholesale — a rectangle on a layout is\n * transcribed by the same code that transcribes one on a slide, which is what keeps the two\n * from drifting. That sharing brings the slide vocabulary with it: a themed outline on a\n * layout records `line.width` exactly as a slide's would. Left unmarked, those notes would be\n * wrong twice over. A template-anchored script would report them, though it never rebuilds a\n * layout and loses nothing; and the round trip would let one excuse a *slide* difference,\n * because a layout note carries no slide number and a name like \"Rectangle 7\" repeats between\n * the tiers. The prefix keeps the shared vocabulary and states which tier it is about.\n *\n * `layout.` rather than `master.`, which is how the other chrome constructs are spelled: those\n * are named after the `defineSlideMaster` call that authors them, while these name the source\n * tier the loss is on — and a master's own decoration is not re-authored at all, so a note\n * under this prefix is always about a layout.\n */\nexport const LAYOUT_NOTE_PREFIX = 'layout.'\n\n/**\n * A {@link NoteCollector} bound to one slide and shape, so a mapping function can record\n * a loss without knowing where in the deck it sits. Obtained via {@link scopeNotes}.\n */\nexport interface NoteScope {\n\t/** Record a loss at this scope. */\n\tnote(construct: string, disposition: Disposition, cause: Cause, detail: string): void\n\t/** Re-scope to a shape within the same slide. */\n\tforShape(shapeName: string | null): NoteScope\n}\n\n/** Bind a collector to a slide (and optionally a shape). */\nexport function scopeNotes(\n\tcollector: NoteCollector,\n\tslideNumber: number | null,\n\tshapeName: string | null = null\n): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\tcollector.add({ slideNumber, shapeName, construct, disposition, cause, detail })\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn scopeNotes(collector, slideNumber, name)\n\t\t},\n\t}\n}\n\n/**\n * Wrap a scope so every construct recorded through it is namespaced under\n * {@link LAYOUT_NOTE_PREFIX} — see there for why.\n *\n * Constructs written at a call site inside the layout walk are therefore *relative*: the\n * decoration mapper records `decoration`, and what lands in the note list is\n * `layout.decoration`. The wrapper survives `forShape`, since a layout loss is scoped to a\n * shape name the same way a slide loss is.\n */\nexport function layoutShapeScope(notes: NoteScope): NoteScope {\n\treturn {\n\t\tnote(construct, disposition, cause, detail) {\n\t\t\tnotes.note(`${LAYOUT_NOTE_PREFIX}${construct}`, disposition, cause, detail)\n\t\t},\n\t\tforShape(name) {\n\t\t\treturn layoutShapeScope(notes.forShape(name))\n\t\t},\n\t}\n}\n","/**\n * The deck IR — a serializable description of a deck as a sequence of write-API calls.\n *\n * This is the seam between reading a `.pptx` and printing TypeScript for it. Everything\n * upstream of the IR knows about OOXML and the read model; everything downstream knows\n * only about strings. Neither half can see the other, which is the point: the decision\n * \"this `a:ln` becomes `line: { width: 2 }`\" is made once, here, and is testable without\n * a printer, while \"how a number is spelled in source text\" is a printer concern that\n * cannot silently change what the deck means.\n *\n * Two rules keep that seam honest, and both are load-bearing:\n *\n * 1. **The IR is data, not objects.** No DOM nodes, no read-model instances, no\n * functions — `structuredClone` and `JSON.stringify` both round-trip it. A round-trip\n * test can therefore compare two IRs directly (see {@link FidelityNote}), and an IR\n * can be cached or shipped without dragging a whole `Presentation` along.\n * 2. **`args` are literal write-API option objects.** A {@link CallIr} is exactly what\n * the emitted source will pass, so the printer never invents, reshapes, or defaults a\n * value — it spells out what is already there. If the printer had to interpret, the\n * same construct could mean two things depending on which half you asked.\n *\n * Media is the one thing that cannot be a literal, since bytes are not source text. It\n * is referenced by {@link AssetRef} and carried out-of-band in {@link DeckIr.assets}, so\n * the IR itself stays serializable and the printer decides between a file path and an\n * inline base64 literal.\n */\nimport type { FidelityNote } from './fidelity.js'\n\n/**\n * A reference to bytes held in {@link DeckIr.assets}, standing where a write-API option\n * wants image/media data. Printed as a `path` or an inline `data:` literal depending on\n * the print options — an IR-level decision would bake one choice into the IR and force a\n * re-read to change it.\n *\n * The `$asset` sigil is deliberate: no write-API option object has a `$`-prefixed key,\n * so a value carrying one is unambiguously a reference rather than user data.\n */\nexport interface AssetRef {\n\t$asset: string\n}\n\n/** `true` when `value` is an {@link AssetRef} rather than a plain IR object. */\nexport function isAssetRef(value: unknown): value is AssetRef {\n\treturn typeof value === 'object' && value !== null && typeof (value as AssetRef).$asset === 'string'\n}\n\n/**\n * Any value an IR may hold. Deliberately narrower than `unknown`: it excludes `undefined`\n * so that \"absent\" has exactly one spelling (a missing key), which is what makes two IRs\n * comparable field-by-field in a round-trip diff. `readModelToIr` never writes an\n * `undefined` value.\n */\nexport type IrValue = null | boolean | number | string | AssetRef | IrValue[] | { [key: string]: IrValue }\n\n/**\n * Widen one of the typed IR records below to {@link IrValue}, for the printer and the\n * canonicaliser, which walk the IR generically.\n *\n * A cast, and unavoidably so. An optional key on an interface types as `T | undefined`,\n * while `IrValue` deliberately excludes `undefined` so that \"absent\" has exactly one\n * spelling — which makes the two mutually unassignable even though every value a mapper\n * actually produces satisfies both. The invariant that closes the gap is enforced at the\n * source (`compact` and the conditional spreads in `from-read/`, pinned by the \"no value is\n * `undefined`\" corpus test) rather than by the type system, so it is stated once here\n * instead of re-argued at each call site.\n */\nexport function asIrValue(value: object): IrValue {\n\treturn value as unknown as IrValue\n}\n\n/** Bytes referenced by an {@link AssetRef}, plus what a printer needs to name and type them. */\nexport interface AssetIr {\n\t/** Stable key an {@link AssetRef} resolves against; also the emitted filename. */\n\tname: string\n\t/** MIME type from the source package's content types, for an inline `data:` URI. */\n\tcontentType: string\n\tbytes: Uint8Array\n}\n\n/**\n * One write-API call on a slide, in the order it must be made. `method` names a real\n * method on the authored slide and `args` are its positional arguments — so a printer is\n * a formatter, and `readModelToIr` owns every semantic choice.\n *\n * Ordering is z-order: OOXML paints a slide's shape tree front-to-back in document order,\n * and so does the write path, so preserving call order preserves overlap.\n */\nexport interface CallIr {\n\tmethod: 'addText' | 'addShape' | 'addImage' | 'addTable' | 'addChart' | 'addConnector' | 'addGroup' | 'addNotes'\n\targs: IrValue[]\n\t/**\n\t * The source shape's name (`p:cNvPr/@name`), when it had one. Not an argument —\n\t * carried so a printer can comment the call and a fidelity note can point at it.\n\t */\n\tsourceName?: string\n}\n\n/**\n * How a slide's content gets into the output deck.\n *\n * `authored` — every shape is transcribed into {@link CallIr}s and regenerated through\n * the write API. This is the goal: the emitted source is editable, and a reader can see\n * what the deck contains.\n *\n * `carried` — the slide holds at least one construct the write API cannot express at all\n * (`chartEx` is the clear case: a full reader, no emitter), so transcribing it would\n * silently produce a different deck. A printer that *can* copy the slide from the source\n * package should do so: fidelity is higher than transcription, though the emitted source then\n * says nothing about what is on the slide, which is a real cost and always carries a\n * {@link FidelityNote}.\n *\n * This is a recommendation, not an erasure. {@link SlideIr.calls} is populated either way, so\n * a printer with no source package to copy from prints them and loses only the unwritable\n * construct rather than the whole slide.\n */\nexport type SlideSource = 'authored' | 'carried'\n\n/**\n * A slide's background, already reduced to what the write API's `background` accepts.\n *\n * `data` rather than `image`, because `BackgroundProps` is `DataOrPathProps & ShapeFillProps`\n * and `data` is the key it actually reads — an `image` key would print, typecheck against\n * `IrValue`, and be ignored at run time.\n */\nexport interface BackgroundIr {\n\tcolor?: string\n\ttransparency?: number\n\tdata?: AssetRef\n}\n\n/**\n * A transition's sound (`p:sndAc`), reduced to what `TransitionSoundProps` accepts.\n *\n * `data` rather than `path`, for the same reason a background image uses `data`: the bytes\n * are the thing the IR carries, and a path would bind the script to a file layout the IR\n * knows nothing about. The stop-previous form has no bytes at all — it silences a sound\n * still playing from the previous slide — so it is the one shape here with no {@link AssetRef}.\n */\nexport interface TransitionSoundIr {\n\t/** Bytes of the embedded WAV, for a start sound. Absent for {@link stopPrevious}. */\n\tdata?: AssetRef\n\t/** `p:snd@name`, the display name PowerPoint shows for the sound. */\n\tname?: string\n\t/** `p:stSnd@loop` — repeat until the next sound starts. Omitted when false, its default. */\n\tloop?: boolean\n\t/** The `p:endSnd` form: stop the previous slide's sound rather than start one. */\n\tstopPrevious?: boolean\n}\n\n/**\n * A slide's show transition (`p:transition`), as a literal `TransitionProps`.\n *\n * Only the base ECMA-376 transitions reach this type. The read model reports\n * {@link TransitionInfo.type} as an *open string*, because PowerPoint's modern effects\n * (Morph, Vortex, …) live in the `p14`/`p15`/`p159` namespaces and it decodes those too —\n * but the write path names 21 base ones and nothing else, so `from-read/transition.ts`\n * filters against that vocabulary and notes what it drops. Anything that survives is a name\n * the write API's own `TransitionType` union accepts, which is what keeps a printed script\n * compiling.\n */\nexport interface TransitionIr {\n\t/** The transition-type element's local name, guaranteed to be a writable one. */\n\ttype: string\n\t/** `p:transition@spd`. Always present — see `from-read/transition.ts` for why it is not omitted. */\n\tspeed: 'slow' | 'med' | 'fast'\n\t/** `p14:dur` in milliseconds, when the source carried an exact duration. */\n\tdurationMs?: number\n\t/** `advClick`. Omitted when true, its default. */\n\tadvanceOnClick?: boolean\n\t/** `advTm` in milliseconds, when the slide auto-advances. */\n\tadvanceAfterMs?: number\n\t/** Type-specific attributes on the type element (`{ dir: 'd' }`, `{ spokes: '2' }`, …). */\n\tvariant?: { [key: string]: string }\n\tsound?: TransitionSoundIr\n}\n\n/**\n * The layout a slide should be bound to in the destination deck, identified two ways\n * because neither alone is sufficient.\n *\n * The **name** is the portable identity: it is what lets a script built from one deck be\n * re-pointed at a different template whose layouts happen to be named the same, and it is\n * what a reader recognises. But `p:cSld@name` is not unique — a deck with several masters\n * routinely carries several \"Title and Content\" layouts, and binding by an ambiguous name\n * is an error, not a coin flip. The **index** into the deck's layout gallery always\n * resolves, so it is the fallback, and {@link nameIsUnique} says which to trust.\n */\nexport interface SlideLayoutIr {\n\t/** `p:cSld@name` of the source layout (`''` when the layout is unnamed). */\n\tname: string\n\t/** Zero-based position in the source deck's layout gallery, in master-then-layout order. */\n\tindex: number\n\t/** `false` when another layout in that gallery shares {@link name}. */\n\tnameIsUnique: boolean\n}\n\n/** One slide of the deck. */\nexport interface SlideIr {\n\t/** 1-based index in the source deck; the identity a {@link FidelityNote} points at. */\n\tnumber: number\n\tsource: SlideSource\n\t/** The layout to bind to, or `null` when the source slide resolves none. */\n\tlayout: SlideLayoutIr | null\n\t/** `p:sld/@show=\"0\"` — a slide hidden from presentation but present in the deck. */\n\thidden: boolean\n\t/** `p:cSld/@name`, when the source slide had one. */\n\tname?: string\n\tbackground?: BackgroundIr\n\t/** Speaker notes as plain text. Notes-slide geometry and placeholders do not survive. */\n\tnotesText?: string\n\t/**\n\t * The show transition, when the source has one the write API can name. Slide-scoped\n\t * rather than a {@link CallIr} because the write API models it as a property assignment\n\t * on the slide, not a method — the IR's `method` union names real methods only.\n\t */\n\ttransition?: TransitionIr\n\t/**\n\t * Write-API calls in z-order.\n\t *\n\t * Populated for every slide, **including a `carried` one**. A printer that can copy the\n\t * source slide ignores these; one that cannot — a standalone output has no source package\n\t * to copy from — prints them and is left with only the unwritable construct missing rather\n\t * than the whole slide. Marking a slide `carried` is a recommendation, not an erasure.\n\t */\n\tcalls: CallIr[]\n}\n\n/**\n * A deck's theme, reduced to what `ThemeProps` accepts — the 12 `a:clrScheme` slots and the\n * major/minor Latin, East-Asian and complex-script faces.\n *\n * What is *not* here is the point of the tier split. `a:fmtScheme` — the three fill, three\n * line and three effect style lists a shape's `p:style` references — has no write-API\n * counterpart and no read accessor, so a theme cannot be reproduced, only approximated.\n */\nexport interface ThemeIr {\n\theadFontFace?: string\n\tbodyFontFace?: string\n\theadFontFaceEA?: string\n\tbodyFontFaceEA?: string\n\theadFontFaceCS?: string\n\tbodyFontFaceCS?: string\n\t/** The 12 `a:clrScheme` slots as bare 6-digit hex, omitting any the theme leaves unset. */\n\tcolorScheme?: { [slot: string]: string }\n}\n\n/**\n * One source slide layout approximated as a `defineSlideMaster` call.\n *\n * The naming is the write API's, not OOXML's: `defineSlideMaster` creates a *layout* under\n * the single shared master, which is exactly the granularity a source layout needs. A source\n * deck's masters have no counterpart at all — hence {@link ChromeIr}'s multi-master note.\n */\nexport interface MasterIr {\n\t/**\n\t * Gallery position of the source layout, matching {@link SlideLayoutIr.index}, so a slide\n\t * finds the master it should bind to without re-deriving a name.\n\t */\n\tlayoutIndex: number\n\t/**\n\t * A `SlideMasterProps` literal. `props.title` is made unique across the deck, because it\n\t * doubles as the key `addSlide({ masterTitle })` matches against and source layout names\n\t * are not unique.\n\t */\n\tprops: { [key: string]: IrValue }\n}\n\n/**\n * The deck's shared chrome, approximated for an output that has no template to inherit it\n * from. A template-anchored printer ignores this entirely — the source deck *is* the chrome.\n */\nexport interface ChromeIr {\n\ttheme: ThemeIr\n\t/** One entry per source layout, in gallery order. */\n\tmasters: MasterIr[]\n}\n\n/** Deck-level properties, reduced to the five `docProps` fields the write API sets. */\nexport interface DeckPropsIr {\n\ttitle?: string\n\tauthor?: string\n\tcompany?: string\n\tsubject?: string\n\trevision?: string\n}\n\n/**\n * A whole deck, ready to print.\n *\n * `widthEmu`/`heightEmu` are raw EMU rather than inches because that is what the read\n * model reports and what the write API's `Coord` accepts verbatim; converting here would\n * introduce a rounding decision at the wrong layer.\n */\nexport interface DeckIr {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\tprops: DeckPropsIr\n\t/**\n\t * Theme and layouts, approximated. Only a standalone printer reads this; a\n\t * template-anchored one gets all of it byte-identical from the source deck instead.\n\t */\n\tchrome: ChromeIr\n\tslides: SlideIr[]\n\tassets: AssetIr[]\n\t/**\n\t * Every construct that did not survive into {@link slides} intact. This is a\n\t * *contract*, not a log: a round-trip check excludes exactly these fields from its\n\t * diff, so an unnoted difference is a bug and a note nothing else corroborates is a\n\t * stale claim. See {@link FidelityNote}.\n\t */\n\tfidelity: FidelityNote[]\n}\n","/**\n * Value-level conversions shared by every mapper: geometry, colour, and the small\n * discipline that keeps an IR diffable.\n *\n * The precision rules here are not style choices, they are the measured boundary of what\n * the write API can carry, and each is pinned by a regression test:\n *\n * - A `Coord`-typed option accepts `` `${n}emu` ``, so EMU passes through untouched and\n * the source geometry is reproduced exactly. That covers every position and size.\n * - `colW`, `rowH`, and `margin` are number/`Margin`-typed **inches** and reject a raw-EMU\n * string, so they are where exactness stops. `defineLayout`'s `width`/`height` are a\n * fourth, reached only by a printer: there the imprecision does not degrade quietly but\n * *throws*, since `appendSlides` compares the two decks' EMU sizes for equality after\n * converting the declared inches back. Six decimal places is the minimum\n * at which `Math.round(printed × 914400)` provably returns the original EMU, bounding the\n * drift at 0.4572 EMU — about half a millionth of an inch. Rounding shorter to suppress\n * `0.5000000001`-style noise trades a cosmetic problem for a real geometry loss.\n */\nimport type { IrValue } from '../ir.js'\nimport type { GraphicFrame } from '../../read.js'\nimport { EMU_PER_POINT } from '../../units.js'\n\n/** EMU per inch (ECMA-376 §20.1.2.1). */\nconst EMU_PER_INCH = 914400\n\n/**\n * Decimal places used for the inch-typed options. See the module header: this is the\n * proven minimum for an EMU-exact round-trip, not a formatting preference.\n */\nconst INCH_DECIMALS = 6\n\n/** Geometry as a `Coord` the write API takes verbatim, preserving the exact EMU. */\nexport function emu(value: number): string {\n\treturn `${Math.round(value)}emu`\n}\n\n/**\n * Geometry as inches, for the three options that reject a raw-EMU string. Rounded to\n * {@link INCH_DECIMALS}, which is EMU-exact on the way back.\n */\nexport function inches(emuValue: number): number {\n\treturn Number((emuValue / EMU_PER_INCH).toFixed(INCH_DECIMALS))\n}\n\n/** EMU → points, the unit the write API uses for line widths and font sizes. */\nexport function points(emuValue: number): number {\n\treturn emuValue / EMU_PER_POINT\n}\n\n/**\n * Points → inches, at the same proven precision as {@link inches}. Needed because the read\n * model reports text-body insets in points while the write API's `margin` takes inches —\n * and warns on a value `>= 1`, on the assumption that it is a points value passed by\n * mistake, so handing it points would both mis-scale the text and produce a warning.\n */\nexport function pointsToInches(pt: number): number {\n\treturn Number((pt / 72).toFixed(INCH_DECIMALS))\n}\n\n/**\n * A colour for a write-API `color` field. The read model splits a colour into a raw\n * `schemeClr` token and a resolved literal hex; this prefers the token, because a token\n * re-resolves against the destination theme and so keeps the deck recolourable, which is\n * the whole reason a theme colour was authored.\n *\n * Only the ten tokens the write path's `clrMap` covers survive as tokens — the other\n * seven `ST_SchemeColorVal` values degrade to a hex literal there anyway, so passing them\n * through would produce a silently different colour. Callers hand those to\n * {@link literalColor} instead after recording a note.\n */\nconst WRITABLE_SCHEME_TOKENS = new Set([\n\t'accent1',\n\t'accent2',\n\t'accent3',\n\t'accent4',\n\t'accent5',\n\t'accent6',\n\t'bg1',\n\t'bg2',\n\t'tx1',\n\t'tx2',\n])\n\n/** `true` when a `schemeClr` token survives as a token rather than degrading to hex. */\nexport function isWritableSchemeToken(token: string | null): boolean {\n\treturn token !== null && WRITABLE_SCHEME_TOKENS.has(token)\n}\n\n/** Normalize a hex to the bare 6-digit uppercase form the write API expects. */\nexport function literalColor(hex: string): string {\n\treturn hex.replace(/^#/, '').toUpperCase()\n}\n\n/**\n * Build an IR object from possibly-absent parts, dropping every `undefined`.\n *\n * Every mapper funnels through this. An IR must spell \"absent\" exactly one way — a\n * missing key — or two IRs describing the same deck compare unequal because one wrote\n * `{ bold: undefined }` and the other wrote `{}`. That would surface as phantom\n * round-trip failures, so the invariant is enforced in one place rather than trusted to\n * every call site.\n *\n * Returns `undefined` when nothing survived, so a caller can drop the whole option object\n * rather than emit an empty one.\n */\nexport function compact(source: Record<string, IrValue | undefined>): Record<string, IrValue> | undefined {\n\tconst out: Record<string, IrValue> = {}\n\tlet any = false\n\tfor (const key of Object.keys(source).sort()) {\n\t\tconst value = source[key]\n\t\tif (value === undefined) continue\n\t\tout[key] = value\n\t\tany = true\n\t}\n\treturn any ? out : undefined\n}\n\n/** {@link compact}, but always an object — for a required options argument. */\nexport function compactRequired(source: Record<string, IrValue | undefined>): Record<string, IrValue> {\n\treturn compact(source) ?? {}\n}\n\n/** Drop a value that is `null`, so the read model's \"unset\" becomes an absent IR key. */\nexport function orUndefined<T>(value: T | null): T | undefined {\n\treturn value === null ? undefined : value\n}\n\n/**\n * A 0–1 opacity as the write API's 0–100 transparency; `undefined` when unset.\n *\n * Fully opaque is *not* `0` here — a caller that means \"no transparency at all\" passes\n * `undefined`, because emitting `transparency: 0` for an `a:alphaModFix amt=\"100000\"`\n * would produce a key the output cannot have: the write path emits no `a:alphaModFix` for\n * a zero transparency, so the re-read deck reports no alpha and the round trip sees a\n * difference where there is no visible one.\n */\nexport function alphaToTransparency(alpha: number | null | undefined): number | undefined {\n\tif (alpha === undefined || alpha === null) return undefined\n\treturn Math.round((1 - alpha) * 100)\n}\n\n/**\n * A graphic frame's position as write-API options. Identical to a shape's, minus rotation and\n * flip: a `p:graphicFrame` has neither, so `a:xfrm` carries only the offset and extent.\n */\nexport function positionOfFrame(frame: GraphicFrame): Record<string, IrValue> {\n\tconst box = frame.absoluteFrame\n\tif (!box) return {}\n\treturn { x: emu(box.left), y: emu(box.top), w: emu(box.width), h: emu(box.height) }\n}\n","/**\n * The non-solid halves of a surface's fill — `a:gradFill` and `a:pattFill` — as\n * `ShapeFillProps`.\n *\n * Shared by a shape's fill, a table's background, and a table cell's, which are the same\n * two elements read from three containers. `ShapeProps.fill`, `TableProps.tableFill` and\n * `TableCellProps.fill` are all `ShapeFillProps`, so the mapping is identical and only the\n * note's `where` prefix differs — the same reasoning that keeps `pictureFillOption` in one\n * place rather than one copy per surface.\n */\nimport type { GradientFill } from '../../read/api/gradient.js'\nimport type { PatternFill } from '../../read/api/pattern-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport { alphaToTransparency, compact, isWritableSchemeToken, literalColor } from './values.js'\n\n/** How a note names the surface a gradient sits on: `fill.gradient`, `table.fill.gradient`, … */\ntype FillNoteScope = 'fill' | 'line' | 'table.fill' | 'table.cell.fill'\n\n/**\n * A read gradient as `GradientFillProps`. Stop positions convert from the read model's\n * 0–1 fraction to the write API's 0–100 percentage; the angle needs no conversion, since\n * both sides use OOXML degrees (clockwise from 3 o'clock).\n */\nexport function gradientStops(gradient: GradientFill, notes: NoteScope, where: FillNoteScope): IrValue | undefined {\n\tconst stops = gradient.stops\n\t\t.map((stop) => {\n\t\t\tconst color = isWritableSchemeToken(stop.schemeColor)\n\t\t\t\t? (stop.schemeColor as string)\n\t\t\t\t: stop.effectiveHex === null\n\t\t\t\t\t? null\n\t\t\t\t\t: literalColor(stop.effectiveHex)\n\t\t\tif (color === null) return null\n\t\t\treturn compact({\n\t\t\t\tcolor,\n\t\t\t\tposition: Math.round((stop.position ?? 0) * 100),\n\t\t\t\ttransparency: alphaToTransparency(stop.alpha),\n\t\t\t}) as IrValue\n\t\t})\n\t\t.filter((stop): stop is IrValue => stop !== null)\n\n\tif (stops.length < 2) {\n\t\tnotes.note(\n\t\t\t`${where}.gradient`,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'a gradient with fewer than two resolvable stops cannot be expressed, so this falls back to no gradient'\n\t\t)\n\t\treturn undefined\n\t}\n\n\tif (gradient.kind === 'path') {\n\t\t// `a:path` covers circle/rect/shape; the write API models only the radial case, so\n\t\t// a rectangular or shape-following gradient becomes a circular one.\n\t\tif (gradient.path !== null && gradient.path !== 'circle') {\n\t\t\tnotes.note(\n\t\t\t\t`${where}.gradient.path`,\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`a \"${gradient.path}\" path gradient is emitted as a radial one; the write API models no other path shape`\n\t\t\t)\n\t\t}\n\t\treturn { kind: 'radial', stops }\n\t}\n\treturn compact({ kind: 'linear', angle: gradient.angleDeg ?? 0, stops })\n}\n\n/**\n * A read hatch as `ShapeFillProps` with `type: 'pattern'`, or `undefined` when the pattern\n * names no preset — `a:pattFill/@prst` is what selects the hatch, so without it there is\n * nothing to reproduce.\n *\n * Both colours are emitted as literals rather than scheme tokens: `PatternFillProps` types\n * `fgColor`/`bgColor` as hex, so a token would not survive the write side anyway.\n */\nexport function patternOption(pattern: PatternFill | null): IrValue | undefined {\n\tif (!pattern?.preset) return undefined\n\treturn {\n\t\ttype: 'pattern',\n\t\tpattern: compact({\n\t\t\tpreset: pattern.preset,\n\t\t\tfgColor: pattern.foreground ? literalColor(pattern.foreground.effectiveHex) : undefined,\n\t\t\tbgColor: pattern.background ? literalColor(pattern.background.effectiveHex) : undefined,\n\t\t}) ?? { preset: pattern.preset },\n\t}\n}\n","/**\n * `a:blipFill` on a *surface* → the write API's `fill: { type: 'image', image: { data } }`.\n *\n * Shared by a shape's fill and a table cell's, which are the same construct read from two\n * containers: `TableCellProps.fill` and `ShapeProps.fill` are both `ShapeFillProps`, so\n * the mapping is identical and only the note wording differs. Keeping one implementation\n * is what stops the two drifting into different answers for the same `a:blipFill`.\n *\n * The bytes and the blip's opacity carry. Nothing else does, and that is a property of the\n * write path rather than of this mapper: `genXmlImageFill` emits every picture fill as\n * `<a:blipFill dpi=\"0\" rotWithShape=\"1\">…<a:srcRect/><a:stretch><a:fillRect/></a:stretch>`,\n * so a tiled fill comes back stretched and a cropped one comes back whole. That is a\n * visible change, so it is noted when — and only when — the source actually uses it.\n */\nimport type { FillRect, PictureFill } from '../../read/api/picture-fill.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { AssetRef, IrValue } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\nimport { alphaToTransparency, compactRequired } from './values.js'\n\n/** How a note names the surface it is about; the mapping itself does not vary. */\nexport interface PictureFillSubject {\n\t/** Note construct for a fill whose bytes cannot be carried at all. */\n\tconstruct: string\n\t/** The surface as a note's detail names it — \"this shape's surface\", \"this table cell\". */\n\tsubject: string\n\t/** Where the fill sits in the source XML, for a note's detail. */\n\telement: string\n}\n\n/**\n * A picture fill as `ShapeFillProps`, or `undefined` when its bytes cannot be carried —\n * in which case a `dropped` note has been recorded and the surface comes out unfilled.\n */\nexport function pictureFillOption(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): IrValue | undefined {\n\tconst asset = pictureAsset(picture, assets, notes, subject)\n\tif (!asset) return undefined\n\n\tnoteUncarriedGeometry(picture, notes, subject)\n\n\treturn compactRequired({\n\t\ttype: 'image',\n\t\timage: { data: asset },\n\t\t// Fully opaque passes as `undefined` rather than `0`; see `alphaToTransparency`.\n\t\ttransparency: picture.alpha === 1 ? undefined : alphaToTransparency(picture.alpha),\n\t})\n}\n\n/** The fill's image as an asset, or `null` with a note saying why it could not be one. */\nfunction pictureAsset(\n\tpicture: PictureFill,\n\tassets: AssetResolver,\n\tnotes: NoteScope,\n\tsubject: PictureFillSubject\n): AssetRef | null {\n\tconst partName = picture.partName\n\tif (partName === null) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`${subject.subject} is filled with an image (${subject.element}) that embeds no image part — an external or linked blip — so there are no bytes to carry and it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\t// The write path refuses an SVG picture fill outright (`src/gen/define/image.ts` warns\n\t// and falls back to `type: 'none'`), so emitting one would produce a script that paints\n\t// nothing while claiming a fill. Checked *before* `assetFor`, which would otherwise\n\t// register bytes that no call ends up referencing.\n\tif (assets.contentTypeOf(partName) === 'image/svg+xml') {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`${subject.subject} is filled with an SVG image (${subject.element} → ${partName}); a picture fill accepts raster bytes only on the write side, so it comes out unfilled`\n\t\t)\n\t\treturn null\n\t}\n\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\tsubject.construct,\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the image filling ${subject.subject} (${subject.element} → ${partName}) is not present in the package, so there are no bytes to carry`\n\t\t)\n\t\treturn null\n\t}\n\treturn asset\n}\n\n/** `true` when a rect actually insets an edge; an explicit but empty rect reports zeros. */\nfunction isRectSet(rect: FillRect | null): boolean {\n\treturn rect !== null && (rect.left !== 0 || rect.top !== 0 || rect.right !== 0 || rect.bottom !== 0)\n}\n\n/**\n * Note the parts of the fill's geometry the write path's fixed stretch cannot express.\n *\n * Only the ones the source actually uses: a note on every picture fill would say nothing,\n * and the round-trip check reads an unmatched note as a candidate for review.\n */\nfunction noteUncarriedGeometry(picture: PictureFill, notes: NoteScope, subject: PictureFillSubject): void {\n\tconst lost: string[] = []\n\tif (picture.mode === 'tile' || picture.tile !== null) lost.push('tiling (a:tile)')\n\tif (isRectSet(picture.srcRect)) lost.push('the source crop (a:srcRect)')\n\tif (isRectSet(picture.fillRect)) lost.push('the destination inset (a:stretch/a:fillRect)')\n\tif (picture.dpi !== null && picture.dpi !== 0) lost.push(`the render resolution (@dpi=\"${picture.dpi}\")`)\n\t// Only the explicit `0`. Unset means \"whatever the application defaults to\", which is\n\t// not a claim this note can make about a difference.\n\tif (picture.rotWithShape === false) lost.push('not rotating with the shape (@rotWithShape=\"0\")')\n\tif (lost.length === 0) return\n\n\tnotes.note(\n\t\t`${subject.construct}.geometry`,\n\t\t'approximated',\n\t\t'unwritable',\n\t\t`the image filling ${subject.subject} is re-embedded, but the write path emits every picture fill as a plain stretched blip (dpi=\"0\" rotWithShape=\"1\", <a:srcRect/><a:stretch><a:fillRect/></a:stretch>), so ${lost.join(', ')} ${lost.length === 1 ? 'does' : 'do'} not carry`\n\t)\n}\n","/**\n * Presence checks for constructs the read model has no accessor for.\n *\n * These reach through the documented raw hatch (`element_`) rather than through a typed\n * accessor, which needs justifying. The rule they follow: **detect, never decode.** Each\n * function answers only \"is this here?\", so the answer can become a {@link FidelityNote}.\n * Nothing here interprets a value or feeds one into a call — that would be building a\n * private read path alongside the public one, and it would rot the moment the element's\n * meaning changed.\n *\n * The alternative is worse than the coupling. Without these checks, a deck with an embedded\n * video converts to a static poster image and a deck with an equation converts to an empty\n * box, both silently and both with a clean round-trip, because a diff cannot see what\n * neither side read. A loss you can name is a bug report; a loss nothing observes is a\n * defect that ships.\n *\n * Each check here is a standing argument for a real accessor. When one lands, the\n * corresponding function should be deleted, not kept in sync.\n */\n\nimport { OOXML_NS } from '../../ooxml/namespaces.js'\n\n/** Office MathML namespace — the equation body itself, wrapped by `a14:m` in a text run. */\nconst MATH_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/math'\n\n/** Shape-tree children that carry drawing content, as opposed to the tree's own properties. */\nconst SHAPE_ELEMENTS = new Set(['sp', 'pic', 'graphicFrame', 'grpSp', 'cxnSp'])\n\n/** A minimal structural view of a DOM element, so this module needs no DOM lib types. */\ninterface ElementLike {\n\tnamespaceURI: string | null\n\tlocalName: string | null\n\tfirstChild: NodeLike | null\n\tgetAttribute(name: string): string | null\n\tgetElementsByTagNameNS(namespaceURI: string, localName: string): { length: number }\n}\n\ninterface NodeLike {\n\tnodeType: number\n\tnextSibling: NodeLike | null\n}\n\nconst ELEMENT_NODE = 1\n\nfunction has(element: unknown, namespaceURI: string, localName: string): boolean {\n\tconst el = element as ElementLike | null\n\tif (!el || typeof el.getElementsByTagNameNS !== 'function') return false\n\treturn el.getElementsByTagNameNS(namespaceURI, localName).length > 0\n}\n\n/**\n * The first *direct* child with this name.\n *\n * A subtree search is wrong for structural lookups, in two ways that both bite here.\n * `a:ext` names two unrelated elements — a shape extent (`@cx`/`@cy`) and an extension-list\n * entry (`@uri`) — so a subtree search finds whichever comes first in document order. And on\n * a group it descends into the group's own children, so a nested group's transform answers\n * for its parent's.\n */\nfunction child(element: ElementLike | null, namespaceURI: string, localName: string): ElementLike | null {\n\tif (!element) return null\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType !== ELEMENT_NODE) continue\n\t\tconst el = node as unknown as ElementLike\n\t\tif (el.namespaceURI === namespaceURI && el.localName === localName) return el\n\t}\n\treturn null\n}\n\n/** Every direct element child, as {@link ElementLike}s. */\nfunction children(element: ElementLike | null): ElementLike[] {\n\tif (!element) return []\n\tconst out: ElementLike[] = []\n\tfor (let node = element.firstChild; node; node = node.nextSibling) {\n\t\tif (node.nodeType === ELEMENT_NODE) out.push(node as unknown as ElementLike)\n\t}\n\treturn out\n}\n\n/**\n * `true` when this shape is an embedded audio or video rather than a still picture.\n *\n * PowerPoint authors media as a `p:pic` whose `p:nvPr` carries an `a:videoFile` or\n * `a:audioFile`, with the poster frame as the picture's own blip. The read model reports\n * only the poster — `mediaKind` distinguishes raster from SVG, not still from moving — so\n * without this check a video converts to a static image that looks deliberate.\n */\nexport function isAudioVideo(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'videoFile') || has(element, OOXML_NS.a, 'audioFile')\n}\n\n/**\n * `true` when this shape's text body contains an OMML equation.\n *\n * An equation lives in `m:oMath` inside an `a14:m` run, which contributes nothing to\n * `TextFrame.text`, so an equation-only shape reads as an empty text frame. The write API\n * *can* author one (`TextProps.math`, plus the `ts-pptx/math` subpath for LaTeX/MathML\n * input), which makes this a read-side gap rather than a hard limit.\n */\nexport function hasEquation(element: unknown): boolean {\n\treturn has(element, MATH_NS, 'oMath')\n}\n\n/**\n * `true` when this `p:sp` is a text box rather than an auto shape.\n *\n * The discriminator is one attribute, `p:cNvSpPr/@txBox`, and nothing reads it. The\n * tempting substitute — \"it has no preset geometry\" — is wrong for the common case:\n * PowerPoint gives every text box an explicit `<a:prstGeom prst=\"rect\"/>`, so that test\n * calls every real text box an auto shape. The difference is not cosmetic. PowerPoint\n * autofits, wraps and resizes a text box by different rules, and offers a different\n * right-click menu for it.\n *\n * Direct child rather than a subtree search: `p:cNvSpPr` sits under `p:nvSpPr`, and a group\n * would otherwise answer for its first child.\n */\nexport function isTextBox(element: unknown): boolean {\n\tconst nvSpPr = child(element as ElementLike | null, OOXML_NS.p, 'nvSpPr')\n\treturn child(nvSpPr, OOXML_NS.p, 'cNvSpPr')?.getAttribute('txBox') === '1'\n}\n\n/**\n * `true` when a group's child coordinate space equals its own frame, so its children are\n * already in slide-absolute units.\n *\n * `addGroup` always emits an identity child space; a source group whose `a:chOff`/`a:chExt`\n * differ scales or shifts its contents, and that behaviour cannot be reproduced. The read\n * model has no accessor for the child space — `absoluteFrame` deliberately composes it away,\n * which is right for locating a shape and wrong for spotting this difference.\n *\n * A group with no explicit transform inherits an identity one, so a missing `a:xfrm` is\n * `true` rather than unknown.\n */\nexport function hasIdentityChildSpace(element: unknown): boolean {\n\tconst xfrm = child(child(element as ElementLike | null, OOXML_NS.p, 'grpSpPr'), OOXML_NS.a, 'xfrm')\n\tif (!xfrm) return true\n\n\tconst off = child(xfrm, OOXML_NS.a, 'off')\n\tconst ext = child(xfrm, OOXML_NS.a, 'ext')\n\tconst chOff = child(xfrm, OOXML_NS.a, 'chOff')\n\tconst chExt = child(xfrm, OOXML_NS.a, 'chExt')\n\tif (!off || !ext || !chOff || !chExt) return true\n\n\treturn (\n\t\toff.getAttribute('x') === chOff.getAttribute('x') &&\n\t\toff.getAttribute('y') === chOff.getAttribute('y') &&\n\t\text.getAttribute('cx') === chExt.getAttribute('cx') &&\n\t\text.getAttribute('cy') === chExt.getAttribute('cy')\n\t)\n}\n\n/**\n * `true` when this theme declares an `a:fmtScheme`.\n *\n * The format scheme holds the three fill, three line and three effect style lists a shape's\n * `p:style` indexes into. Neither half of the library touches it: nothing reads it, and the\n * write path emits a hardcoded Office one. So a deck whose theme carries a custom format\n * scheme is repainted with Office's, and this is the only way to notice.\n */\nexport function hasFormatScheme(element: unknown): boolean {\n\treturn has(element, OOXML_NS.a, 'fmtScheme')\n}\n\n/**\n * `true` when this slide master declares per-level text styles (`p:txStyles`) with content.\n *\n * `SlideMasterProps.textStyles` can author them, so this is purely a read-side gap — the\n * default size, face, colour and bullet of every placeholder level is invisible to the\n * converter and comes back as PowerPoint's built-in default.\n */\nexport function hasTextStyles(element: unknown): boolean {\n\tconst txStyles = child(element as ElementLike | null, OOXML_NS.p, 'txStyles')\n\treturn children(txStyles).some((group) => children(group).length > 0)\n}\n\n/**\n * `true` when this shape is a placeholder — the tier that *reserves* a region for a slide to\n * fill, as opposed to the decoration that is drawn as-is.\n *\n * A DOM predicate rather than `shape.placeholder !== null`, and that is not an oversight: only\n * `AutoShape` reports a `p:ph` through the read model, so the model-based spelling would call\n * a *picture* placeholder (`p:nvPicPr/p:nvPr/p:ph`, which PowerPoint does author) decoration\n * and re-draw it as a fixed image on every slide bound to the layout.\n *\n * Not a direct-child lookup, unlike its neighbours: the `p:ph` sits two or three levels down\n * inside whichever `p:nv*Pr` the shape kind uses. That means a *group* containing a\n * placeholder answers `true` for its child, which is the wanted answer anyway — a group is\n * never itself a placeholder, and a layout that put one inside a group is one whose grouping\n * cannot survive being flattened into loose objects.\n */\nexport function isPlaceholderShape(element: unknown): boolean {\n\treturn has(element, OOXML_NS.p, 'ph')\n}\n\n/**\n * `true` when this master or layout carries a shape that is not a placeholder — a logo, a\n * rule, a background image, a footer graphic.\n *\n * Only the **master** arm still needs this. A layout's decoration is now transcribed into its\n * `defineSlideMaster({ objects })` call, so what did not survive is reported per shape rather\n * than as a blanket count. A master's cannot be: `defineSlideMaster` authors a *layout* under\n * the one shared master, so a master's own shape tree has no write-side counterpart at all,\n * and a deck whose master carries none loses nothing — which is why this is a presence check\n * rather than an unconditional note.\n */\nexport function hasDecorativeShapes(element: unknown): boolean {\n\tconst spTree = child(child(element as ElementLike | null, OOXML_NS.p, 'cSld'), OOXML_NS.p, 'spTree')\n\treturn children(spTree).some(\n\t\t(shape) =>\n\t\t\tshape.namespaceURI === OOXML_NS.p && SHAPE_ELEMENTS.has(shape.localName ?? '') && !isPlaceholderShape(shape)\n\t)\n}\n","/**\n * `TextFrame` → `addText(TextProps[], TextPropsOptions)`.\n *\n * Two structural mismatches shape this mapper, and both are why the conversion is not a\n * field-by-field copy:\n *\n * 1. **The read model is a tree; `addText` takes a flat list.** OOXML nests runs inside\n * paragraphs; `TextProps[]` is one flat array where a paragraph boundary is a\n * `breakLine` flag on the item that *precedes* it. So the last run of each paragraph\n * carries the break, and a paragraph's own properties are replicated onto each of its\n * runs — the write path reads alignment and spacing off whichever run starts a line.\n *\n * 2. **Vocabularies differ on both sides of the same concept.** OOXML spells alignment\n * `l`/`ctr`/`r`/`just`, the write API spells it `left`/`center`/`right`/`justify`; two\n * of the six `@algn` values have no write spelling at all. Every such translation is a\n * table here rather than a pass-through, so an unmappable token produces a note instead\n * of an invalid option.\n *\n * Run-level reads prefer the *explicit* value over the resolved one, but only where leaving\n * the option out really does leave the value inherited. That is the part worth checking\n * rather than assuming: the round-trip harness found that an omitted run colour and an\n * omitted vertical anchor are both filled in by the write path — black, and centred — so\n * \"stay quiet and let it inherit\" was silently repainting text and re-anchoring bodies. Both\n * now emit the *resolved* value with a note, which freezes it against a later theme edit and\n * renders correctly, in preference to staying faithful in the IR and wrong on the slide.\n */\nimport type { BodyProperties, BulletDetail, BulletStyle, Paragraph, Run, TextFrame } from '../../read/api/text.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { IrValue } from '../ir.js'\nimport { compact, isWritableSchemeToken, literalColor, orUndefined, pointsToInches } from './values.js'\n\n/**\n * `a:pPr/@algn` → `HAlign`. `dist` and `thaiDist` (distributed justification) are\n * deliberately absent: the write API has no spelling for them, and mapping them onto\n * `justify` would be a silent visual change rather than a declared loss.\n */\nconst ALIGN: Record<string, string> = { l: 'left', ctr: 'center', r: 'right', just: 'justify' }\n\n/** `a:bodyPr/@anchor` → `VAlign`. */\nconst ANCHOR: Record<string, string> = { t: 'top', ctr: 'middle', b: 'bottom' }\n\n/** `AutofitMode` → the write API's `fit`. */\nconst FIT: Record<string, string> = { none: 'none', normAutofit: 'shrink', spAutoFit: 'resize' }\n\n/** `a:bodyPr/@vert` values the write API's `vert` accepts (`TextVertType`). */\nconst WRITABLE_VERT = new Set(['eaVert', 'horz', 'mongolianVert', 'vert', 'vert270', 'wordArtVert', 'wordArtVertRtl'])\n\n/**\n * The `a:buAutoNum/@type` values the write API's `numberType` names.\n *\n * This used to be the *discriminator* between a numbered and a character bullet, back when\n * the read model reported both as one tagged string. `BulletDetail.kind` does that now, so\n * the set has one job left: telling a scheme the write path can spell from one it cannot.\n */\nconst AUTO_NUMBER_TYPES = new Set([\n\t'alphaLcParenBoth',\n\t'alphaLcParenR',\n\t'alphaLcPeriod',\n\t'alphaUcParenBoth',\n\t'alphaUcParenR',\n\t'alphaUcPeriod',\n\t'arabicParenBoth',\n\t'arabicParenR',\n\t'arabicPeriod',\n\t'arabicPlain',\n\t'romanLcParenBoth',\n\t'romanLcParenR',\n\t'romanLcPeriod',\n\t'romanUcParenBoth',\n\t'romanUcParenR',\n\t'romanUcPeriod',\n])\n\n/**\n * `Paragraph.bulletDetail` → the write API's `bullet` option.\n *\n * This function used to take a **tagged** string — `'none'`, `'char:<glyph>'` or\n * `'autoNum:<type>'` — and its first version read it as a bare glyph. The result was silent\n * and universal: a paragraph that explicitly suppressed its bullet (`a:buNone`, which is most\n * of them) came back with a literal `n` bullet, because `'none'.codePointAt(0)` is `n`; a real\n * character bullet came back as `c`, from the `char:` tag; and a numbered list came back as\n * `a`. Every converted deck was affected and nothing failed, which is why the round-trip check\n * exists — and why the accessor is now a discriminated union with no parsing left to get wrong.\n */\nfunction bulletOption(bullet: BulletDetail, notes: NoteScope): IrValue {\n\t// Explicit suppression, and it must stay explicit: an omitted `bullet` lets the\n\t// destination list style put one back.\n\tif (bullet.kind === 'none') return false\n\n\t// A picture bullet's bytes would have to be re-embedded through the asset resolver, which\n\t// the paragraph mapper does not carry — `addText`'s `bullet.image` could author it.\n\tif (bullet.kind === 'picture') {\n\t\tnotes.note(\n\t\t\t'text.bullet.picture',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'this paragraph uses an image as its bullet glyph (a:buBlip); the text mapper has no asset resolver to re-embed it with, so the bullet falls back to the default character'\n\t\t)\n\t\treturn true\n\t}\n\n\tconst style = bulletStyle(bullet, notes)\n\n\tif (bullet.kind === 'autoNum') {\n\t\tif (!AUTO_NUMBER_TYPES.has(bullet.scheme)) {\n\t\t\tnotes.note(\n\t\t\t\t'text.bullet.numberType',\n\t\t\t\t'approximated',\n\t\t\t\t'unwritable',\n\t\t\t\t`numbering scheme \"${bullet.scheme}\" is outside the set the write API names, so the list falls back to the default scheme`\n\t\t\t)\n\t\t\treturn compact({ type: 'number', ...startAtOption(bullet.startAt), ...style }) ?? { type: 'number' }\n\t\t}\n\t\treturn (\n\t\t\tcompact({ type: 'number', numberType: bullet.scheme, ...startAtOption(bullet.startAt), ...style }) ?? {\n\t\t\t\ttype: 'number',\n\t\t\t}\n\t\t)\n\t}\n\n\t// Zero-padded to four digits, and that is load-bearing rather than cosmetic: the write\n\t// path tests `characterCode` against /^[0-9A-Fa-f]{4}$/ and, on a miss, warns to the\n\t// console and substitutes its own default glyph. So \"6E\" — a perfectly good code point —\n\t// silently became a different bullet character, visible only in the rendered slide.\n\tconst code = bullet.char.codePointAt(0) ?? 0x2022\n\tif (code > 0xffff) {\n\t\tnotes.note(\n\t\t\t'text.bullet.glyph',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph U+${code.toString(16).toUpperCase()} is outside the Basic Multilingual Plane and characterCode takes a four-digit code, so the bullet falls back to the write path's default glyph`\n\t\t)\n\t}\n\treturn compact({ characterCode: code.toString(16).toUpperCase().padStart(4, '0'), ...style }) ?? {}\n}\n\n/**\n * `a:pPr/@marL` / `@indent` → `paraMarginLeft` / `paraIndent`.\n *\n * A stated margin carries as its number. An *absent* one is the interesting case, because\n * leaving the key out does not reproduce it: every `bullet` state except `'inherit'` makes the\n * write path put a margin on the element — its hanging default for a drawn bullet, zero for\n * `bullet: false` — so a paragraph that inherits its margin has to ask for silence explicitly.\n * Under `bullet: 'inherit'` nothing is written either way and the key would be noise, which is\n * why the bullet option decides rather than the paragraph being asked twice.\n * @param {number|null} valuePt - the paragraph's own margin in points, `null` when unset\n * @param {IrValue} bulletValue - the `bullet` option this paragraph maps onto\n * @return {IrValue|undefined} the option value, or `undefined` to leave the key out\n */\nfunction paraMarginOption(valuePt: number | null, bulletValue: IrValue): IrValue | undefined {\n\tif (valuePt !== null) return valuePt\n\treturn bulletValue === 'inherit' ? undefined : 'inherit'\n}\n\n/**\n * `a:buAutoNum/@startAt` → `numberStartAt`.\n *\n * Numbering is content rather than styling: a list continuing \"5. Deploy\" that comes back as\n * \"1. Deploy\" is a different slide. `1` is the schema default, so emitting it would only add\n * noise to the printed script.\n */\nfunction startAtOption(startAt: number | null): Record<string, IrValue> {\n\treturn startAt === null || startAt === 1 ? {} : { numberStartAt: startAt }\n}\n\n/**\n * The bullet's own font, size and colour (`a:buFont` / `a:buSzPct` / `a:buClr`) as the write\n * API's `fontFace` / `size` / `color`.\n *\n * `a:buSzPts` has no write-API counterpart — `bullet.size` is a percentage of the run size —\n * so an absolute bullet size is the one part of this that still cannot carry.\n */\nfunction bulletStyle(bullet: BulletStyle, notes: NoteScope): Record<string, IrValue> {\n\tif (bullet.sizePt !== null) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePt',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this bullet sets an absolute glyph size (a:buSzPts); bullet.size is a percentage of the run size, so the absolute value has no write-API expression and the glyph follows the text size'\n\t\t)\n\t}\n\n\t// 25–400% is the range the write path accepts; outside it the option is rejected with a\n\t// console warning and the glyph silently falls back to full size, so it is declared here.\n\tconst sizePct = bullet.sizePct\n\tif (sizePct !== null && (sizePct < 25 || sizePct > 400)) {\n\t\tnotes.note(\n\t\t\t'text.bullet.sizePct',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet glyph size ${sizePct}% is outside the 25–400% range the write API accepts, so no a:buSzPct is emitted and the glyph size is left to be inherited`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\tfontFace: orUndefined(bullet.font),\n\t\t\tsize: sizePct === null || sizePct < 25 || sizePct > 400 ? undefined : sizePct,\n\t\t\tcolor: bulletColor(bullet, notes),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The bullet's colour, preferring the raw `schemeClr` token over the resolved literal for the\n * same reason {@link runColor} does: a token keeps tracking the destination theme.\n */\nfunction bulletColor(bullet: BulletStyle, notes: NoteScope): string | undefined {\n\tconst scheme = bullet.schemeColor\n\tif (isWritableSchemeToken(scheme)) return scheme as string\n\tif (bullet.color !== null) return literalColor(bullet.color)\n\tconst resolved = bullet.resolvedColor\n\tif (!resolved) return undefined\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'text.bullet.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`bullet scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t}\n\treturn literalColor(resolved.effectiveHex)\n}\n\n/**\n * Per-run character formatting, shared by shape text and table-cell text.\n *\n * The three decoration tokens carry their **explicit off** — `u=\"none\"`, `strike=\"noStrike\"`,\n * `cap=\"none\"` — rather than collapsing it into the unstated case. Stating one is a different\n * fact from stating nothing: run properties resolve down the `a:lstStyle` → placeholder →\n * layout → master chain, so a run that would take `u=\"sng\"` from its list style and states\n * `u=\"none\"` is *not* underlined, while the same run with the attribute dropped is. Only an\n * absent attribute (`null` here) means \"state nothing\"; each off token is a member of its\n * enumeration in its own right (ECMA-376 §20.1.10.81 / §20.1.10.78) and would be redundant\n * with omission otherwise.\n */\nexport function runOptions(run: Run, notes: NoteScope): Record<string, IrValue> | undefined {\n\tconst underline = run.underline\n\n\treturn compact({\n\t\tbold: orUndefined(run.bold),\n\t\titalic: orUndefined(run.italic),\n\t\tunderline: underline === null ? undefined : { style: underline },\n\t\tstrike: orUndefined(run.strike),\n\t\tfontSize: orUndefined(run.fontSizePt),\n\t\tfontFace: orUndefined(run.fontName),\n\t\tcolor: runColor(run, notes),\n\t\thighlight: run.highlight ? literalColor(run.highlight.effectiveHex) : undefined,\n\t\tcaps: orUndefined(run.caps),\n\t\t// The write API spells baseline shift as a percentage, the same unit the read\n\t\t// model reports, so superscript/subscript survive without a preset round-trip.\n\t\tbaseline: orUndefined(run.baselinePct),\n\t\thyperlink: hyperlinkOption(run),\n\t})\n}\n\n/**\n * A run's colour, preferring the raw `schemeClr` token over the resolved literal so the\n * text keeps tracking the destination theme. Only the ten tokens the write path's `clrMap`\n * covers survive as tokens; the other seven degrade to a literal hex there anyway, so\n * passing one through unchanged would produce a silently different colour.\n */\nfunction runColor(run: Run, notes: NoteScope): string | undefined {\n\tconst scheme = run.schemeColor\n\tif (isWritableSchemeToken(scheme)) return scheme as string\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'text.color.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t\tconst resolved = run.resolvedColor\n\t\treturn resolved ? literalColor(resolved.effectiveHex) : undefined\n\t}\n\tif (run.color !== null) return literalColor(run.color)\n\n\t// A run with no colour of its own inherits one, and leaving the option out does *not* pass\n\t// that inheritance along: `addText` fills an uncoloured non-placeholder run with\n\t// DEF_FONT_COLOR, so omitting it repaints the text black. That makes this a loss either\n\t// way, and which loss depends on whether the inherited colour can be resolved — so the two\n\t// outcomes are declared separately rather than under one note that would overstate one and\n\t// understate the other.\n\tconst inherited = run.resolvedColor\n\tif (!inherited) {\n\t\tnotes.note(\n\t\t\t'text.color.default',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t'this run inherits its colour and nothing resolves what it inherits (a table style tier, or a list style the read model does not walk), so the write path paints it black — the one case where the output colour is not merely frozen but possibly wrong'\n\t\t)\n\t\treturn undefined\n\t}\n\tnotes.note(\n\t\t'text.color.inherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\t'this run inherits its colour from the placeholder, master or theme; the write path paints an uncoloured run black instead of leaving it to inherit, so the inherited colour is resolved and baked in and no longer tracks a theme change'\n\t)\n\treturn literalColor(inherited.effectiveHex)\n}\n\n/**\n * A run's hyperlink. Only external links map: the read model reports an internal jump as a\n * target part name, while the write API takes a slide *number*, which the deck-level walk\n * resolves — so a slide link is handled there, not here.\n */\nfunction hyperlinkOption(run: Run): IrValue | undefined {\n\tconst link = run.hyperlink\n\tif (!link?.url) return undefined\n\treturn compact({ url: link.url, tooltip: link.tooltip ?? undefined })\n}\n\n/** Paragraph-level properties, replicated onto each of the paragraph's runs. */\nfunction paragraphOptions(paragraph: Paragraph, notes: NoteScope): Record<string, IrValue> {\n\tconst spacing = paragraph.lineSpacing\n\tconst bullet = paragraph.bulletDetail\n\tconst align = paragraph.align\n\n\tif (align !== null && !(align in ALIGN)) {\n\t\tnotes.note(\n\t\t\t'text.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`distributed alignment \"${align}\" has no write-API spelling, so the paragraph falls back to its inherited alignment`\n\t\t)\n\t}\n\tif (paragraph.spaceBeforePt === 0 || paragraph.spaceAfterPt === 0) {\n\t\tnotes.note(\n\t\t\t'text.paraSpaceZero',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this paragraph explicitly sets zero space before or after (a:spcBef / a:spcAft of 0), which suppresses the spacing its list style would otherwise apply; the write path treats 0 as \"unset\" and emits nothing, so the inherited spacing comes back'\n\t\t)\n\t}\n\t// `text.indent` used to be filed here — a paragraph's own `a:pPr/@marL` and `@indent` had no\n\t// write option at all, so every margin it stated was replaced by whatever the `bullet` state\n\t// wrote. `paraMarginLeft` / `paraIndent` state them now, so the mapper carries the values\n\t// instead of excusing their loss and the note is gone rather than unmapped.\n\tconst bulletValue = bullet === null ? 'inherit' : bulletOption(bullet, notes)\n\n\treturn (\n\t\tcompact({\n\t\t\talign: align === null ? undefined : ALIGN[align],\n\t\t\tindentLevel: paragraph.level === 0 ? undefined : paragraph.level,\n\t\t\tparaMarginLeft: paraMarginOption(paragraph.marginLeftPt, bulletValue),\n\t\t\tparaIndent: paraMarginOption(paragraph.indentPt, bulletValue),\n\t\t\tparaSpaceBefore: orUndefined(paragraph.spaceBeforePt),\n\t\t\tparaSpaceAfter: orUndefined(paragraph.spaceAfterPt),\n\t\t\tlineSpacing: spacing?.type === 'points' ? spacing.valuePt : undefined,\n\t\t\tlineSpacingMultiple: spacing?.type === 'percent' ? spacing.percent / 100 : undefined,\n\t\t\t// A paragraph with no bullet child of its own states nothing, and `'inherit'` is\n\t\t\t// how the write path says that. `undefined` would NOT do — an omitted `bullet`\n\t\t\t// emits an explicit `a:buNone`, which suppresses whatever the destination list\n\t\t\t// style has. That was this converter's most frequent loss (`text.bullet.inherited`,\n\t\t\t// 34 of 44 corpus fixtures) until the option gained a third state. Resolved above\n\t\t\t// rather than here: the margin keys need to know which bullet state was chosen, and\n\t\t\t// calling `bulletOption` twice would file its notes twice.\n\t\t\tbullet: bulletValue,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * Flatten a text frame into the `TextProps[]` first argument of `addText`.\n *\n * An empty paragraph becomes an item with empty text and a `breakLine`, which is how a\n * blank line survives — dropping it would silently close up vertical space the author put\n * there deliberately.\n */\nexport function textRuns(frame: TextFrame, notes: NoteScope): IrValue[] {\n\tconst paragraphs = frame.paragraphs\n\tconst items: IrValue[] = []\n\n\tparagraphs.forEach((paragraph, paragraphIndex) => {\n\t\tconst paraOpts = paragraphOptions(paragraph, notes)\n\t\tconst runs = paragraph.runs\n\t\t// The paragraph break rides on the last run of every paragraph but the final one;\n\t\t// a trailing break would add an empty line the frame never had.\n\t\tconst breaks = paragraphIndex < paragraphs.length - 1\n\n\t\tif (runs.length === 0) {\n\t\t\titems.push({ text: '', options: compact({ ...paraOpts, breakLine: breaks }) ?? {} })\n\t\t\treturn\n\t\t}\n\n\t\truns.forEach((run, runIndex) => {\n\t\t\tconst isLastRun = runIndex === runs.length - 1\n\t\t\t// `bullet` goes on the first run only, unlike the other paragraph properties. The\n\t\t\t// write path treats a bullet on a run that is *not* starting a line as a request for\n\t\t\t// a new paragraph — and clears that run's `breakLine` while it is at it — so\n\t\t\t// replicating the bullet split every bulleted paragraph that had more than one run.\n\t\t\t// It reads paragraph properties off whichever run opens the line, so once is enough.\n\t\t\tconst continuation = { ...paraOpts }\n\t\t\tdelete continuation['bullet']\n\t\t\tconst options = compact({\n\t\t\t\t...(runIndex === 0 ? paraOpts : continuation),\n\t\t\t\t...runOptions(run, notes),\n\t\t\t\t...(isLastRun && breaks ? { breakLine: true } : {}),\n\t\t\t})\n\t\t\titems.push(compact({ text: run.text, options }) ?? { text: run.text })\n\t\t})\n\t})\n\n\treturn items\n}\n\n/**\n * Frame-level layout for the `TextPropsOptions` second argument — everything that belongs\n * to the body as a whole rather than to any paragraph.\n *\n * `resolvedAnchor` is the one place a *resolved* read is the right one: vertical anchoring\n * has no per-run fallback, so an unset `a:bodyPr/@anchor` genuinely means \"whatever the\n * placeholder says\", and an appended shape does not inherit that.\n */\nexport function textFrameOptions(frame: TextFrame, notes: NoteScope): Record<string, IrValue> {\n\tconst body = frame.bodyProperties\n\tconst anchor = frame.resolvedAnchor\n\tconst vert = body?.vert ?? null\n\n\tif (vert !== null && !WRITABLE_VERT.has(vert)) {\n\t\tnotes.note(\n\t\t\t'text.vert',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`text direction \"${vert}\" is outside TextVertType, so the body falls back to horizontal`\n\t\t)\n\t}\n\n\treturn (\n\t\tcompact({\n\t\t\t// Spelled out even when nothing in the source set it. `resolvedAnchor` returning\n\t\t\t// null means PowerPoint would default the body to top — but `addText` defaults a\n\t\t\t// non-placeholder body to *centre*, so leaving the option out re-anchors the text.\n\t\t\tvalign: anchor === null ? 'top' : ANCHOR[anchor],\n\t\t\t// `@wrap` is `square`/`none` in OOXML and a boolean in the write API.\n\t\t\twrap: body?.wrap === null || body?.wrap === undefined ? undefined : body.wrap !== 'none',\n\t\t\tvert: vert !== null && WRITABLE_VERT.has(vert) ? vert : undefined,\n\t\t\tfit: fitOption(frame, notes),\n\t\t\tmargin: marginOption(body),\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * `a:bodyPr`'s autofit as the write API's `fit`.\n *\n * A `normAutofit` that bakes `fontScale` or `lnSpcReduction` is a *different state* from a\n * bare `<a:normAutofit/>`, so the two get different spellings. ECMA-376 §21.1.2.1.3 defaults\n * each attribute to 100%/0% only when it is **omitted**; PowerPoint recomputes an unbaked\n * scale on edit and draws the baked one exactly as written until then. Flattening both to\n * `'shrink'` therefore re-emits a frame that paints its text at full size — a deck baked at\n * `fontScale=\"40000\"` comes back two and a half times too large — and the object form is\n * already what the write API accepts, so nothing has to be lost here.\n *\n * Out-of-range percentages are the one arm that still loses something. The write path rejects\n * anything outside 0–100 and drops the attribute with a warning, so passing one through would\n * turn a declared loss into a silent one; the frame falls back to bare `'shrink'` with a note.\n */\nfunction fitOption(frame: TextFrame, notes: NoteScope): IrValue | undefined {\n\tconst autofit = frame.autofit\n\tif (autofit === null) return undefined\n\tif (autofit !== 'normAutofit') return FIT[autofit]\n\n\tconst baked = compact({\n\t\tfontScale: bakedPct(frame.autofitFontScale, 'fontScale', notes),\n\t\tlnSpcReduction: bakedPct(frame.autofitLineSpaceReduction, 'lnSpcReduction', notes),\n\t})\n\treturn baked ? { type: 'shrink', ...baked } : FIT[autofit]\n}\n\n/** A baked `a:normAutofit` percentage, or `undefined` (with a note) when the write API would reject it. */\nfunction bakedPct(value: number | null, name: string, notes: NoteScope): number | undefined {\n\tif (value === null) return undefined\n\tif (value >= 0 && value <= 100) return value\n\tnotes.note(\n\t\t`text.autofit.${name}`,\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`baked a:normAutofit/@${name} of ${value}% is outside the 0-100 the write API accepts, so the frame re-emits a bare <a:normAutofit/>`\n\t)\n\treturn undefined\n}\n\n/**\n * `a:bodyPr` insets as the write API's `margin`.\n *\n * A unit change, not just a copy: the read model reports insets in points, `margin` takes\n * **inches**, and it warns on any value `>= 1` on the assumption it is a stray points\n * value. Passing points straight through would therefore both inset the text by roughly\n * 72× too much and trip that warning.\n *\n * Emitted as the four-tuple whenever any inset is set, since a partial tuple is not\n * expressible; an unset side takes PowerPoint's own default rather than zero, so those are\n * spelled out — defaulting them to 0 would visibly reflow every body that sets one side.\n */\nconst DEFAULT_INSETS_PT = { left: 7.2, right: 7.2, top: 3.6, bottom: 3.6 }\n\nfunction marginOption(body: BodyProperties | null): IrValue | undefined {\n\tconst insets = body?.insetsPt\n\tif (!insets) return undefined\n\tconst { left, right, top, bottom } = insets\n\tif (left === undefined && right === undefined && top === undefined && bottom === undefined) return undefined\n\treturn [\n\t\tpointsToInches(top ?? DEFAULT_INSETS_PT.top),\n\t\tpointsToInches(right ?? DEFAULT_INSETS_PT.right),\n\t\tpointsToInches(bottom ?? DEFAULT_INSETS_PT.bottom),\n\t\tpointsToInches(left ?? DEFAULT_INSETS_PT.left),\n\t]\n}\n","/**\n * `Table` → `addTable(TableRow[], TableProps)`.\n *\n * Tables are the one place the exact-EMU rule stops. `colW` and `rowH` are number-typed\n * (inches) rather than `Coord`-typed, so they cannot take a raw-EMU string the way every\n * position and size can. They print at six decimal places, which is the measured minimum\n * at which `Math.round(inches × 914400)` returns the original EMU — the drift is bounded\n * at 0.4572 EMU, roughly half a millionth of an inch, and rounding shorter to make the\n * numbers look tidy would turn a cosmetic problem into a real geometry loss.\n *\n * Table *style* is the opposite story, and better than it looks. A style is a GUID into\n * the deck's `ppt/tableStyles.xml`, and a template-anchored output keeps that part intact,\n * so passing the source GUID through reproduces the banding, header shading, and borders\n * exactly rather than approximately. That is why per-cell fills read off the style graph\n * are deliberately *not* baked into each cell here: doing so would freeze the appearance\n * and stop the table responding to its own style.\n */\nimport type { CellBorder, Table, TableCell } from '../../read/api/table.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\nimport { compact, inches, literalColor, orUndefined, positionOfFrame } from './values.js'\nimport { pictureFillOption, type PictureFillSubject } from './picture-fill.js'\nimport { gradientStops, patternOption } from './surface-fill.js'\nimport { runOptions, textRuns } from './text.js'\n\n/** How {@link pictureFillOption}'s notes name a cell. */\nconst CELL_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'table.cell.fill.picture',\n\tsubject: 'this table cell',\n\telement: 'a:tcPr/a:blipFill',\n}\n\n/** How {@link pictureFillOption}'s notes name the table's own background. */\nconst TABLE_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'table.fill.picture',\n\tsubject: 'this table',\n\telement: 'a:tblPr/a:blipFill',\n}\n\n/** `a:tcPr/@anchor` → the write API's `valign`. */\nconst ANCHOR: Record<string, string> = { t: 'top', ctr: 'middle', b: 'bottom' }\n\nexport function tableCall(frame: GraphicFrame, table: Table, notes: NoteScope, assets: AssetResolver): CallIr {\n\tconst styleId = table.styleId\n\tconst hasStyle = table.resolvedStyle !== null\n\tconst rows: IrValue[] = []\n\tconst rowHeights: number[] = []\n\n\tfor (const row of table.rows) {\n\t\tconst cells: IrValue[] = []\n\t\tfor (const cell of row.cells) {\n\t\t\t// A merge continuation is the covered half of a span: it carries no content and\n\t\t\t// exists only so the grid stays rectangular. The write path derives those from\n\t\t\t// colspan/rowspan, so emitting them would double-count the span.\n\t\t\tif (cell.isMergeContinuation) continue\n\t\t\tcells.push(cellIr(cell, hasStyle, notes, assets))\n\t\t}\n\t\trows.push(cells)\n\t\trowHeights.push(row.heightEmu ?? 0)\n\t}\n\n\t// A row of height 0 is PowerPoint's \"auto — as tall as its content needs\", not a\n\t// zero-height row, and neither the mixed nor the all-auto case survives the write path.\n\t// Nothing is visibly wrong either way; what is lost is the *implicitness*, which matters\n\t// the moment someone edits a cell and expects the row to grow.\n\t//\n\t// The all-auto case is the more common of the two — a table authored without explicit row\n\t// heights has `a:tr/@h=\"0\"` on every row — and it went undeclared for longer precisely\n\t// because it looks like the harmless one. It is the case where `rowH` is omitted entirely\n\t// below, and `addTable` then divides the frame height evenly rather than leaving the rows\n\t// auto, so three auto rows come back pinned to a third of the frame each.\n\tconst autoRows = rowHeights.filter((height) => height === 0).length\n\tif (autoRows === rowHeights.length && autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'every row is auto-height (a:tr/@h of 0), so no rowH is emitted and addTable divides the frame height evenly among the rows; the rows come back pinned to that even split rather than sized to their content'\n\t\t)\n\t} else if (autoRows > 0) {\n\t\tnotes.note(\n\t\t\t'table.rowAuto',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t'at least one row is auto-height (a:tr/@h of 0) while others are not; rowH must be given for every row or none, so the auto rows are emitted as 0 and come back pinned to the height their content produced'\n\t\t)\n\t}\n\n\tif (styleId === null) {\n\t\tnotes.note(\n\t\t\t'table.style',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this table names no a:tableStyleId, so it takes the generated deck's default table style\"\n\t\t)\n\t}\n\n\tconst columnWidths = table.columnWidths\n\tconst options = compact({\n\t\t...positionOfFrame(frame),\n\t\tobjectName: frame.name || undefined,\n\t\t// The source GUID resolves against the destination's own tableStyles.xml, which a\n\t\t// template-anchored output carries over intact.\n\t\ttableStyle: orUndefined(styleId),\n\t\t// `tableFill`, not `fill`: the source has one fill on `a:tblPr`, and `fill` would\n\t\t// flatten it into a copy on every cell, which is a different package for the same\n\t\t// picture. See `TableProps.tableFill`.\n\t\ttableFill: tableFill(table, notes, assets),\n\t\thasHeader: table.firstRowHeader ? true : undefined,\n\t\thasBandedRows: table.bandedRows ? true : undefined,\n\t\tcolW: columnWidths.every((w) => w === null) ? undefined : columnWidths.map((w) => inches(w ?? 0)),\n\t\trowH: rowHeights.every((h) => h === 0) ? undefined : rowHeights.map(inches),\n\t})\n\n\treturn { method: 'addTable', args: [rows, options ?? {}], ...(frame.name ? { sourceName: frame.name } : {}) }\n}\n\n/**\n * The table's own background (`a:tblPr` fill).\n *\n * Simpler than {@link cellFill}, and for one reason: a `a:tblPr` fill can only be the\n * table's own. There is no style graph feeding into it, so there is no\n * own-versus-inherited ambiguity to be careful about and the resolved colour can be used\n * directly. A scheme token still wins over the literal when there is one, so the replica\n * keeps tracking its theme.\n */\nfunction tableFill(table: Table, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\tconst gradient = table.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'table.fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(table.patternFill)\n\tif (pattern) return pattern\n\n\tconst picture = table.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, TABLE_PICTURE_FILL)\n\n\tconst scheme = table.fillSchemeColor\n\tif (scheme !== null) return { color: scheme }\n\n\tconst resolved = table.resolvedFill\n\treturn resolved ? { color: literalColor(resolved.effectiveHex) } : undefined\n}\n\n/**\n * One cell as a `TableCell`.\n *\n * Cell text reuses the shape text mapper, so a per-run format inside a cell behaves\n * identically to one on a shape — the read model already shares `TextFrame` between the\n * two, and diverging here would be a difference with no cause.\n */\nfunction cellIr(cell: TableCell, hasStyle: boolean, notes: NoteScope, assets: AssetResolver): IrValue {\n\tconst frame = cell.textFrame\n\tconst anchor = cell.anchor\n\tconst margins = cell.marginsEmu\n\n\t// `a:tc/@id` and `a:tcPr/a:headers` are the one pair here that is *deliberately* not\n\t// mapped. PowerPoint strips both on save (probe:\n\t// `test/read/fixtures/authoring/probe-table-cell-a11y-and-3d.ps1`), so there is no write\n\t// option to map them to and adding one would ship a feature that dies on the first save.\n\t// A source deck from another producer can still carry them, so the loss is recorded.\n\tif (cell.id !== null || cell.headerIds.length > 0) {\n\t\tnotes.note(\n\t\t\t'table.cell.headers',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this cell carries a screen-reader header association (a:tc/@id / a:tcPr/a:headers); PowerPoint strips both on save, so there is no write option and the association is lost — hasHeader (a:tblPr/@firstRow) is the marker that survives'\n\t\t)\n\t}\n\n\tconst options = compact({\n\t\tfill: cellFill(cell, hasStyle, notes, assets),\n\t\tborder: cellBorders(cell, notes),\n\t\tdiagonal: cellDiagonals(cell, notes),\n\t\tanchorCtr: cell.anchorCtr ? true : undefined,\n\t\tcell3D: cellThreeD(cell),\n\t\tvalign: anchor === null ? undefined : ANCHOR[anchor],\n\t\t// `textDirection` reaches `a:tcPr/@vert` through the same table-cell inheritance list every\n\t\t// other cell option uses, so a vertical label survives the round trip. Anything outside the\n\t\t// option's own union would be written back out verbatim as an invalid attribute.\n\t\ttextDirection: cellTextDirection(cell, notes),\n\t\t// Only the two values the write option accepts survive; anything else in the source\n\t\t// deck would be written straight back out as an invalid attribute.\n\t\thorzOverflow: cell.horzOverflow === 'clip' || cell.horzOverflow === 'overflow' ? cell.horzOverflow : undefined,\n\t\tcolspan: cell.gridSpan > 1 ? cell.gridSpan : undefined,\n\t\trowspan: cell.rowSpan > 1 ? cell.rowSpan : undefined,\n\t\t// `margin` takes inches, and the read model reports the insets in EMU.\n\t\tmargin: margins\n\t\t\t? [inches(margins.top ?? 0), inches(margins.right ?? 0), inches(margins.bottom ?? 0), inches(margins.left ?? 0)]\n\t\t\t: undefined,\n\t\t// A cell's own runs may each carry formatting; the first run's options double as the\n\t\t// cell default, which is how the write path applies cell-level character formatting.\n\t\t...(frame?.paragraphs[0]?.runs[0] ? (runOptions(frame.paragraphs[0].runs[0], notes) ?? {}) : {}),\n\t})\n\n\treturn compact({ text: frame ? textRuns(frame, notes) : cell.text, options }) ?? { text: '' }\n}\n\n/**\n * The two corner-to-corner rules as `TableCellProps.diagonal`.\n *\n * Kept out of {@link cellBorders}' tuple for the same reason the write option is: they are\n * not edges. Every dash and colour a diagonal can carry is one an edge can, so they share\n * {@link borderIr} — including its out-of-enum dash note.\n */\nfunction cellDiagonals(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders || (!borders.tlToBr && !borders.blToTr)) return undefined\n\treturn compact({\n\t\ttlToBr: borders.tlToBr ? borderIr(borders.tlToBr, notes) : undefined,\n\t\tblToTr: borders.blToTr ? borderIr(borders.blToTr, notes) : undefined,\n\t})\n}\n\n/**\n * A cell's `a:cell3D` as `TableCellProps.cell3D`.\n *\n * Every field is passed through as read: the write path vets each against its `ST_` union\n * before emission, so a value from a source deck that somehow falls outside one is caught\n * there rather than being screened twice with two chances to disagree. Sizes are already in\n * points on both sides.\n */\nfunction cellThreeD(cell: TableCell): IrValue | undefined {\n\tconst cell3D = cell.cell3D\n\tif (!cell3D) return undefined\n\tconst rig = cell3D.lightRig\n\treturn (\n\t\tcompact({\n\t\t\tpreset: orUndefined(cell3D.bevel.preset),\n\t\t\twidth: orUndefined(cell3D.bevel.widthPt),\n\t\t\theight: orUndefined(cell3D.bevel.heightPt),\n\t\t\tmaterial: orUndefined(cell3D.material),\n\t\t\t// CT_LightRig requires both, so a half-specified one from a source deck is dropped\n\t\t\t// rather than passed on for the emitter to reject.\n\t\t\tlightRig: rig?.rig && rig.dir ? { rig: rig.rig, dir: rig.dir } : undefined,\n\t\t}) ?? {}\n\t)\n}\n\n/** The `ST_TextVerticalType` values `TextBaseProps.textDirection` accepts. */\nconst WRITABLE_TEXT_DIRECTIONS = new Set(['horz', 'vert', 'vert270', 'wordArtVert'])\n\n/**\n * A cell's `a:tcPr/@vert` as the write API's `textDirection`.\n *\n * `ST_TextVerticalType` has nine values and the write option covers four. The rest\n * (`eaVert`, `mongolianVert`, the WordArt right-to-left variants) are East-Asian layout\n * modes with no `TextBaseProps` spelling, so they are noted rather than written — passing\n * one straight through would put a value the option does not admit into the attribute.\n */\nfunction cellTextDirection(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst vert = cell.verticalText\n\tif (vert === null || vert === 'horz') return undefined\n\tif (WRITABLE_TEXT_DIRECTIONS.has(vert)) return vert\n\tnotes.note(\n\t\t'table.cell.vert',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t`this cell's a:tcPr/@vert is \\`${vert}\\`, which textDirection does not spell (it covers horz/vert/vert270/wordArtVert), so its text lands horizontal`\n\t)\n\treturn undefined\n}\n\n/**\n * A cell's fill.\n *\n * The question here is not \"what colour is this cell\" but \"what did the *source* say\", and\n * the two differ for a styled table: `resolvedFill` answers the first, folding the cell's\n * own `a:solidFill` together with the colour it merely inherits from the style's\n * header/banding rules. Writing an inherited colour back would turn every banded cell into\n * an explicitly-filled one — the copy looks right until someone changes its table style, and\n * then nothing moves.\n *\n * {@link TableCell.hasOwnFill} separates them: an `a:tcPr` either carries an\n * `EG_FillProperties` child or it does not. So a cell's own fill is emitted (in whatever\n * form it took), and a cell with none is left to the style GUID, which reproduces the\n * banding exactly rather than approximately. Neither case loses anything, which is why\n * neither records a note.\n */\nfunction cellFill(cell: TableCell, hasStyle: boolean, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\t// An explicit `a:noFill` is a statement, and the one `EG_FillProperties` member whose\n\t// loss is invisible further down: a suppressed cell reports `null` from every colour\n\t// accessor, so without this it falls out of the bottom as \"no fill option\" and the copy\n\t// takes the style's banding — the opposite of what the source shows. Same distinction\n\t// `lineOption` makes for `lineNoFill` on the shape side.\n\tif (cell.fillNoFill) return { type: 'none' }\n\n\t// Every non-solid choice comes next, and for one shared reason: a cell whose `a:tcPr`\n\t// holds a `a:gradFill`/`a:pattFill`/`a:blipFill` holds no `a:solidFill` for the colour\n\t// legs below to find, so `resolvedFill` would answer with the table style's banding\n\t// colour and paint over the cell with something the source never showed.\n\tconst gradient = cell.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'table.cell.fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(cell.patternFill)\n\tif (pattern) return pattern\n\n\tconst picture = cell.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, CELL_PICTURE_FILL)\n\n\tconst scheme = cell.fillSchemeColor\n\tif (scheme !== null) return { color: scheme }\n\n\t// A styled cell with no fill of its own takes the style's banding, and the style GUID\n\t// travels with the table — so emitting nothing here is not a loss, it is what keeps the\n\t// copy responsive to its own style.\n\tif (hasStyle && !cell.hasOwnFill) return undefined\n\n\tconst resolved = cell.resolvedFill\n\tif (!resolved) return undefined\n\t// Reached only when the cell's fill IS its own: either there is no style to inherit from,\n\t// or `hasOwnFill` said so. The literal is exact for a `srgbClr`, and for the rarer colour\n\t// models (`a:sysClr`, `a:prstClr`, `a:hslClr`, …) it is the colour they resolve to, which\n\t// is the closest the write API's hex option can come.\n\treturn { color: literalColor(resolved.effectiveHex) }\n}\n\n/**\n * The four edge borders as the write API's `[top, right, bottom, left]` tuple.\n *\n * A suppressed edge (`a:noFill`) becomes `type: 'none'`, which is distinct from an absent\n * one — the first means \"deliberately no rule here\", the second means \"inherit\". The two\n * diagonals the read model also decodes are carried separately, by {@link cellDiagonals}.\n */\nfunction cellBorders(cell: TableCell, notes: NoteScope): IrValue | undefined {\n\tconst borders = cell.borders\n\tif (!borders) return undefined\n\n\tconst edges = [borders.top, borders.right, borders.bottom, borders.left]\n\tif (edges.every((edge) => edge === null)) return undefined\n\n\treturn edges.map((edge) => borderIr(edge, notes))\n}\n\n/** The `ST_PresetLineDashVal` tokens `BorderProps.dashType` accepts. */\nconst WRITABLE_DASHES = new Set([\n\t'solid',\n\t'dot',\n\t'dash',\n\t'lgDash',\n\t'dashDot',\n\t'lgDashDot',\n\t'lgDashDotDot',\n\t'sysDash',\n\t'sysDot',\n\t'sysDashDot',\n\t'sysDashDotDot',\n])\n\n/**\n * One decoded edge (or diagonal) as `BorderProps`.\n *\n * `type` stays the coarse on/off switch and `dashType` carries the exact preset, so a\n * `lgDashDot` rule comes back as itself rather than as the generic `sysDash` every dash\n * used to collapse onto. A dash outside `ST_PresetLineDashVal` cannot have come from a\n * conformant deck, so it is dropped to a plain dashed rule and noted.\n */\nfunction borderIr(edge: CellBorder | null, notes: NoteScope): IrValue {\n\tif (!edge) return {}\n\tif (edge.noFill) return { type: 'none' }\n\tconst dash = edge.dash\n\tconst known = dash === null || WRITABLE_DASHES.has(dash)\n\tif (!known) {\n\t\tnotes.note(\n\t\t\t'table.cell.borders.dash',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`a cell border's a:prstDash/@val is \\`${dash}\\`, which is outside ST_PresetLineDashVal; it is written as a plain dashed rule`\n\t\t)\n\t}\n\treturn (\n\t\tcompact({\n\t\t\ttype: dash === null || dash === 'solid' ? 'solid' : 'dash',\n\t\t\t// `solid` is what an absent/solid dash already implies, so emitting it would be noise.\n\t\t\tdashType: known && dash !== null && dash !== 'solid' ? dash : undefined,\n\t\t\tcolor: edge.schemeColor ?? (edge.color === null ? undefined : literalColor(edge.color)),\n\t\t\twidth: orUndefined(edge.widthPt),\n\t\t}) ?? {}\n\t)\n}\n","/**\n * `Chart` → `addChart(OptsChartData[], ChartOpts)`.\n *\n * The open question this mapper settles is where the data comes from. A `.pptx` chart\n * carries its numbers twice: once in an embedded `.xlsx` workbook, and once as *cached*\n * values inside the chart XML itself (`c:tx`, `c:cat`, `c:val`) so a viewer can render\n * without opening the workbook. Probing the fixtures showed the cache is complete for\n * every chart the write API can express, so the workbook never needs cracking — which\n * removes a whole spreadsheet parser from this project's dependency surface.\n *\n * The one seam is blanks. The read model reports `(number | null)[]`, since a cached point\n * may legitimately be empty, while `OptsChartData.values` is `number[]`. A blank becomes\n * `0`, which is a visible change on a line chart — a gap turns into a dip to the axis — so\n * it is noted rather than quietly coerced.\n *\n * A rebuilt chart also gets a *regenerated* workbook rather than the source one, so\n * double-clicking it in PowerPoint opens data that matches the plot but has lost the source\n * sheet's formulas, extra columns, and formatting.\n */\nimport type { Chart } from '../../read/api/chart.js'\nimport type { GraphicFrame } from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { CallIr, IrValue } from '../ir.js'\nimport { compact, literalColor, orUndefined, positionOfFrame } from './values.js'\n\n/**\n * Read chart-group token → `CHART_NAME`. The read model strips the `Chart` suffix from the\n * plot-area element name, so `c:barChart` arrives as `bar`. A 3-D group maps onto the\n * matching flat type where one exists; anything absent from this table has no write-API\n * chart type and is reported rather than guessed at.\n */\nconst CHART_TYPE: Record<string, string> = {\n\tarea: 'area',\n\tarea3D: 'area',\n\tbar: 'bar',\n\tbar3D: 'bar3D',\n\tbubble: 'bubble',\n\tbubble3D: 'bubble3D',\n\tdoughnut: 'doughnut',\n\tline: 'line',\n\tline3D: 'line',\n\tpie: 'pie',\n\tpie3D: 'pie',\n\tradar: 'radar',\n\tscatter: 'scatter',\n\tstock: 'stock',\n\tsurface: 'surface',\n\tsurface3D: 'surface',\n}\n\n/** `c:legendPos/@val` → the write API's `legendPos`. */\nconst LEGEND_POS: Record<string, string> = { r: 'r', l: 'l', t: 't', b: 'b', tr: 'tr' }\n\nexport function chartCall(frame: GraphicFrame, chart: Chart, notes: NoteScope): CallIr | null {\n\tconst sourceType = chart.chartType\n\tconst type = sourceType === null ? undefined : CHART_TYPE[sourceType]\n\tif (!type) {\n\t\tnotes.note(\n\t\t\t'chart.type',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`chart type \"${sourceType ?? 'none'}\" has no write-API counterpart, so the chart is omitted`\n\t\t)\n\t\treturn null\n\t}\n\n\tif (chart.chartTypes.length > 1) {\n\t\tnotes.note(\n\t\t\t'chart.combo',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`a combo chart (${chart.chartTypes.join(' + ')}) is emitted as a single ${type} chart; addChart's multi-type form needs a per-series type the read model does not report`\n\t\t)\n\t}\n\n\tnotes.note(\n\t\t'chart.workbook',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t\"the chart is rebuilt from its cached plot values, so its embedded workbook is regenerated: the plotted numbers match, but the source sheet's formulas, extra columns and formatting are gone\"\n\t)\n\n\tconst data = seriesData(chart, notes)\n\tif (data.length === 0) {\n\t\tnotes.note('chart.data', 'dropped', 'unsupported', 'this chart caches no plottable series values')\n\t\treturn null\n\t}\n\n\t// `type` is an *option*, not a positional argument: the signature is\n\t// `addChart(data, options & { type })`. Passing it separately produces a call that\n\t// typechecks nowhere and throws \"a chart `type` is required\" at run time.\n\tconst options = compact({\n\t\ttype,\n\t\t...positionOfFrame(frame),\n\t\tobjectName: frame.name || undefined,\n\t\t...titleOptions(chart),\n\t\t...legendOptions(chart),\n\t\t...labelOptions(chart),\n\t\t...axisOptions(chart),\n\t\tchartColors: seriesColors(chart),\n\t})\n\n\treturn {\n\t\tmethod: 'addChart',\n\t\targs: [data, options ?? { type }],\n\t\t...(frame.name ? { sourceName: frame.name } : {}),\n\t}\n}\n\n/**\n * Series as `OptsChartData[]`. Category labels ride on the first series, which is the shape\n * `addChart` expects; the read model reports them per-series but they are shared in\n * practice.\n */\nfunction seriesData(chart: Chart, notes: NoteScope): IrValue[] {\n\tconst categories = chart.categories.map((label) => label ?? '')\n\tlet sawBlank = false\n\n\tconst data = chart.series.map((series, index) => {\n\t\tconst values = series.values.map((value) => {\n\t\t\tif (value === null) sawBlank = true\n\t\t\treturn value ?? 0\n\t\t})\n\t\treturn (\n\t\t\tcompact({\n\t\t\t\tname: orUndefined(series.name),\n\t\t\t\tvalues,\n\t\t\t\t// Only the first series carries labels, matching how addChart reads them.\n\t\t\t\tlabels: index === 0 && categories.length > 0 ? categories : undefined,\n\t\t\t}) ?? { values }\n\t\t)\n\t})\n\n\tif (sawBlank) {\n\t\tnotes.note(\n\t\t\t'chart.blanks',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t'a blank cached data point becomes 0, because OptsChartData.values is number[] and has no spelling for a gap; on a line chart this draws a dip to the axis where the source showed a break'\n\t\t)\n\t}\n\treturn data\n}\n\nfunction titleOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst title = chart.title\n\treturn title === null ? {} : { showTitle: true, title }\n}\n\nfunction legendOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst legend = chart.legend\n\tif (!legend) return { showLegend: false }\n\treturn {\n\t\tshowLegend: true,\n\t\tlegendPos: legend.position === null ? undefined : LEGEND_POS[legend.position],\n\t}\n}\n\nfunction labelOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst labels = chart.dataLabels\n\tif (!labels) return {}\n\treturn {\n\t\tshowValue: labels.showValue ?? undefined,\n\t\tshowSerName: labels.showSeriesName ?? undefined,\n\t\tshowCatName: labels.showCategoryName ?? undefined,\n\t\tshowPercent: labels.showPercent ?? undefined,\n\t\tshowLegendKey: labels.showLegendKey ?? undefined,\n\t\tshowLeaderLines: labels.showLeaderLines ?? undefined,\n\t\tdataLabelPosition: orUndefined(labels.position),\n\t\tdataLabelFormatCode: labels.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Axis bounds, titles and gridlines. The write API spells these as a flat `catAxis*` /\n * `valAxis*` prefix set rather than an axis object, so each side is unpacked by hand.\n */\nfunction axisOptions(chart: Chart): Record<string, IrValue | undefined> {\n\tconst cat = chart.categoryAxis\n\tconst val = chart.valueAxis\n\treturn {\n\t\tcatAxisHidden: cat?.hidden ? true : undefined,\n\t\tcatAxisTitle: cat?.title ?? undefined,\n\t\tvalAxisHidden: val?.hidden ? true : undefined,\n\t\tvalAxisTitle: val?.title ?? undefined,\n\t\tvalAxisMinVal: val?.min ?? undefined,\n\t\tvalAxisMaxVal: val?.max ?? undefined,\n\t\tvalAxisMajorUnit: val?.majorUnit ?? undefined,\n\t\tvalAxisLabelFormatCode: val?.numberFormat?.formatCode ?? undefined,\n\t}\n}\n\n/**\n * Per-series fill colours as `chartColors`, which is positional — entry `n` colours series\n * `n`. A series with no explicit fill takes the theme's accent for its position, which the\n * read model does not resolve, so the whole option is dropped unless every series names a\n * colour; a partial list would silently recolour the unnamed ones.\n */\nfunction seriesColors(chart: Chart): IrValue | undefined {\n\tconst series = chart.series\n\tif (series.length === 0) return undefined\n\tconst colors: string[] = []\n\tfor (const one of series) {\n\t\tconst fill = one.fill\n\t\tconst hex = fill?.color\n\t\tif (!hex) return undefined\n\t\tcolors.push(literalColor(hex))\n\t}\n\treturn colors\n}\n","/**\n * `AnyShape` → one {@link CallIr}.\n *\n * The dispatch is on what the shape *is*, not on what it looks like: an `AutoShape` with a\n * text frame and no geometry is an `addText`, one with geometry is an `addShape` that may\n * also carry text, a `Picture` is an `addImage`, and a `GraphicFrame` delegates to the\n * table or chart mapper. A `GroupShape` recurses.\n *\n * The single most important thing this module does is record what it cannot carry.\n * Measurement against the fixture corpus found the binding constraint is the *read* side,\n * not the write side — several constructs the write API can express have no accessor at\n * all — so a converter that mapped only what it could see would produce clean-looking\n * output with silent visual losses. The clearest is theme-referenced line styling: a shape\n * whose outline comes from `p:style/a:lnRef` reports a colour through `resolvedLine` but\n * reports `null` for width and dash, because there is a resolved-colour path and no\n * resolved-width path. In the corpus that was every such shape, so a themed 2pt\n * border silently becomes a 1pt default. Each one is noted here rather than quietly thinned.\n *\n * The same dispatch serves the deck's *chrome*: {@link masterObject} re-tags a call as an\n * entry in a `defineSlideMaster({ objects })` array, so a rectangle on a layout is transcribed\n * by the code that transcribes one on a slide. Sharing it is the point — a second mapper would\n * be a second set of decisions about the same OOXML, drifting from this one silently.\n */\nimport {\n\tisAutoShape,\n\tisConnector,\n\tisGraphicFrame,\n\tisGroupShape,\n\tisPicture,\n\ttype AnyShape,\n\ttype AutoShape,\n\ttype Connector,\n\ttype CustomGeometry,\n\ttype GraphicFrame,\n\ttype GroupShape,\n\ttype Picture,\n} from '../../read/api/shapes.js'\nimport type { NoteScope } from '../fidelity.js'\nimport { isAssetRef, type AssetRef, type CallIr, type IrValue } from '../ir.js'\nimport { alphaToTransparency, compact, emu, isWritableSchemeToken, literalColor, orUndefined } from './values.js'\nimport { gradientStops, patternOption } from './surface-fill.js'\nimport { pictureFillOption, type PictureFillSubject } from './picture-fill.js'\nimport { hasEquation, hasIdentityChildSpace, isAudioVideo, isTextBox } from './detect.js'\nimport { textFrameOptions, textRuns } from './text.js'\nimport { tableCall } from './table.js'\nimport { chartCall } from './chart.js'\nimport { PERCENT_SCALE } from '../../units.js'\n\n/** Resolves an image/media part name to bytes the deck-level walk has registered. */\nexport interface AssetResolver {\n\t/** Register a part's bytes and hand back the reference that stands in for them. */\n\tassetFor(partName: string): AssetRef | null\n\t/**\n\t * The part's content type, or `null` when it is not in the package.\n\t *\n\t * Separate from {@link assetFor} because it has to be answerable *without* registering\n\t * anything: a caller that rejects a part on its type (a picture fill's SVG blip, which\n\t * the write path refuses) would otherwise leave bytes in the asset list that no call\n\t * references, and those bytes are emitted as a file next to the script.\n\t */\n\tcontentTypeOf(partName: string): string | null\n}\n\n/** How {@link pictureFillOption}'s notes name a shape's surface. */\nconst SHAPE_PICTURE_FILL: PictureFillSubject = {\n\tconstruct: 'fill.picture',\n\tsubject: \"this shape's surface\",\n\telement: 'a:blipFill',\n}\n\n/** Arrowhead types `ShapeLineProps` accepts; `a:headEnd/@type` uses the same tokens. */\nconst WRITABLE_ARROWS = new Set(['none', 'arrow', 'diamond', 'oval', 'stealth', 'triangle'])\n\n/** Dash tokens `ShapeLineProps.dashType` accepts — the whole `ST_PresetLineDashVal` set. */\nconst WRITABLE_DASHES = new Set([\n\t'solid',\n\t'dot',\n\t'dash',\n\t'lgDash',\n\t'dashDot',\n\t'lgDashDot',\n\t'lgDashDotDot',\n\t'sysDash',\n\t'sysDot',\n\t'sysDashDot',\n\t'sysDashDotDot',\n])\n\n/**\n * `a:ln/@cap` tokens → the `ShapeLineProps.cap` spelling that authors them. The read side\n * reports the raw OOXML token (`AutoShape.lineCap`) and the write side takes a friendly\n * name, so this is the whole of the mapping between them. `ST_LineCap` has exactly these\n * three members, so nothing falls off the end.\n */\nconst CAP_TOKENS: Record<string, 'flat' | 'square' | 'round'> = {\n\tflat: 'flat',\n\tsq: 'square',\n\trnd: 'round',\n}\n\n/**\n * Map one shape. Returns `null` when the shape produces no call at all — a note is always\n * recorded in that case, so a dropped shape is never silent.\n */\nexport function shapeCall(shape: AnyShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst scoped = notes.forShape(shape.name || null)\n\n\tif (shape.hidden) {\n\t\tnoteHidden(scoped)\n\t\treturn null\n\t}\n\n\tif (isGroupShape(shape)) return groupCall(shape, scoped, assets)\n\tif (isPicture(shape)) return pictureCall(shape, scoped, assets)\n\tif (isConnector(shape)) return connectorCall(shape, scoped)\n\tif (isGraphicFrame(shape)) return graphicFrameCall(shape, scoped, assets)\n\tif (isAutoShape(shape)) return autoShapeCall(shape, scoped, assets)\n\n\t// Unreachable: the five guards above exhaust `AnyShape`, which is why `shape` narrows to\n\t// `never` here. Left as a floor so a sixth shape kind fails to compile at the call sites\n\t// that assume a call, rather than silently falling through to a silent drop.\n\treturn null\n}\n\n/**\n * `p:cNvPr/@hidden` has no write-API counterpart, so a hidden shape would come back visible.\n * Omitting it preserves what the deck looks like, which is the lesser loss. Shared with the\n * layout-decoration mapper below, whose connector arm does not pass through {@link shapeCall}.\n */\nfunction noteHidden(notes: NoteScope): void {\n\tnotes.note(\n\t\t'shape.hidden',\n\t\t'dropped',\n\t\t'unwritable',\n\t\t'a hidden shape has no write-API expression; it is omitted rather than emitted visible'\n\t)\n}\n\n/* ===== position, fill, line, effects — shared by every shape kind ===== */\n\n/**\n * Position as `Coord`-typed EMU strings, so the source geometry survives exactly.\n *\n * `absoluteFrame` rather than the raw `left`/`top`: a shape inside a group is positioned in\n * its group's child coordinate space, which a flattened call list cannot express, so the\n * group transform has to be composed in here. For a top-level shape the two are identical.\n */\nfunction positionOptions(shape: AnyShape, notes?: NoteScope): Record<string, IrValue> {\n\tconst frame = shape.absoluteFrame\n\tif (frame) return { x: emu(frame.left), y: emu(frame.top), w: emu(frame.width), h: emu(frame.height) }\n\n\t// No transform of its own — a placeholder taking its geometry from the layout or master.\n\t// `resolvedFrame` walks that chain, and using it is not optional: omitting the geometry\n\t// does *not* leave it to be inherited, because a regenerated slide's placeholder inherits\n\t// nothing. It produces `x=0 y=0 w=<slide width> h=0` — a zero-height box in the corner,\n\t// which is broken output rather than lossy output.\n\tconst resolved = shape.resolvedFrame\n\tif (!resolved) return {}\n\tnotes?.note(\n\t\t'shape.frameInherited',\n\t\t'flattened',\n\t\t'unsupported',\n\t\t`this shape has no transform of its own and takes its geometry from the ${resolved.source}; a regenerated slide inherits nothing, so the resolved position is baked in and stops tracking later edits to that ${resolved.source}`\n\t)\n\treturn { x: emu(resolved.left), y: emu(resolved.top), w: emu(resolved.width), h: emu(resolved.height) }\n}\n\n/**\n * Rotation and flips. Taken from `absoluteFrame`, which composes enclosing group rotations\n * and XOR-composes group flips — the same reason position is absolute.\n */\nfunction transformOptions(shape: AnyShape): Record<string, IrValue | undefined> {\n\tconst frame = shape.absoluteFrame\n\tconst rotate = frame ? frame.rotation : (shape.rotation ?? 0)\n\treturn {\n\t\trotate: rotate === 0 ? undefined : rotate,\n\t\tflipH: (frame?.flipH ?? shape.flipH) ? true : undefined,\n\t\tflipV: (frame?.flipV ?? shape.flipV) ? true : undefined,\n\t}\n}\n\n/**\n * A shape's fill as `ShapeFillProps`.\n *\n * Prefers the raw scheme token over `resolvedFill` for the same reason run colour does: a\n * token keeps tracking the destination theme. `resolvedFill` is the fallback because it is\n * the only accessor that sees a `p:style/a:fillRef` — a shape styled entirely from the\n * theme has no `a:solidFill` of its own, so without it the shape would come out unfilled.\n */\nfunction fillOption(shape: AnyShape, notes: NoteScope, assets: AssetResolver): IrValue | undefined {\n\tconst gradient = shape.gradientFill\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'fill')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst pattern = patternOption(shape.patternFill)\n\tif (pattern) return pattern\n\n\t// An image-filled *surface* is not a picture object — it is `ShapeFillProps.image`, so\n\t// the bytes are re-embedded through the same asset resolver an `addImage` uses. Before\n\t// the fill option itself, since a shape carrying a `a:blipFill` has no `a:solidFill` for\n\t// the colour legs below to find.\n\tconst picture = shape.pictureFill\n\tif (picture) return pictureFillOption(picture, assets, notes, SHAPE_PICTURE_FILL)\n\n\tconst scheme = shape.fillSchemeColor\n\tif (isWritableSchemeToken(scheme)) return { color: scheme as string }\n\tif (shape.fillColor !== null) return { color: literalColor(shape.fillColor) }\n\n\tconst resolved = shape.resolvedFill\n\tif (!resolved) return undefined\n\tif (scheme !== null) {\n\t\tnotes.note(\n\t\t\t'fill.schemeToken',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`fill scheme colour \"${scheme}\" is outside the ten tokens the write path maps, so it is baked to a literal hex and stops tracking the theme`\n\t\t)\n\t}\n\treturn compact({\n\t\tcolor: literalColor(resolved.effectiveHex),\n\t\ttransparency: alphaToTransparency(resolved.alpha),\n\t})\n}\n\n/**\n * A shape's outline as `ShapeLineProps`.\n *\n * This is where the measured silent loss lives. When a shape takes its outline from\n * `p:style/a:lnRef`, `resolvedLine` supplies the colour but `lineWidthPt` and `lineDash`\n * both report `null` — the theme's `a:lnStyleLst` entry, where the width and dash actually\n * live, has no accessor. Emitting the colour and noting the rest is the honest outcome;\n * inventing a width would be worse, because it would look deliberate.\n */\nfunction lineOption(shape: AnyShape, notes: NoteScope): Record<string, IrValue> | undefined {\n\tif (shape.lineNoFill) return { type: 'none' }\n\n\tconst gradient = shape.lineGradient\n\tif (gradient) {\n\t\tconst stops = gradientStops(gradient, notes, 'line')\n\t\tif (stops) return { type: 'gradient', gradient: stops }\n\t}\n\n\tconst widthPt = shape.lineWidthPt\n\tconst dash = shape.lineDash\n\tconst cap = shape.lineCap\n\tconst scheme = shape.lineSchemeColor\n\tconst resolved = shape.resolvedLine\n\n\tlet color: string | undefined\n\tif (isWritableSchemeToken(scheme)) color = scheme as string\n\telse if (shape.lineColor !== null) color = literalColor(shape.lineColor)\n\telse if (resolved) color = literalColor(resolved.effectiveHex)\n\n\t// A colour only `resolvedLine` could supply means the stroke came from the theme style\n\t// list, whose width and dash are unreadable.\n\tif (resolved !== null && shape.lineColor === null && scheme === null && widthPt === null) {\n\t\tnotes.note(\n\t\t\t'line.width',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this outline comes from the theme style list (p:style/a:lnRef); its width and dash live in the theme fmtScheme a:lnStyleLst, which has no accessor, so only the colour carries'\n\t\t)\n\t}\n\tif (dash !== null && !WRITABLE_DASHES.has(dash)) {\n\t\tnotes.note(\n\t\t\t'line.dash',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`dash style \"${dash}\" is outside the eight the write API accepts, so the outline falls back to solid`\n\t\t)\n\t}\n\t// `@algn` is the one outline attribute both sides can see and neither can carry: the read\n\t// model reports it (`lineAlign`) and `ShapeLineProps` has no option for it. Only `in` is\n\t// noted — it insets the stroke by half its width, so it moves the border. `ctr` is what an\n\t// omitted `@algn` already renders as, so noting that would fire on most PowerPoint-authored\n\t// shapes while describing no loss at all.\n\tif (shape.lineAlign === 'in') {\n\t\tnotes.note(\n\t\t\t'line.align',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'this outline is inset (a:ln/@algn=\"in\", drawn wholly inside the shape); ShapeLineProps has no alignment option, so it comes back centred on the edge and sits half its width further out'\n\t\t)\n\t}\n\n\tconst options = compact({\n\t\tcolor,\n\t\twidth: orUndefined(widthPt),\n\t\tdashType: dash !== null && WRITABLE_DASHES.has(dash) ? dash : undefined,\n\t\tcap: cap === null ? undefined : CAP_TOKENS[cap],\n\t\ttransparency: alphaToTransparency(resolved?.alpha),\n\t\t...arrowOptions(shape, notes),\n\t})\n\treturn options\n}\n\n/** Arrowheads. Types map directly; the `sm`/`med`/`lg` size classes have no option. */\nfunction arrowOptions(shape: AnyShape, notes: NoteScope): Record<string, IrValue | undefined> {\n\tconst ends = shape.lineEnds\n\tif (!ends) return {}\n\tconst sized = [ends.head, ends.tail].some((end) => end && (end.width !== null || end.length !== null))\n\tif (sized) {\n\t\tnotes.note(\n\t\t\t'line.arrowSize',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'arrowhead width and length classes (@w / @len) have no write-API option, so arrowheads render at the default size'\n\t\t)\n\t}\n\treturn {\n\t\tbeginArrowType: ends.head && WRITABLE_ARROWS.has(ends.head.type) ? ends.head.type : undefined,\n\t\tendArrowType: ends.tail && WRITABLE_ARROWS.has(ends.tail.type) ? ends.tail.type : undefined,\n\t}\n}\n\n/** Outer shadow as `ShadowProps`; an inner shadow uses the same option with `type: 'inner'`. */\nfunction shadowOption(shape: AnyShape, notes: NoteScope): IrValue | undefined {\n\tif (shape.reflection || shape.softEdge) {\n\t\tnotes.note(\n\t\t\t'shape.effects',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a:reflection and a:softEdge are read but have no write-API emitter, so those effects are lost'\n\t\t)\n\t}\n\n\tconst outer = shape.shadow\n\tconst source = outer ?? shape.innerShadow\n\tif (!source) return undefined\n\n\treturn compact({\n\t\ttype: outer ? 'outer' : 'inner',\n\t\tcolor: source.color === null ? undefined : literalColor(source.color),\n\t\tblur: source.blurPt,\n\t\toffset: source.offsetPt,\n\t\tangle: source.angleDeg,\n\t\ttransparency: alphaToTransparency(source.alpha),\n\t})\n}\n\n/** Glow. The read model reports opacity as a 0–1 alpha, which is the write API's unit too. */\nfunction glowOption(shape: AnyShape): IrValue | undefined {\n\tconst glow = shape.glow\n\tif (!glow) return undefined\n\treturn compact({\n\t\tsize: glow.radiusPt,\n\t\tcolor: glow.color === null ? undefined : literalColor(glow.color),\n\t\topacity: glow.alpha,\n\t})\n}\n\n/** The style block every shape kind shares. */\nfunction styleOptions(shape: AnyShape, notes: NoteScope, assets: AssetResolver): Record<string, IrValue | undefined> {\n\treturn {\n\t\tfill: fillOption(shape, notes, assets),\n\t\tline: lineOption(shape, notes),\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape),\n\t}\n}\n\n/* ===== per-kind mappers ===== */\n\n/**\n * An `AutoShape` becomes an `addShape` when it is bare geometry and an `addText` when it\n * carries text. A shape with both takes the `addText` form, because `addShape` has no text\n * argument while `addText` accepts a `shape` option — so only that form expresses both.\n */\nfunction autoShapeCall(shape: AutoShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst preset = shape.presetGeometry\n\tconst custom = shape.customGeometry\n\tconst frame = shape.hasTextFrame ? shape.textFrame : null\n\n\t// \"Has text\" means text this converter can author, which is *runs*. `TextFrame.text` also\n\t// counts `a:fld` field text — a slide number, date or footer placeholder — and there is no\n\t// run behind it, so measuring by `text` made every field placeholder emit an `addText`\n\t// carrying a single empty string: an invisible empty box where a number used to be.\n\tconst runText = frame === null ? '' : frame.paragraphs.flatMap((p) => p.runs.map((run) => run.text)).join('')\n\tconst hasText = runText.length > 0\n\n\t// Run text is a subsequence of the frame's text, so anything longer came from a field.\n\tif (frame !== null && frame.text.replaceAll('\\n', '').length > runText.length) {\n\t\tnotes.note(\n\t\t\t'text.field',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this shape holds an automatic field (a:fld — a slide number, date or footer), which has no accessor and no addText expression, so its text is not reproduced'\n\t\t)\n\t}\n\n\t// An OMML equation contributes nothing to `TextFrame.text`, so an equation-only shape\n\t// looks like an empty box and would otherwise emit as bare geometry.\n\tif (frame !== null && hasEquation(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'text.equation',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'this shape holds an OMML equation, which no accessor exposes, so the shape is emitted without it — even though TextProps.math (and the ts-pptx/math subpath) could author one'\n\t\t)\n\t}\n\n\tif (shape.placeholder) {\n\t\tnotes.note(\n\t\t\t'shape.placeholder',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t'a placeholder is emitted as a plain shape with its inherited geometry and styling baked in, so it no longer follows its layout'\n\t\t)\n\t}\n\n\tconst common = {\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\t...styleOptions(shape, notes, assets),\n\t\tobjectName: shape.name || undefined,\n\t}\n\n\tif (custom) {\n\t\tnotes.note(\n\t\t\t'shape.custGeom.guides',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'custGeom guides, adjust handles and connection sites (a:gdLst / a:ahLst / a:cxnLst) have no accessor, so only the path outline carries'\n\t\t)\n\t\tconst options = compact({ ...common, points: customGeometryPoints(shape, custom) })\n\t\treturn { method: 'addShape', args: ['custGeom', options ?? {}], ...nameOf(shape) }\n\t}\n\n\tif (hasText && frame !== null) {\n\t\t// `isTextBox` and `shape` are independent, not alternatives: a PowerPoint text box\n\t\t// carries `txBox=\"1\"` *and* an explicit `prstGeom rect`, so reading text-box-ness off\n\t\t// the absence of geometry misclassified every one of them as an auto shape.\n\t\tconst options = compact({\n\t\t\t...common,\n\t\t\t...textFrameOptions(frame, notes),\n\t\t\t...(isTextBox(shape.element_) ? { isTextBox: true } : {}),\n\t\t\t...(preset === null ? {} : { shape: preset, ...adjustOptions(shape) }),\n\t\t})\n\t\treturn { method: 'addText', args: [textRuns(frame, notes), options ?? {}], ...nameOf(shape) }\n\t}\n\n\t// No text and no geometry of its own: an empty placeholder, whose shape comes from the\n\t// layout it inherits. `addShape` needs a preset name and `addText` would author an\n\t// invisible empty box, so the shape is dropped — which matches how it renders in a\n\t// slideshow, where an unfilled placeholder shows nothing. It is still a loss in the\n\t// editor, so it is declared rather than assumed harmless.\n\tif (preset === null) {\n\t\tnotes.note(\n\t\t\t'shape.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this shape carries no text and no geometry of its own (an unfilled placeholder drawing its outline from the layout), so there is no addShape preset to name and it is omitted'\n\t\t)\n\t\treturn null\n\t}\n\tconst options = compact({ ...common, ...adjustOptions(shape) })\n\treturn { method: 'addShape', args: [preset, options ?? {}], ...nameOf(shape) }\n}\n\n/**\n * Preset-geometry adjust handles (`a:avLst`) as `shapeAdjust`.\n *\n * The read model reports each guide's raw formula string; a preset's adjust values are\n * `val <n>` where `<n>` is in 1000ths of a percent, and the write API takes the same handle\n * as a `0.0–1.0` fraction. Anything that is not a plain `val` is a computed guide, which\n * has no write-API expression, so it is skipped rather than mis-scaled.\n */\nfunction adjustOptions(shape: AutoShape): Record<string, IrValue | undefined> {\n\tconst values = shape.adjustValues\n\tconst guides: IrValue[] = []\n\tfor (const name of Object.keys(values).sort()) {\n\t\tconst match = /^val\\s+(-?\\d+)$/.exec((values[name] ?? '').trim())\n\t\tif (!match?.[1]) continue\n\t\tguides.push({ name, value: Number(match[1]) / PERCENT_SCALE })\n\t}\n\treturn guides.length ? { shapeAdjust: guides } : {}\n}\n\n/**\n * `custGeom` path commands as the write API's `points` array.\n *\n * Path coordinates are integers in the path's own `0..w`/`0..h` viewport, not EMU, so each\n * is scaled onto the shape's box before being printed as EMU. A path that declares no\n * viewport (`@w`/`@h` of 0) is already in the shape's own space and passes through.\n */\nfunction customGeometryPoints(shape: AutoShape, custom: CustomGeometry): IrValue {\n\tconst frame = shape.absoluteFrame\n\tconst points: IrValue[] = []\n\n\tfor (const path of custom.paths) {\n\t\tconst sx = path.w > 0 && frame ? frame.width / path.w : 1\n\t\tconst sy = path.h > 0 && frame ? frame.height / path.h : 1\n\t\tconst px = (v: number): string => emu(v * sx)\n\t\tconst py = (v: number): string => emu(v * sy)\n\n\t\tfor (const command of path.commands) {\n\t\t\tswitch (command.cmd) {\n\t\t\t\tcase 'moveTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y), moveTo: true })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'lnTo':\n\t\t\t\t\tpoints.push({ x: px(command.x), y: py(command.y) })\n\t\t\t\t\tbreak\n\t\t\t\tcase 'cubicBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'cubic', x1: px(command.x1), y1: py(command.y1), x2: px(command.x2), y2: py(command.y2) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'quadBezTo':\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tx: px(command.x),\n\t\t\t\t\t\ty: py(command.y),\n\t\t\t\t\t\tcurve: { type: 'quadratic', x1: px(command.x1), y1: py(command.y1) },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'arcTo':\n\t\t\t\t\t// An arcTo carries no end point on either side — the renderer derives it from\n\t\t\t\t\t// the pen position, radii and swept angle — so this maps one-to-one.\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tcurve: { type: 'arc', wR: px(command.wR), hR: py(command.hR), stAng: command.stAng, swAng: command.swAng },\n\t\t\t\t\t})\n\t\t\t\t\tbreak\n\t\t\t\tcase 'close':\n\t\t\t\t\tpoints.push({ close: true })\n\t\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn points\n}\n\n/**\n * A `Picture` becomes `addImage`, with its bytes carried as an asset.\n *\n * PowerPoint authors embedded audio and video as a picture too — the poster frame is the\n * blip, and the media itself hangs off `p:nvPr` as `a:videoFile`/`a:audioFile`. The read\n * model surfaces only the poster (`mediaKind` separates raster from SVG, not still from\n * moving), so a video would otherwise convert to a static image with nothing to show it had\n * ever moved. The write API has `addMedia`, so this is a read-side gap, and it is declared\n * rather than silently flattened.\n */\nfunction pictureCall(shape: Picture, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tif (isAudioVideo(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'media.audioVideo',\n\t\t\t'flattened',\n\t\t\t'unread',\n\t\t\t'this is embedded audio or video: no accessor reports the media part or its kind, only the poster frame, so it is emitted as a still image even though addMedia could author it'\n\t\t)\n\t}\n\n\t// The vector part wins when there is one. A PowerPoint SVG picture is an `asvg:svgBlip`\n\t// extension over a raster fallback, and the fallback is the lossy copy — taking it would\n\t// throw away the vector for no reason, since `addImage` accepts SVG bytes directly and\n\t// regenerates a fallback of its own.\n\tconst partName = shape.svgPartName ?? shape.imagePartName\n\tif (!partName) {\n\t\tnotes.note(\n\t\t\t'image.data',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this picture references no embedded image part (an external or linked image), so there are no bytes to carry'\n\t\t)\n\t\treturn null\n\t}\n\tconst asset = assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note('image.data', 'dropped', 'unsupported', `image part ${partName} is not present in the package`)\n\t\treturn null\n\t}\n\n\tif (shape.svgPartName && shape.imagePartName) {\n\t\tnotes.note(\n\t\t\t'image.svg',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"the vector part of this SVG picture is carried and the source's own raster fallback is not; the write path generates a fresh fallback, so a renderer that cannot draw SVG shows a different image from the one the source deck shipped\"\n\t\t)\n\t}\n\tif (shape.recolor) {\n\t\tnotes.note(\n\t\t\t'image.recolor',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'a picture recolour (a:duotone / a:clrChange / a:grayscl) is read but has no write-API option'\n\t\t)\n\t}\n\n\tconst crop = shape.crop\n\tconst options = compact({\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\tobjectName: shape.name || undefined,\n\t\t// `crop`, not `sizing`. Both exist and they are not interchangeable: `crop` is\n\t\t// `a:srcRect` emitted verbatim as percentage edge insets — the exact model the read\n\t\t// model reports — while `sizing: 'crop'` cuts a window in *displayed inches* against\n\t\t// the image's measured natural size. Feeding fractions to `sizing` read them as\n\t\t// inches, which shrank every cropped picture to a fraction of its box.\n\t\tcrop:\n\t\t\tcrop === null ? undefined : { l: crop.left * 100, t: crop.top * 100, r: crop.right * 100, b: crop.bottom * 100 },\n\t})\n\treturn { method: 'addImage', args: [{ ...options, data: asset }], ...nameOf(shape) }\n}\n\n/**\n * `ConnectorProps` keys that {@link lineOption} can produce. A connector styles its stroke\n * with *flat* options rather than the nested `line` object every other shape takes, and it\n * accepts a strict subset: no `transparency`, no gradient stroke, and its own `type` names\n * the routing (`straight`/`elbow`/`curved`), not a fill kind — so spreading a line option\n * object into it wholesale would both drop silently and collide.\n */\nconst CONNECTOR_LINE_KEYS = ['color', 'width', 'dashType', 'beginArrowType', 'endArrowType'] as const\n\n/**\n * A `Connector` becomes `addConnector`.\n *\n * The endpoints are the one real translation here. OOXML gives a connector a bounding box\n * plus flip flags; `addConnector` takes two points. `a:flipH`/`a:flipV` are what say which\n * diagonal of the box the line runs along, so dropping them would silently mirror every\n * connector that runs up or leftward.\n *\n * The *bindings* (`a:stCxn`/`a:endCxn`) reference source shape ids that have no counterpart\n * in the output, so a connector lands unbound and stops following its shapes when they move.\n */\nfunction connectorCall(shape: Connector, notes: NoteScope): CallIr | null {\n\tconst frame = shape.absoluteFrame\n\tif (!frame) return null\n\n\tif (shape.startConnection || shape.endConnection) {\n\t\tnotes.note(\n\t\t\t'connector.binding',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'connector endpoint bindings reference source shape ids with no counterpart in the output, so the connector lands unbound and no longer follows its shapes'\n\t\t)\n\t}\n\tif (shape.rotation) {\n\t\tnotes.note(\n\t\t\t'connector.rotation',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'addConnector takes two endpoints and no rotation, so a rotated connector lands along the unrotated diagonal of its box'\n\t\t)\n\t}\n\n\tconst line = lineOption(shape, notes) ?? {}\n\tconst stroke: Record<string, IrValue> = {}\n\tfor (const key of CONNECTOR_LINE_KEYS) {\n\t\tconst value = line[key]\n\t\tif (value !== undefined) stroke[key] = value\n\t}\n\tif (line['type'] === 'gradient' || line['transparency'] !== undefined) {\n\t\tnotes.note(\n\t\t\t'connector.line',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'a connector styles its stroke with flat colour/width options, which cannot express a gradient stroke or a stroke transparency, so those fall back to a plain line'\n\t\t)\n\t}\n\n\tconst right = frame.left + frame.width\n\tconst bottom = frame.top + frame.height\n\treturn {\n\t\tmethod: 'addConnector',\n\t\targs: [\n\t\t\tcompact({\n\t\t\t\t// Routing is not readable — `presetGeometry` names the connector preset but the\n\t\t\t\t// bend count it implies is not exposed — so every connector emits straight.\n\t\t\t\ttype: 'straight',\n\t\t\t\tx1: emu(shape.flipH ? right : frame.left),\n\t\t\t\ty1: emu(shape.flipV ? bottom : frame.top),\n\t\t\t\tx2: emu(shape.flipH ? frame.left : right),\n\t\t\t\ty2: emu(shape.flipV ? frame.top : bottom),\n\t\t\t\tobjectName: shape.name || undefined,\n\t\t\t\t...stroke,\n\t\t\t}) ?? {},\n\t\t],\n\t\t...nameOf(shape),\n\t}\n}\n\n/**\n * Why a graphic frame cannot be authored from a script, or `null` when it can.\n *\n * The single enumeration of the payloads with no write-API emitter, and the reason it is a\n * function rather than a condition spelled at each site: `graphicFrameCall` needs it to pick\n * a fidelity note, and `hasUnwritableContent` in `from-read/deck.ts` needs it to decide\n * whether the printer must copy the slide instead of transcribing it. Those were two\n * hand-maintained lists, they disagreed — the deck-level one named extended charts only — and\n * a SmartArt slide was therefore transcribed with a hole where the graphic had been. The two\n * consequences are the same for every member, so the membership has to be too.\n */\nexport function unwritableFramePayload(shape: GraphicFrame): 'chartEx' | 'diagram' | 'unknown' | null {\n\tif (shape.table || shape.chart) return null\n\tif (shape.hasChartEx) return 'chartEx'\n\tif (shape.hasDiagram) return 'diagram'\n\treturn 'unknown'\n}\n\n/** A `GraphicFrame` hosts a table or a chart; both have their own mapper. */\nfunction graphicFrameCall(shape: GraphicFrame, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst table = shape.table\n\tif (table) return tableCall(shape, table, notes, assets)\n\n\tconst chart = shape.chart\n\tif (chart) return chartCall(shape, chart, notes)\n\n\t// Everything below emits no call. Reached even when the deck-level walk already marked the\n\t// slide `carried`, because the standalone tier has no source package to copy from and needs\n\t// the per-shape note to say what it lost.\n\tswitch (unwritableFramePayload(shape)) {\n\t\tcase 'chartEx':\n\t\t\tnotes.note(\n\t\t\t\t'chartEx.all',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'an extended chart (waterfall, funnel, box-and-whisker, …) has a full reader but no write-API counterpart'\n\t\t\t)\n\t\t\treturn null\n\t\tcase 'diagram':\n\t\t\t// Read but unwritable, so it takes the `chartEx.all` shape rather than the\n\t\t\t// `graphicFrame.unknown` one below: the loss is the *write* side's, and saying\n\t\t\t// \"not decoded\" of a construct whose text the read model now returns would be false.\n\t\t\tnotes.note(\n\t\t\t\t'diagram.all',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t'a SmartArt diagram has a full reader and its text can be edited in place through it (DiagramPoint.text), but no write API authors one from a script, so a converted script cannot describe this frame'\n\t\t\t)\n\t\t\treturn null\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'graphicFrame.unknown',\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t'this graphic frame hosts none of a table, a chart or a SmartArt diagram (an OLE object or an ink annotation), which the read model does not decode'\n\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/**\n * A `GroupShape` becomes `addGroup`, with each child mapped and re-tagged into the\n * key-tagged `GroupChildProps` shape the write API expects.\n *\n * Children keep slide-absolute coordinates, which is not a compromise here: `addGroup`\n * holds an identity child coordinate space (`chOff/chExt == off/ext`) at every depth\n * precisely so they can. Nested groups therefore nest rather than flatten. What does not\n * survive is a source group with a *non*-identity child space — that group scales its\n * contents when resized and the emitted one will not — so that case, and only that case,\n * is noted.\n *\n * Charts, tables, media and placeholders are excluded from groups by the write API, so a\n * group holding one loses that child.\n */\nfunction groupCall(shape: GroupShape, notes: NoteScope, assets: AssetResolver): CallIr | null {\n\tconst children: IrValue[] = []\n\tfor (const child of shape.shapes) {\n\t\tconst call = shapeCall(child, notes, assets)\n\t\tif (!call) continue\n\t\tconst tagged = asGroupChild(call)\n\t\tif (!tagged) {\n\t\t\tnotes.note(\n\t\t\t\t'group.child',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`addGroup accepts no ${call.method.replace(/^add/, '').toLowerCase()} child (charts, tables and media are excluded by design), so this child is omitted from the group`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\tchildren.push(tagged)\n\t}\n\tif (children.length === 0) {\n\t\tnotes.note(\n\t\t\t'group.empty',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'no child of this group produced a call, and addGroup rejects an empty child list, so the group itself is omitted too'\n\t\t)\n\t\treturn null\n\t}\n\n\tif (!hasIdentityChildSpace(shape.element_)) {\n\t\tnotes.note(\n\t\t\t'group.childSpace',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"this group scales its contents (its a:chOff/a:chExt differ from its a:off/a:ext); addGroup's child space is always identity, so the children are emitted pre-scaled and resizing the group no longer rescales them\"\n\t\t)\n\t}\n\n\t// The group's own rotation and flips are deliberately NOT emitted here. `absoluteFrame`\n\t// composes them into every child, and the children above were built from it, so the\n\t// transform is already baked in at slide-absolute coordinates. Emitting it on the group\n\t// as well would apply it a second time — measured: a group rotated 30° came back at 60°\n\t// with its children walked off their positions, and a flipped group came back unflipped\n\t// because the double flip cancelled. The group's frame is a bounding box and nothing else.\n\tif (shape.rotation !== 0 || shape.flipH || shape.flipV) {\n\t\tnotes.note(\n\t\t\t'group.transform',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"the group's own rotation and flips are baked into its children's coordinates rather than kept on the group, because addGroup would otherwise apply them twice; the shapes render identically but rotating or resetting the group no longer moves them together\"\n\t\t)\n\t}\n\n\treturn {\n\t\tmethod: 'addGroup',\n\t\targs: [children, compact({ ...positionOptions(shape, notes), objectName: shape.name || undefined }) ?? {}],\n\t\t...nameOf(shape),\n\t}\n}\n\n/**\n * Re-tag a call as a `GroupChildProps` entry, or `null` when the content type is one\n * `addGroup` excludes. The tagged form is a single-key object, not a `{ type, args }` pair.\n */\nfunction asGroupChild(call: CallIr): IrValue | null {\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addGroup':\n\t\t\treturn { group: compact({ children: first, options: second }) ?? {} }\n\t\tdefault:\n\t\t\t// Charts, tables, connectors and media have no GroupChildProps variant.\n\t\t\treturn null\n\t}\n}\n\n/**\n * The three key-tagged variants both union-shaped call sites emit identically: a text box, an\n * auto shape, and an image. `null` when `call.method` is not one of them, which is the signal\n * for the caller to try its own extra arms.\n *\n * Shared rather than duplicated because this is exactly where a fourth common variant would be\n * added to one site and forgotten in the other. What is deliberately *not* shared is either\n * caller's `default`: a group child silently declines a chart, while a layout object reports it\n * as a fidelity loss, and that difference is the point of having two functions.\n */\nfunction commonShapeVariant(call: CallIr): IrValue | null {\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addText':\n\t\t\treturn { text: compact({ text: first, options: second }) ?? {} }\n\t\tcase 'addShape':\n\t\t\treturn { shape: compact({ type: first, options: second }) ?? {} }\n\t\tcase 'addImage':\n\t\t\treturn { image: first ?? {} }\n\t\tdefault:\n\t\t\treturn null\n\t}\n}\n\n/** Attach the source name to a call, when the shape had one. */\nfunction nameOf(shape: AnyShape): { sourceName?: string } {\n\treturn shape.name ? { sourceName: shape.name } : {}\n}\n\n/* ===== a layout's own shapes ===== */\n\n/**\n * One shape from a **layout's** shape tree as a `SlideMasterObject` — an entry in the\n * `objects` array of a `defineSlideMaster` call.\n *\n * Everything about the shape itself is decided by {@link shapeCall}, so a rectangle on a\n * layout is transcribed by the same code that transcribes one on a slide and cannot drift\n * from it. Only the *envelope* differs: `objects` is a key-tagged union rather than a method\n * name plus arguments — the same shape `GroupChildProps` takes — which is why this reads as a\n * sibling of {@link asGroupChild}.\n *\n * `notes` must already be a `layoutShapeScope`, so the slide vocabulary this borrows lands\n * under `layout.` and cannot be mistaken for a loss on a slide.\n *\n * Two methods have no variant in the union. `addGroup` never reaches here — the layout walk\n * flattens a group into its children first, since children already carry slide-absolute\n * coordinates. `addTable` genuinely has nowhere to go, and is the one kind this reports as\n * lost.\n */\nexport function masterObject(shape: AnyShape, notes: NoteScope, assets: AssetResolver): IrValue | null {\n\t// The connector arm bypasses `shapeCall`, so it carries the hidden check with it.\n\tif (isConnector(shape)) {\n\t\tconst scoped = notes.forShape(shape.name || null)\n\t\tif (shape.hidden) {\n\t\t\tnoteHidden(scoped)\n\t\t\treturn null\n\t\t}\n\t\treturn connectorObject(shape, scoped)\n\t}\n\n\tconst call = shapeCall(shape, notes, assets)\n\tif (!call) return null\n\n\tconst shared = commonShapeVariant(call)\n\tif (shared) return shared\n\n\tconst [first, second] = call.args\n\tswitch (call.method) {\n\t\tcase 'addChart': {\n\t\t\t// `addChart(data, options)` carries the chart type inside its options, while a master\n\t\t\t// object names it separately. Lifted back out rather than moved: `addChildDefinition`\n\t\t\t// passes the whole options object on to `addChartDefinition` as well, which is where a\n\t\t\t// chart's `type` is read from in the first place.\n\t\t\tconst options = second !== null && typeof second === 'object' && !Array.isArray(second) && !isAssetRef(second) ? second : null // prettier-ignore\n\t\t\tconst type = options?.['type']\n\t\t\tif (type === undefined || first === undefined) return null\n\t\t\treturn { chart: compact({ type, data: first, opts: options }) ?? {} }\n\t\t}\n\t\tdefault:\n\t\t\tnotes\n\t\t\t\t.forShape(shape.name || null)\n\t\t\t\t.note(\n\t\t\t\t\t'decoration',\n\t\t\t\t\t'dropped',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t`a ${call.method.replace(/^add/, '').toLowerCase()} on a slide layout has no defineSlideMaster({ objects }) variant — the union covers a chart, an image, a shape and a text box — so it is dropped from the layout the output rebuilds`\n\t\t\t\t)\n\t\t\treturn null\n\t}\n}\n\n/**\n * A `Connector` as a `line` shape descriptor, which is the only way one reaches a layout.\n *\n * The alternative to this arm is dropping every connector a layout carries, and in the fixture\n * corpus that is 18 of the 45 shapes every layout actually draws — because PowerPoint's\n * line tool authors a `p:cxnSp`, so a plain horizontal rule under a title is usually a\n * connector rather than a shape. Drawing it as a `line` preset paints the identical stroke.\n *\n * What that costs is the endpoint binding, and on a layout it costs nothing that was working:\n * `a:stCxn`/`a:endCxn` reference shapes in the *layout's* tree, and nothing a slide later puts\n * on top is one of them. The slide-side `addConnector` mapping loses the binding too.\n *\n * It is also better than that mapping in one respect. `addConnector` takes two endpoints and\n * no rotation, so a rotated connector lands along the unrotated diagonal of its box; a shape\n * carries `rotate`, so this keeps it.\n */\nfunction connectorObject(shape: Connector, notes: NoteScope): IrValue | null {\n\tif (!shape.absoluteFrame) return null\n\n\tif (shape.startConnection || shape.endConnection) {\n\t\tnotes.note(\n\t\t\t'connector.binding',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t'this connector is bound to shapes on the layout; it is re-authored as a line shape, which paints the same stroke but no longer follows them'\n\t\t)\n\t}\n\n\t// No `fill`: a connector's `p:spPr` has no fill that a line geometry could show, and asking\n\t// `fillOption` for one would resolve the `p:style/a:fillRef` a `p:cxnSp` always carries into\n\t// a colour that paints nothing on the source and a filled box on the output.\n\tconst options = compact({\n\t\t...positionOptions(shape, notes),\n\t\t...transformOptions(shape),\n\t\tline: lineOption(shape, notes),\n\t\tshadow: shadowOption(shape, notes),\n\t\tglow: glowOption(shape),\n\t\tobjectName: shape.name || undefined,\n\t})\n\t// Through `compact` like the other arms, so every emitted descriptor spells its keys in the\n\t// same order and the printed script does not read as two different mappers.\n\treturn { shape: compact({ type: 'line', options: options ?? {} }) ?? {} }\n}\n","/**\n * The deck's shared chrome → {@link ChromeIr}: theme colours and fonts, plus one\n * `defineSlideMaster` descriptor per source layout.\n *\n * **Only a standalone output needs any of this,** and it is the part of a deck that survives\n * a conversion worst. A template-anchored output reuses the source package, so its masters,\n * layouts and theme are the originals byte for byte; everything below is the approximation\n * that replaces them when there is no template to inherit from. The notes it records are\n * therefore tier-scoped: real for a standalone script, and suppressed by the template-anchored\n * printer because they do not describe its output.\n *\n * **Two ceilings meet here, and neither moves by working harder on this file:**\n *\n * 1. `a:fmtScheme` is unreachable from *both* directions — no read accessor, and the write\n * path emits a hardcoded Office one. A shape whose look comes from `p:style` is repainted.\n * 2. `p:txStyles` has a write counterpart (`SlideMasterProps.textStyles`) and no reader, so\n * the per-level placeholder defaults are invisible.\n *\n * **A layout's decoration used to be a third, and is not any more.** `SlideLayout.shapes`\n * decodes it, and {@link masterObject} re-tags each shape as an entry in the layout's\n * `defineSlideMaster({ objects })` array — through the *same* mapper the slides use, so a band\n * or a wordmark on a layout is transcribed exactly as one on a slide would be. What is left of\n * the ceiling is narrow and named per shape (`layout.*`): a table has no variant in that\n * union, and a group is flattened into its children because the union has no `group` either.\n * A **master's** own decoration is still lost outright, and structurally so — `defineSlideMaster`\n * creates a *layout* under the one shared master, so a master's shape tree has no counterpart\n * to be written to.\n *\n * **Layout placeholders are deliberately not emitted, and that is a write-path finding rather\n * than a read-path one.** `addPlaceholdersToSlideLayouts` seeds *every* slide with each layout\n * placeholder the slide did not populate, as an empty text shape\n * (`src/gen/define/placeholder.ts`). Since this converter transcribes every source shape as\n * concrete absolute-positioned content and never binds one to a placeholder, reproducing the\n * layout's placeholders would add a ghost shape to every slide for each of them — shapes the\n * source deck does not have. Dropping them costs an editing affordance; emitting them would\n * cost the output's shape tree. It is also what makes the decoration walk below a *filter*\n * rather than a straight transcription of `SlideLayout.shapes`.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { SlideLayout, SlideMaster, Theme } from '../../read/api/chrome.js'\nimport type { SlideBackground } from '../../read/api/slide-background.js'\nimport { isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport type { ChromeIr, IrValue, MasterIr, ThemeIr } from '../ir.js'\nimport { layoutShapeScope, type NoteScope } from '../fidelity.js'\nimport { masterObject, type AssetResolver } from './shape.js'\nimport { hasDecorativeShapes, hasFormatScheme, hasTextStyles, isPlaceholderShape } from './detect.js'\nimport { compact, literalColor, orUndefined } from './values.js'\nimport { DEFAULT_COLOR_MAP } from '../../ooxml/st-enums.js'\n\n/** Build the chrome IR for a deck. */\nexport function chromeToIr(pres: Presentation, notes: NoteScope, assets: AssetResolver): ChromeIr {\n\tconst masters = pres.masters()\n\n\tif (masters.length > 1) {\n\t\tnotes.note(\n\t\t\t'master.multiple',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t`this deck has ${masters.length} slide masters; the write API models a deck as one shared master with many layouts, so every layout is rebuilt under a single master and only the first master's theme and colour map survive`\n\t\t)\n\t}\n\n\tconst first = masters[0]\n\tconst theme = first?.theme ?? null\n\trecordMasterLosses(masters, theme, notes)\n\n\treturn { theme: themeToIr(theme), masters: layoutsToIr(masters, notes, assets) }\n}\n\n/** The theme's colour scheme and font faces, in `ThemeProps` spelling. */\nfunction themeToIr(theme: Theme | null): ThemeIr {\n\tif (!theme) return {}\n\n\tconst scheme = theme.colorScheme\n\tconst colors: Record<string, string> = {}\n\tfor (const [slot, hex] of Object.entries(scheme)) {\n\t\tif (hex !== null) colors[slot] = literalColor(hex)\n\t}\n\n\tconst fonts = theme.fontScheme\n\treturn compact({\n\t\theadFontFace: orUndefined(fonts?.major.latin ?? null),\n\t\tbodyFontFace: orUndefined(fonts?.minor.latin ?? null),\n\t\theadFontFaceEA: orUndefined(fonts?.major.ea ?? null),\n\t\tbodyFontFaceEA: orUndefined(fonts?.minor.ea ?? null),\n\t\theadFontFaceCS: orUndefined(fonts?.major.cs ?? null),\n\t\tbodyFontFaceCS: orUndefined(fonts?.minor.cs ?? null),\n\t\tcolorScheme: Object.keys(colors).length > 0 ? colors : undefined,\n\t}) as ThemeIr\n}\n\n/** The losses that belong to the master/theme tier as a whole rather than to one layout. */\nfunction recordMasterLosses(masters: SlideMaster[], theme: Theme | null, notes: NoteScope): void {\n\tif (theme && hasFormatScheme(theme.element_)) {\n\t\tnotes.note(\n\t\t\t'theme.fmtScheme',\n\t\t\t'approximated',\n\t\t\t'unread',\n\t\t\t\"the theme's format scheme (a:fmtScheme — the three fill, line and effect style lists a shape's p:style indexes into) has no read accessor and no write-API option, so the output carries Office's default; a shape whose fill or outline came from the theme rather than from its own a:ln keeps its colour but not its width, dash or effect\"\n\t\t)\n\t}\n\n\tfor (const master of masters) {\n\t\tconst root = master.part.dom.documentElement\n\t\tif (hasTextStyles(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.txStyles',\n\t\t\t\t'dropped',\n\t\t\t\t'unread',\n\t\t\t\t\"the master's per-level text styles (p:txStyles — the default size, face, colour, indent and bullet of each of the nine list levels) have no read accessor, so placeholder text falls back to PowerPoint's built-in defaults; SlideMasterProps.textStyles could author them if they could be seen\"\n\t\t\t)\n\t\t}\n\t\tif (hasDecorativeShapes(root)) {\n\t\t\tnotes.note(\n\t\t\t\t'master.decoration',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t\"this slide master carries shapes that are not placeholders (a logo, a rule, a background graphic); the read model decodes them (SlideMaster.shapes) and a layout's are re-authored, but a master's cannot be — defineSlideMaster creates a layout under the one shared master, so the master's own shape tree has no write-side counterpart to receive them\"\n\t\t\t)\n\t\t}\n\n\t\tconst map = master.colorMap\n\t\tconst remapped = Object.entries(DEFAULT_COLOR_MAP).filter(\n\t\t\t([token, slot]) => map[token as keyof typeof map] !== slot\n\t\t)\n\t\tif (remapped.length > 0) {\n\t\t\tnotes.note(\n\t\t\t\t'master.colorMap',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t`this master remaps ${remapped.map(([token]) => token).join(', ')} to a different theme slot and the write path always emits the identity map, so every scheme colour that passes through as a token resolves to a different hex than it did in the source`\n\t\t\t)\n\t\t}\n\t}\n}\n\n/**\n * One `defineSlideMaster` descriptor per source layout, in the same gallery order\n * `Presentation.layouts()` reports — which is what lets a slide bind by index.\n *\n * Titles are made unique because they are the lookup key `addSlide({ masterTitle })` matches\n * on, and `p:cSld@name` is not unique: a multi-master deck routinely carries several layouts\n * called \"Title and Content\", and two `defineSlideMaster` calls sharing a title would make\n * every slide bind to whichever won.\n */\nfunction layoutsToIr(masters: SlideMaster[], notes: NoteScope, assets: AssetResolver): MasterIr[] {\n\tconst out: MasterIr[] = []\n\tconst used = new Set<string>()\n\t// Rolled up rather than noted per layout: a 12-layout deck loses the placeholder definitions\n\t// on most of them, and twelve near-identical paragraphs at the top of the emitted script bury\n\t// the per-shape notes underneath that a reader can actually act on.\n\tlet placeholderCount = 0\n\tlet placeholderLayouts = 0\n\n\tconst renamed: string[] = []\n\tconst collided: string[] = []\n\n\tfor (const master of masters) {\n\t\tfor (const layout of master.layouts) {\n\t\t\tconst index = out.length\n\t\t\tconst flattened = flattenAttributeValue(layout.name)\n\t\t\tif (flattened !== layout.name) renamed.push(`${JSON.stringify(layout.name)} → ${JSON.stringify(flattened)}`)\n\t\t\tconst base = flattened || `Layout ${index + 1}`\n\t\t\tlet title = base\n\t\t\tfor (let suffix = 2; used.has(title); suffix++) title = `${base} (${suffix})`\n\t\t\tif (title !== base) collided.push(`${JSON.stringify(base)} → ${JSON.stringify(title)}`)\n\t\t\tused.add(title)\n\n\t\t\tconst placeholders = layout.placeholders.length\n\t\t\tif (placeholders > 0) {\n\t\t\t\tplaceholderCount += placeholders\n\t\t\t\tplaceholderLayouts++\n\t\t\t}\n\n\t\t\t// The layout's own background if it has one, else the master's — which is what a slide\n\t\t\t// bound to that layout actually shows, and the only tier the write API can set it at.\n\t\t\tconst background = backgroundProps(layout.background ?? master.background, notes, assets)\n\t\t\tconst objects = layoutObjects(layout, notes, assets)\n\t\t\tout.push({\n\t\t\t\tlayoutIndex: index,\n\t\t\t\tprops: compact({\n\t\t\t\t\ttitle,\n\t\t\t\t\tbackground,\n\t\t\t\t\tobjects: objects.length > 0 ? objects : undefined,\n\t\t\t\t}) as Record<string, IrValue>,\n\t\t\t})\n\t\t}\n\t}\n\n\tif (collided.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.nameCollision',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`${collided.length} layout name(s) are not unique in the source — normally because the deck has several masters, each with its own \"Title and Content\" — and a layout title here is also the key addSlide({ masterTitle }) binds on, so duplicates cannot both exist. The later ones are suffixed and the slides bound to them follow: ${collided.join('; ')}`\n\t\t)\n\t}\n\tif (renamed.length > 0) {\n\t\tnotes.note(\n\t\t\t'master.name',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t`${renamed.length} layout name(s) contain a line break or tab, which cannot survive as a layout title: the write path emits the name as a literal XML attribute value rather than a character reference, and XML normalises whitespace in an attribute to spaces. Collapsed here so the emitted script says what the output will contain — ${renamed.join('; ')}`\n\t\t)\n\t}\n\tif (placeholderCount > 0) {\n\t\tnotes.note(\n\t\t\t'master.placeholders',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`the ${placeholderCount} placeholder definition(s) across ${placeholderLayouts} slide layout(s) are not reproduced: the write path seeds every slide with each layout placeholder the slide did not populate, and since every source shape is authored here as concrete content rather than into a placeholder, re-declaring them would add an empty shape to every slide rather than a prompt`\n\t\t)\n\t}\n\n\treturn out\n}\n\n/**\n * A layout's own shapes as the `objects` of its `defineSlideMaster` call — the bands, rules,\n * wordmarks and footer graphics that make a deck recognisable as somebody's template.\n *\n * **Placeholders are filtered out, not mapped.** They are the other half of a layout's tree and\n * the write path already reproduces them from the far side: `addPlaceholdersToSlideLayouts`\n * seeds every slide with each layout placeholder it did not populate, so re-declaring one here\n * would put an empty ghost shape on every slide bound to the layout (see the module header).\n * The test is a DOM predicate rather than `shape.placeholder`, because only `AutoShape` reports\n * one — see {@link isPlaceholderShape}.\n *\n * **A group is flattened into its children rather than dropped.** `SlideMasterObject` has no\n * `group` variant, and unlike the slide-side `addGroup` mapping this loses nothing visual:\n * `absoluteFrame` already composes an enclosing group's offset, rotation, flips *and* its\n * child-space scaling, so each child lands exactly where the group put it. What goes is the\n * grouping itself — one selectable object in PowerPoint becomes several.\n *\n * Notes are recorded through a {@link layoutShapeScope}, so the slide vocabulary the shared\n * mapper speaks lands under `layout.` and stays attributable to the layout tier. Constructs\n * written below are therefore relative to that prefix.\n */\nfunction layoutObjects(layout: SlideLayout, notes: NoteScope, assets: AssetResolver): IrValue[] {\n\tconst out: IrValue[] = []\n\tcollectObjects(layout.shapes, out, layoutShapeScope(notes), assets)\n\treturn out\n}\n\n/** {@link layoutObjects}'s walk, recursing through groups. */\nfunction collectObjects(shapes: AnyShape[], out: IrValue[], notes: NoteScope, assets: AssetResolver): void {\n\tfor (const shape of shapes) {\n\t\tif (isPlaceholderShape(shape.element_)) continue\n\n\t\tif (isGroupShape(shape)) {\n\t\t\tnotes\n\t\t\t\t.forShape(shape.name || null)\n\t\t\t\t.note(\n\t\t\t\t\t'group',\n\t\t\t\t\t'flattened',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t\"defineSlideMaster({ objects }) has no group variant, so this group's children are emitted as loose objects; they land in the same places — the group's offset, rotation, flips and child-space scaling are composed into each child's coordinates — but the layout no longer offers them as one selectable object\"\n\t\t\t\t)\n\t\t\tcollectObjects(shape.shapes, out, notes, assets)\n\t\t\tcontinue\n\t\t}\n\n\t\t// `null` is always already noted, either by the shared mapper (a hidden shape, a picture\n\t\t// with no bytes) or by `masterObject` itself (a kind with no variant in the union).\n\t\tconst object = masterObject(shape, notes, assets)\n\t\tif (object !== null) out.push(object)\n\t}\n}\n\n/**\n * Collapse the whitespace an XML attribute value cannot carry.\n *\n * Not a style choice: XML normalises a literal tab, carriage return or line feed inside an\n * attribute value to a space (XML 1.0 §3.3.3), and the write path emits a layout title as a\n * literal rather than as a ` ` character reference. So a PowerPoint layout named across\n * two lines — \"Abschnitts-⏎überschrift\" is a real one, in the German built-in set — comes back\n * with a space either way. Doing it here rather than leaving it to the serializer means the\n * emitted script states the title the output will actually have, and the round trip compares\n * two decks that agree instead of reporting a rename it cannot act on.\n */\nfunction flattenAttributeValue(value: string): string {\n\treturn value.replace(/[\\t\\r\\n]+/g, ' ')\n}\n\n/** A master/layout background reduced to what `BackgroundProps` accepts. */\nfunction backgroundProps(\n\tbackground: SlideBackground | null,\n\tnotes: NoteScope,\n\tassets: AssetResolver\n): IrValue | undefined {\n\tif (!background || background.type === 'none') return undefined\n\n\tswitch (background.type) {\n\t\tcase 'solid':\n\t\t\treturn background.color ? { color: literalColor(background.color.effectiveHex) } : undefined\n\t\tcase 'image': {\n\t\t\tconst asset = background.partName === null ? null : assets.assetFor(background.partName)\n\t\t\treturn asset ? { data: asset } : undefined\n\t\t}\n\t\tcase 'themeRef': {\n\t\t\t// `p:bgRef` indexes the theme's background fill list, which the write path cannot\n\t\t\t// author. The read model resolves it, so the flat colour survives even though the\n\t\t\t// reference — and therefore its response to a theme change — does not.\n\t\t\tconst fill = background.resolvedFill\n\t\t\tif (fill?.type === 'solid' && fill.color) {\n\t\t\t\tnotes.note(\n\t\t\t\t\t'master.background',\n\t\t\t\t\t'flattened',\n\t\t\t\t\t'unwritable',\n\t\t\t\t\t\"this layout's background is a theme reference (p:bgRef into the theme's background fill list), which has no write-API option; the colour it currently resolves to is baked in and stops following the theme\"\n\t\t\t\t)\n\t\t\t\treturn { color: literalColor(fill.color.effectiveHex) }\n\t\t\t}\n\t\t\tnotes.note(\n\t\t\t\t'master.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unwritable',\n\t\t\t\t\"this layout's background is a theme reference to a non-solid fill, which has no write-API option; the layout is emitted with no background\"\n\t\t\t)\n\t\t\treturn undefined\n\t\t}\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'master.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`a ${background.type} layout background is not expressible through the write API's background option, so the layout is emitted with no background`\n\t\t\t)\n\t\t\treturn undefined\n\t}\n}\n","/**\n * A slide's show transition (`p:transition`) → the write API's `TransitionProps`.\n *\n * **The whole difficulty is one type mismatch.** `TransitionInfo.type` is an *open string*,\n * because the read model decodes PowerPoint's modern effects (Morph, Vortex, Ripple, …)\n * alongside the base ECMA-376 ones and tells them apart by namespace rather than by name.\n * The write API's `TransitionType` is a closed union of 21 base names. Passing the read\n * model's string straight through would therefore produce a script that does not compile\n * for exactly the decks a converter is most likely to meet — a modern transition is what\n * PowerPoint's own UI offers first. So {@link WRITABLE_TYPES} is the filter, and a name that\n * does not survive it becomes a fidelity note rather than a compile error.\n *\n * **Why `speed` is always emitted.** `spd` is absent from most PowerPoint-authored\n * transitions (its schema default is `fast`) and the read model reports the default rather\n * than the absence, so there is nothing to distinguish \"absent\" from \"explicitly fast\". That\n * is harmless on its own — both read back as `fast`. What is *not* harmless is omitting it\n * when a duration is present: the write path then derives the bucket from `durationMs`\n * (`transitionSpeedForDuration`), and PowerPoint's own pairing does not always agree with\n * that formula — the sound fixture carries `spd=\"slow\"` with `p14:dur=\"2000\"`, which the\n * derivation happens to reproduce, while a 600ms `fast` transition would come back `med`.\n * Emitting the read value verbatim removes the derivation from the path entirely, which is\n * the same discipline the rest of the IR follows: state what was read, never recompute it.\n */\nimport type { Slide } from '../../read/api/slide.js'\nimport type { TransitionInfo } from '../../read/api/transition.js'\nimport type { TransitionType } from '../../types/animation.js'\nimport type { NoteScope } from '../fidelity.js'\nimport type { TransitionIr, TransitionSoundIr } from '../ir.js'\nimport type { AssetResolver } from './shape.js'\n\n/**\n * The transitions the write API can author, as a lookup.\n *\n * Spelled as a `Record` keyed by `TransitionType` rather than as an array of strings so the\n * compiler polices it in *both* directions: a name the union does not have is rejected here,\n * and a name the union gains without being added here fails to satisfy the record. A plain\n * `Set<string>` would silently drift out of date, and the symptom would be a printed script\n * that does not compile — found by whoever runs it, not by this repository's test suite.\n */\nconst WRITABLE_TYPES: Record<TransitionType, true> = {\n\tblinds: true,\n\tchecker: true,\n\tcircle: true,\n\tcomb: true,\n\tcover: true,\n\tcut: true,\n\tdiamond: true,\n\tdissolve: true,\n\tfade: true,\n\tnewsflash: true,\n\tplus: true,\n\tpull: true,\n\tpush: true,\n\trandom: true,\n\trandomBar: true,\n\tsplit: true,\n\tstrips: true,\n\twedge: true,\n\twheel: true,\n\twipe: true,\n\tzoom: true,\n}\n\n/**\n * `true` when the write API has a name for this transition.\n *\n * The namespace check does no work on PowerPoint's own output and is kept anyway. Every one\n * of the 21 modern effect names in the probed table (`conveyor`, `morph`, `vortex`, …) is\n * distinct from every base name, so today the name lookup alone would reach the same verdict\n * — measured, not assumed. But \"is this a base ECMA-376 transition\" is a question about the\n * *namespace*, and answering it by name would be relying on that disjointness holding for\n * every namespace Microsoft ever adds. The write path emits `p:${type}` unconditionally, so\n * the cost of being wrong is a modern effect silently rewritten as a base one with the same\n * name and no note — a conversion that reports itself as faithful. `script-ir.test.js`\n * authors a `p14:fade` to keep this branch honest, since no fixture can.\n */\nfunction isWritable(info: TransitionInfo): boolean {\n\treturn info.namespace === 'p' && Object.hasOwn(WRITABLE_TYPES, info.type)\n}\n\n/**\n * Map a slide's transition, recording a note for anything that does not survive.\n *\n * Returns `undefined` both when the slide has no transition and when it has one this\n * library cannot author — the difference between those two is what the note carries.\n */\nexport function transitionToIr(slide: Slide, notes: NoteScope, assets: AssetResolver): TransitionIr | undefined {\n\tconst info = slide.transition\n\tif (!info) return undefined\n\n\tif (!isWritable(info)) {\n\t\tnotes.note(\n\t\t\t'slide.transition',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`this slide's ${info.namespace === 'p' ? '' : `${info.namespace} `}${info.type} transition is not one of the 21 base ECMA-376 transitions the write API can author${\n\t\t\t\tinfo.namespace === 'p' ? '' : \" — it is one of PowerPoint's modern effects, which have no write-API vocabulary\"\n\t\t\t}, so the regenerated slide advances with no effect`\n\t\t)\n\t\treturn undefined\n\t}\n\n\t// Each optional key is spread in only when the source carried it, so an absent attribute\n\t// stays absent rather than becoming an explicit default the source never wrote.\n\tconst sound = soundToIr(slide, info, notes, assets)\n\treturn {\n\t\ttype: info.type,\n\t\tspeed: info.speed,\n\t\t...(info.durationMs === null ? {} : { durationMs: info.durationMs }),\n\t\t// Both are omitted at their OOXML default, so the emitted script says only what the\n\t\t// source said: `advClick` defaults to true and `advTm` to unset.\n\t\t...(info.advanceOnClick ? {} : { advanceOnClick: false }),\n\t\t...(info.advanceAfterMs === null ? {} : { advanceAfterMs: info.advanceAfterMs }),\n\t\t...(Object.keys(info.variant).length > 0 ? { variant: { ...info.variant } } : {}),\n\t\t...(sound ? { sound } : {}),\n\t}\n}\n\n/**\n * The transition's sound (`p:sndAc`), in the two forms OOXML gives it.\n *\n * The stop-previous form is pure structure — no relationship, no media part — so it maps\n * unconditionally. A start sound is an embedded WAV reached through the slide's own\n * relationships, which is the only place in this converter that resolves an `r:embed` by\n * hand: every other media reference arrives already resolved to a partname by the read\n * model's shape accessors, and a transition sound has no shape to hang off.\n */\nfunction soundToIr(\n\tslide: Slide,\n\tinfo: TransitionInfo,\n\tnotes: NoteScope,\n\tassets: AssetResolver\n): TransitionSoundIr | undefined {\n\tconst sound = info.sound\n\tif (!sound) return undefined\n\tif (sound.form === 'stop') return { stopPrevious: true }\n\n\tconst partName = soundPartName(slide, sound.embedRid)\n\tconst asset = partName === null ? null : assets.assetFor(partName)\n\tif (!asset) {\n\t\tnotes.note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t`this transition's start sound (${sound.embedRid ?? 'no r:embed'}) does not resolve to an audio part in the package, so the regenerated transition is silent`\n\t\t)\n\t\treturn undefined\n\t}\n\n\treturn {\n\t\tdata: asset,\n\t\t...(sound.name === null ? {} : { name: sound.name }),\n\t\t// Omitted at its default, like `advanceOnClick`: `p:stSnd@loop` defaults to false.\n\t\t...(sound.loop ? { loop: true } : {}),\n\t}\n}\n\n/** Resolve `p:snd@r:embed` to the audio part it names, or `null` when it does not resolve. */\nfunction soundPartName(slide: Slide, embedRid: string | null): string | null {\n\tif (!embedRid) return null\n\tconst relationship = slide.relationships.get(embedRid)\n\t// An External audio rel has no partname to read bytes from; `resolveTarget` throws on\n\t// both cases, so they are screened here rather than caught.\n\tif (!relationship || relationship.targetMode === 'External') return null\n\treturn slide.relationships.resolveTarget(embedRid)\n}\n","/**\n * `Presentation` → {@link DeckIr}. The entry point of the read half.\n *\n * Pure in the sense that matters: it reads a loaded package and returns data, touching no\n * filesystem and mutating nothing. Given the same bytes it returns the same IR, so a\n * round-trip check can compare two runs directly.\n *\n * The one judgement made at this level rather than per-shape is {@link SlideSource}. A\n * slide holding a construct the write API cannot express *at all* — a graphic frame with a\n * complete reader and no emitter, which today means an extended chart, a SmartArt diagram,\n * an OLE object or ink — cannot be honestly transcribed, because the output would silently\n * differ from the source. Such a slide is marked `carried` so the printer copies it instead.\n * That decision has to be made here, before any shape is mapped, since it is a property of\n * the slide as a whole.\n */\nimport type { Presentation } from '../../read/api/presentation.js'\nimport type { Slide } from '../../read/api/slide.js'\nimport { isGraphicFrame, isGroupShape, type AnyShape } from '../../read/api/shapes.js'\nimport { NoteCollector, scopeNotes, type NoteScope } from '../fidelity.js'\nimport type { AssetIr, AssetRef, BackgroundIr, CallIr, DeckIr, DeckPropsIr, SlideIr, SlideLayoutIr } from '../ir.js'\nimport { shapeCall, unwritableFramePayload, type AssetResolver } from './shape.js'\nimport { chromeToIr } from './chrome.js'\nimport { transitionToIr } from './transition.js'\nimport { compact } from './values.js'\n\n/** Default slide size (10\" × 7.5\") for a deck whose `presentation.xml` declares none. */\nconst DEFAULT_SLIDE_SIZE = { widthEmu: 9144000, heightEmu: 6858000 }\n\n/** Extensions by content type, so an emitted asset filename is one a viewer recognises. */\nconst ASSET_EXTENSIONS: Record<string, string> = {\n\t'image/png': 'png',\n\t'image/jpeg': 'jpg',\n\t'image/gif': 'gif',\n\t'image/bmp': 'bmp',\n\t'image/webp': 'webp',\n\t'image/tiff': 'tif',\n\t'image/x-emf': 'emf',\n\t'image/x-wmf': 'wmf',\n\t'image/svg+xml': 'svg',\n\t// PowerPoint authors the `x-` form for an embedded transition sound; both spellings\n\t// appear in the wild and neither has `wav` as its trailing path component.\n\t'audio/x-wav': 'wav',\n\t'audio/wav': 'wav',\n\t'audio/mpeg': 'mp3',\n}\n\n/**\n * Collects media as shapes reference it, assigning each part a stable sequential name.\n *\n * Names are assigned in first-reference order rather than derived from the source part\n * name, so the output is deterministic for a given deck and does not leak whatever the\n * source package happened to call its files. A part referenced twice resolves to one asset.\n *\n * Numbering runs per *kind* (`image1.png`, `image2.png`, `audio1.wav`) rather than over one\n * shared counter. Not cosmetics: the asset name becomes a `const` identifier in the emitted\n * script and a filename in its asset directory, and a transition sound bound to `image7`\n * reads as a bug in the generated source every time anyone opens it.\n */\nclass Assets implements AssetResolver {\n\treadonly #byPartName = new Map<string, AssetRef>()\n\treadonly #assets: AssetIr[] = []\n\treadonly #counts = new Map<string, number>()\n\n\tconstructor(private readonly pres: Presentation) {}\n\n\tassetFor(partName: string): AssetRef | null {\n\t\tconst existing = this.#byPartName.get(partName)\n\t\tif (existing) return existing\n\n\t\tconst part = this.pres.opc.part(partName)\n\t\tif (!part) return null\n\n\t\tconst extension = ASSET_EXTENSIONS[part.contentType] ?? partName.split('.').pop() ?? 'bin'\n\t\tconst kind = part.contentType.startsWith('audio/') ? 'audio' : 'image'\n\t\tconst index = (this.#counts.get(kind) ?? 0) + 1\n\t\tthis.#counts.set(kind, index)\n\t\tconst name = `${kind}${index}.${extension}`\n\t\tconst ref: AssetRef = { $asset: name }\n\t\tthis.#byPartName.set(partName, ref)\n\t\tthis.#assets.push({ name, contentType: part.contentType, bytes: part.bytes })\n\t\treturn ref\n\t}\n\n\tcontentTypeOf(partName: string): string | null {\n\t\treturn this.pres.opc.part(partName)?.contentType ?? null\n\t}\n\n\tget assets(): AssetIr[] {\n\t\treturn this.#assets\n\t}\n}\n\n/** Convert a loaded deck into its IR. */\nexport function readModelToIr(pres: Presentation): DeckIr {\n\tconst collector = new NoteCollector()\n\tconst assets = new Assets(pres)\n\tconst size = pres.slideSize\n\tconst deckScope = scopeNotes(collector, null)\n\n\tif (!size) {\n\t\tdeckScope.note(\n\t\t\t'deck.slideSize',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t`this deck declares no slide size, so the output uses the ${DEFAULT_SLIDE_SIZE.widthEmu / 914400}in × ${DEFAULT_SLIDE_SIZE.heightEmu / 914400}in default`\n\t\t)\n\t}\n\n\tconst layouts = layoutGallery(pres)\n\t// Before the slides, so the chrome's deck-level notes lead the list the way the chrome\n\t// leads the deck. Assets are shared: a layout background image and a slide image that are\n\t// the same part resolve to one asset.\n\tconst chrome = chromeToIr(pres, deckScope, assets)\n\tconst slides = pres.slides.map((slide, index) => slideToIr(slide, index + 1, collector, assets, layouts))\n\n\treturn {\n\t\tslideSize: size ? { widthEmu: size.widthEmu, heightEmu: size.heightEmu } : DEFAULT_SLIDE_SIZE,\n\t\tprops: deckProps(pres, deckScope),\n\t\tchrome,\n\t\tslides,\n\t\tassets: assets.assets,\n\t\tfidelity: collector.notes,\n\t}\n}\n\n/**\n * Deck properties, reduced to the five `docProps` fields the write API sets. The other\n * seven the read model exposes have no setter — they survive anyway in a template-anchored\n * output, since the source deck itself becomes the template, so this is only a loss for a\n * standalone one.\n */\nfunction deckProps(pres: Presentation, notes: NoteScope): DeckPropsIr {\n\tconst core = pres.coreProperties\n\tconst carried = ['keywords', 'description', 'category', 'contentStatus', 'lastModifiedBy'] as const\n\tif (carried.some((key) => core[key] !== undefined)) {\n\t\tnotes.note(\n\t\t\t'deck.docProps',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t'only title, author, company, subject and revision have write-API setters; keywords, description, category, content status and last-modified-by have none'\n\t\t)\n\t}\n\treturn (\n\t\tcompact({\n\t\t\ttitle: core.title,\n\t\t\tauthor: core.creator,\n\t\t\tsubject: core.subject,\n\t\t\trevision: core.revision,\n\t\t}) ?? {}\n\t)\n}\n\n/**\n * The deck's layouts keyed by partname, each resolved to what a printer needs to bind to\n * it: its gallery position and whether its name identifies it on its own.\n *\n * Built once per deck rather than per slide — `layouts()` walks every master's layout list,\n * and the uniqueness question is about the gallery as a whole, so asking it per slide would\n * be both quadratic and unable to see layouts no slide happens to use.\n */\nfunction layoutGallery(pres: Presentation): Map<string, SlideLayoutIr> {\n\tconst handles = pres.layouts()\n\tconst nameCounts = new Map<string, number>()\n\tfor (const handle of handles) nameCounts.set(handle.name, (nameCounts.get(handle.name) ?? 0) + 1)\n\n\treturn new Map(\n\t\thandles.map((handle, index) => [\n\t\t\thandle.partName,\n\t\t\t{ name: handle.name, index, nameIsUnique: (nameCounts.get(handle.name) ?? 0) === 1 },\n\t\t])\n\t)\n}\n\nfunction slideToIr(\n\tslide: Slide,\n\tnumber: number,\n\tcollector: NoteCollector,\n\tassets: Assets,\n\tlayouts: Map<string, SlideLayoutIr>\n): SlideIr {\n\tconst notes = scopeNotes(collector, number)\n\tconst layoutPartName = slide.layout?.partName\n\tconst base = {\n\t\tnumber,\n\t\tlayout: (layoutPartName === undefined ? undefined : layouts.get(layoutPartName)) ?? null,\n\t\thidden: slide.hidden,\n\t\t...(slide.name ? { name: slide.name } : {}),\n\t\t...backgroundOf(slide, notes),\n\t\t...notesOf(slide, notes),\n\t}\n\n\tconst transition = transitionToIr(slide, notes, assets)\n\tconst carried = hasUnwritableContent(slide)\n\tif (carried) {\n\t\tnotes.note(\n\t\t\t'slide.carried',\n\t\t\t'flattened',\n\t\t\t'unwritable',\n\t\t\t'this slide holds a graphic frame the write API cannot author (an extended chart, a SmartArt diagram, an OLE object or ink); a printer that can copy the source slide does so instead of transcribing it, so it renders correctly but the emitted script does not describe its contents. The per-shape note beside this one says which construct forced the copy'\n\t\t)\n\t}\n\n\t// Mapped even for a carried slide: a printer with no source package to copy from prints\n\t// these and loses only the unwritable construct, rather than the whole slide. Each shape\n\t// records its own note, so that loss is declared either way.\n\tconst calls: CallIr[] = []\n\tfor (const shape of slide.shapes) {\n\t\tconst call = shapeCall(shape, notes, assets)\n\t\tif (call) calls.push(call)\n\t}\n\n\t// Build animations are recorded once per slide rather than per shape, since they live in a\n\t// slide-scoped element with no shape to attribute them to.\n\trecordAnimationLoss(slide, notes)\n\n\treturn {\n\t\t...base,\n\t\t...(transition ? { transition } : {}),\n\t\tsource: carried ? 'carried' : 'authored',\n\t\tcalls,\n\t}\n}\n\n/**\n * `true` when the slide holds something with no write-API expression at all, forcing a\n * carried slide. Descends into groups, since a group can host a graphic frame.\n *\n * Membership comes from {@link unwritableFramePayload}, which `graphicFrameCall` also uses to\n * pick its note — one enumeration, so the two cannot drift apart again. This test named\n * extended charts alone until then, which is why a slide holding SmartArt (or an OLE object,\n * or ink) was transcribed as `authored` and rendered with a hole where the graphic had been.\n */\nfunction hasUnwritableContent(slide: Slide): boolean {\n\tconst check = (shapes: AnyShape[]): boolean =>\n\t\tshapes.some((shape) => {\n\t\t\tif (isGroupShape(shape)) return check(shape.shapes)\n\t\t\treturn isGraphicFrame(shape) && unwritableFramePayload(shape) !== null\n\t\t})\n\treturn check(slide.shapes)\n}\n\nfunction backgroundOf(slide: Slide, notes: NoteScope): { background?: BackgroundIr } {\n\tconst background = slide.background\n\t// An inherited background comes with the layout, so re-authoring it onto the slide would\n\t// pin a colour that should keep following the layout.\n\tif (!background || background.source !== 'slide') return {}\n\n\tswitch (background.type) {\n\t\tcase 'solid':\n\t\t\treturn background.color\n\t\t\t\t? { background: compact({ color: background.color.effectiveHex.replace(/^#/, '').toUpperCase() }) }\n\t\t\t\t: {}\n\t\tcase 'none':\n\t\t\treturn {}\n\t\tdefault:\n\t\t\tnotes.note(\n\t\t\t\t'slide.background',\n\t\t\t\t'dropped',\n\t\t\t\t'unsupported',\n\t\t\t\t`a ${background.type} slide background is not expressible through the write API's background option, so the slide takes its layout's background`\n\t\t\t)\n\t\t\treturn {}\n\t}\n}\n\nfunction notesOf(slide: Slide, notes: NoteScope): { notesText?: string } {\n\tconst text = slide.notesText\n\tif (!text) return {}\n\tconst frame = slide.notesTextFrame\n\tif (frame && frame.paragraphs.some((paragraph) => paragraph.runs.some((run) => run.bold || run.italic))) {\n\t\tnotes.note(\n\t\t\t'notes.formatting',\n\t\t\t'flattened',\n\t\t\t'unsupported',\n\t\t\t\"speaker notes carry as plain text; per-run formatting and the notes slide's own placeholder geometry do not\"\n\t\t)\n\t}\n\treturn { notesText: text }\n}\n\n/**\n * Build animations, which live in a slide-scoped `p:timing` element rather than in any\n * shape's subtree.\n *\n * The transition next door used to be recorded here for the same reason and is now mapped\n * instead (`from-read/transition.ts`), which leaves this the one genuinely slide-scoped\n * loss: there is no structural reader for `p:timing` at all, only spid manipulation for the\n * deck-to-deck import path, so a build sequence is invisible to this converter.\n */\nfunction recordAnimationLoss(slide: Slide, notes: NoteScope): void {\n\tif (slide.hasAnimations) {\n\t\tnotes.note(\n\t\t\t'slide.animation',\n\t\t\t'dropped',\n\t\t\t'unread',\n\t\t\t'build animations have no structural reader (p:timing is only manipulated by spid for the deck-to-deck import path), so every shape on this slide lands static'\n\t\t)\n\t}\n}\n","/**\n * {@link IrValue} → TypeScript source text.\n *\n * This module is deliberately the dumbest part of the subsystem. It knows nothing about\n * decks, shapes, or units — only how a value is spelled. Every semantic decision was made\n * upstream in the read half, which is what lets the printed text be checked by comparing\n * IRs rather than by reading source: if this file were allowed to interpret, the same\n * construct could mean two things depending on which half you asked.\n *\n * Two consequences worth stating, because they are easy to erode later:\n *\n * - **Numbers are printed, not reformatted.** The IR already holds geometry either as a\n * `` `${n}emu` `` string (exact) or as a six-decimal inch number (the proven minimum for\n * an EMU-exact round-trip). Rounding here to suppress `0.5000000001`-style noise would\n * turn a cosmetic problem into a real geometry loss, so `printNumber` only refuses\n * values JavaScript cannot spell back.\n * - **Layout is a function of the value alone.** Whether an object prints on one line or\n * several depends only on its rendered width, never on where it came from, so the same\n * deck prints byte-identical text every time.\n */\nimport { isAssetRef, type AssetRef, type IrValue } from '../ir.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** Matches `.oxfmtrc.jsonc`: `printWidth: 120`. */\nconst MAX_WIDTH = 120\n\n/**\n * Columns a tab is assumed to occupy when measuring against {@link MAX_WIDTH}. The\n * formatter's default `tabWidth`, since the repo sets `useTabs` but not `tabWidth`.\n */\nconst TAB_COLUMNS = 2\n\n/** A bare object key needs no quotes only if it is a plain identifier. */\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/**\n * Resolves an {@link AssetRef} to the source text that stands in for it — a `const`\n * identifier when assets are written as files, an inline `data:` literal otherwise. The\n * printer takes this as a callback rather than deciding itself, because the choice belongs\n * to the caller's output layout, not to how a value is spelled.\n */\nexport type AssetPrinter = (ref: AssetRef) => string\n\n/**\n * A string literal in the repo's style (`singleQuote: true`).\n *\n * Deck text is arbitrary user content, so every case below is reachable in practice: a\n * quote, a backslash, a hard line break inside a run. `JSON.stringify` would handle those\n * correctly — it is avoided here for the quote style, not for correctness.\n */\nexport function printString(value: string): string {\n\tlet out = \"'\"\n\tfor (const char of value) {\n\t\tswitch (char) {\n\t\t\tcase '\\\\':\n\t\t\t\tout += '\\\\\\\\'\n\t\t\t\tbreak\n\t\t\tcase \"'\":\n\t\t\t\tout += \"\\\\'\"\n\t\t\t\tbreak\n\t\t\tcase '\\n':\n\t\t\t\tout += '\\\\n'\n\t\t\t\tbreak\n\t\t\tcase '\\r':\n\t\t\t\tout += '\\\\r'\n\t\t\t\tbreak\n\t\t\tcase '\\t':\n\t\t\t\tout += '\\\\t'\n\t\t\t\tbreak\n\t\t\tdefault: {\n\t\t\t\tconst code = char.codePointAt(0) ?? 0\n\t\t\t\t// C0/C1 controls have no visible spelling, so a raw one is invisible corruption.\n\t\t\t\t// U+2028/U+2029 have been legal inside a string literal since ES2019 and do not\n\t\t\t\t// strictly need escaping for a modern engine — they are escaped anyway because\n\t\t\t\t// they remain line terminators everywhere *else* in the grammar, and a file that\n\t\t\t\t// depends on that distinction is a poor thing to hand to an unknown toolchain.\n\t\t\t\t// Everything else rides through, so the script stays readable in the deck's language.\n\t\t\t\tconst escape = code < 0x20 || (code >= 0x7f && code <= 0x9f) || code === 0x2028 || code === 0x2029\n\t\t\t\tout += escape ? '\\\\u' + code.toString(16).padStart(4, '0') : char\n\t\t\t}\n\t\t}\n\t}\n\treturn `${out}'`\n}\n\n/**\n * A number literal. `String` gives the shortest text that reads back as the same double,\n * which is exactly the guarantee needed: the printed script must produce the same value the\n * IR held. Non-finite values cannot satisfy that (`NaN` and `Infinity` are identifiers, not\n * literals) and never reach here from a well-formed IR, so they throw rather than emit\n * source that would not run.\n */\nfunction printNumber(value: number): string {\n\tif (!Number.isFinite(value))\n\t\tthrow new InvalidOptionError('script/non-finite-literal', `Cannot print a non-finite number: ${value}`)\n\treturn String(value)\n}\n\n/** An object key, bare when it is a plain identifier and quoted when it is not. */\nfunction printKey(key: string): string {\n\treturn IDENTIFIER.test(key) ? key : printString(key)\n}\n\n/** The value on a single line, however long that line comes out. */\nfunction inline(value: IrValue, asset: AssetPrinter): string {\n\tif (value === null) return 'null'\n\tif (typeof value === 'boolean') return String(value)\n\tif (typeof value === 'number') return printNumber(value)\n\tif (typeof value === 'string') return printString(value)\n\tif (isAssetRef(value)) return asset(value)\n\tif (Array.isArray(value)) return `[${value.map((item) => inline(item, asset)).join(', ')}]`\n\n\tconst keys = Object.keys(value)\n\tif (keys.length === 0) return '{}'\n\treturn `{ ${keys.map((key) => `${printKey(key)}: ${inline(value[key] as IrValue, asset)}`).join(', ')} }`\n}\n\n/**\n * The value as source text, broken across lines only where it would otherwise overflow\n * {@link MAX_WIDTH}.\n *\n * `indentLevel` is the depth the value *starts* at, so a caller that has already written a\n * prefix (`slide1.addText(`) passes the level its closing brace should line up with.\n */\nexport function printValue(value: IrValue, indentLevel: number, asset: AssetPrinter): string {\n\tconst flat = inline(value, asset)\n\tif (indentLevel * TAB_COLUMNS + flat.length <= MAX_WIDTH) return flat\n\n\t// Only containers can be broken up; a single long string or number stays long.\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\n\tif (Array.isArray(value)) {\n\t\tif (value.length === 0) return '[]'\n\t\tconst items = value.map((item) => `${inner}${printValue(item, indentLevel + 1, asset)},`)\n\t\treturn `[\\n${items.join('\\n')}\\n${pad}]`\n\t}\n\n\tif (typeof value === 'object' && value !== null && !isAssetRef(value)) {\n\t\tconst keys = Object.keys(value)\n\t\tif (keys.length === 0) return '{}'\n\t\tconst entries = keys.map(\n\t\t\t(key) => `${inner}${printKey(key)}: ${printValue(value[key] as IrValue, indentLevel + 1, asset)},`\n\t\t)\n\t\treturn `{\\n${entries.join('\\n')}\\n${pad}}`\n\t}\n\n\treturn flat\n}\n\n/**\n * A call's argument list, either inline after `prefix` or one argument per line.\n *\n * The decision is made on the *whole* call rather than per argument, so a call either reads\n * as one line or as a list — never as a short first argument followed by a hanging brace,\n * which is what a per-argument rule produces.\n */\nexport function printArguments(prefix: string, args: IrValue[], indentLevel: number, asset: AssetPrinter): string {\n\tconst pad = '\\t'.repeat(indentLevel)\n\tconst flat = `${pad}${prefix}(${args.map((arg) => inline(arg, asset)).join(', ')})`\n\tif (indentLevel * TAB_COLUMNS + flat.length - pad.length <= MAX_WIDTH) return flat\n\n\t// No trailing comma after the final argument: `trailingComma: 'es5'` adds them inside\n\t// objects and arrays but not to an argument list, so one here would be reformatted away.\n\tconst inner = '\\t'.repeat(indentLevel + 1)\n\tconst printed = args.map((arg) => `${inner}${printValue(arg, indentLevel + 1, asset)}`)\n\treturn `${pad}${prefix}(\\n${printed.join(',\\n')}\\n${pad})`\n}\n","/**\n * The parts of printing a script that do not depend on which tier is being printed.\n *\n * Two printers target the same IR — one anchored to the source deck as a template, one\n * standalone — and they differ only in how a deck and its chrome are set up. Everything after\n * that is identical: a slide's statements, how image bytes reach the script, and how the\n * fidelity notes are rendered into the banner. Keeping that here is not tidiness. A slide body\n * printed two slightly different ways would mean the round-trip oracle certifies one tier and\n * only resembles a check on the other, and the drift would be invisible in review.\n */\nimport { asIrValue, type AssetRef, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\nimport { scopeNotes, type FidelityNote, type NoteCollector } from '../fidelity.js'\nimport { printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport { InvalidOptionError } from '../../errors.js'\n\n/** How image bytes reach the emitted script. */\nexport type AssetMode =\n\t/** Written beside the script and read at run time. Keeps the script readable. */\n\t| 'file'\n\t/** Inlined as `data:` literals. One self-contained file, at roughly 4/3 the byte size. */\n\t| 'inline'\n\nexport interface PrintedScript {\n\t/** The TypeScript module source. */\n\tcode: string\n\t/**\n\t * Image bytes the script expects to find in its asset directory, keyed by filename.\n\t * Empty when the print options asked for `'inline'`, since the bytes are then in\n\t * {@link code}.\n\t */\n\tassets: Map<string, Uint8Array>\n\t/**\n\t * The losses that apply to **this** output: the IR's own notes, minus any this tier\n\t * rescues, plus the ones this tier causes. Reproduced as a comment block at the top of\n\t * {@link code}, so the artifact carries its own caveats.\n\t */\n\tnotes: FidelityNote[]\n}\n\n/**\n * Default import specifier for an emitted script — this package's *published* name, which is\n * not its directory name. Getting it wrong produces a script that prints and typechecks and\n * then fails at `import`, so it is pinned by a test rather than left to a literal.\n */\nexport const PACKAGE_NAME = '@shbernal/ts-pptx'\n\n/** The print options both tiers share, with their defaults applied. */\nexport interface ResolvedPrintOptions {\n\t/** Where the emitted script writes its deck, resolved against the script's own location. */\n\toutputPath: string\n\t/** Where the emitted script reads image assets from, with any trailing slash stripped. */\n\tassetDir: string\n\t/** Whether image bytes are written beside the script or inlined as `data:` literals. */\n\tassetMode: AssetMode\n\t/** The import specifier the emitted script uses. */\n\tpackageName: string\n}\n\n/**\n * Apply the defaults both printers share.\n *\n * `templatePath` is deliberately not here: only the template-anchored tier has one, and that\n * difference is the whole reason there are two printers.\n * @param options - the caller's options, any of which may be absent\n */\nexport function resolvePrintOptions(options: {\n\toutputPath?: string\n\tassetDir?: string\n\tassets?: AssetMode\n\tpackageName?: string\n}): ResolvedPrintOptions {\n\treturn {\n\t\toutputPath: options.outputPath ?? './output.pptx',\n\t\t// A trailing slash would print `./assets/` and then join another, so it is stripped once\n\t\t// here rather than defended against at each of the places the directory is interpolated.\n\t\tassetDir: (options.assetDir ?? './assets').replace(/\\/$/, ''),\n\t\tassetMode: options.assets ?? 'file',\n\t\tpackageName: options.packageName ?? PACKAGE_NAME,\n\t}\n}\n\n/** Width the header comment's prose wraps at, leaving room for the ` * ` prefix. */\nconst COMMENT_WIDTH = 110\n\n/**\n * A stable JavaScript identifier per asset.\n *\n * Derived from the asset's own name rather than its index, so a reader can match a `const`\n * in the script against a file in the asset directory. The dedupe suffix is defensive: the\n * read half currently names assets `image1.png`, `image2.jpg`, … which cannot collide after\n * the extension is stripped, but nothing in the IR contract promises that.\n */\nexport function assetIdentifiers(ir: DeckIr): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tconst used = new Set<string>()\n\tfor (const asset of ir.assets) {\n\t\tconst base = asset.name.replace(/\\.[^.]*$/, '').replace(/[^A-Za-z0-9_$]/g, '_')\n\t\tlet identifier = /^[A-Za-z_$]/.test(base) ? base : `_${base}`\n\t\tlet suffix = 2\n\t\twhile (used.has(identifier)) identifier = `${base}_${suffix++}`\n\t\tused.add(identifier)\n\t\tout.set(asset.name, identifier)\n\t}\n\treturn out\n}\n\n/** Resolve an {@link AssetRef} to the `const` identifier standing for its bytes. */\nexport function assetPrinter(identifiers: Map<string, string>): AssetPrinter {\n\treturn (ref: AssetRef): string => {\n\t\tconst identifier = identifiers.get(ref.$asset)\n\t\tif (!identifier)\n\t\t\tthrow new InvalidOptionError(\n\t\t\t\t'script/unresolved-asset-reference',\n\t\t\t\t`Asset reference ${ref.$asset} has no entry in DeckIr.assets`\n\t\t\t)\n\t\treturn identifier\n\t}\n}\n\n/**\n * One `const` per asset, each holding a complete `data:` URI.\n *\n * Both modes bind the same *kind* of value — a data URI string — so the call sites are\n * identical and `addImage`'s `data` option is used either way. Only where the bytes come\n * from changes. Rewriting the option key to `path` in file mode would have the printer\n * reshaping an argument, which is precisely the thing that keeps the IR checkable.\n */\nexport function printAssetBindings(\n\tir: DeckIr,\n\tidentifiers: Map<string, string>,\n\tassetDir: string,\n\tmode: AssetMode,\n\tinlineComment = '// Media bytes, inlined so this script needs no files but its template.'\n): string[] {\n\tif (ir.assets.length === 0) return []\n\n\tconst lines =\n\t\tmode === 'file' ? ['// Media bytes, loaded from the asset directory beside this script.'] : [inlineComment]\n\n\tfor (const asset of ir.assets) {\n\t\tconst identifier = identifiers.get(asset.name)\n\t\tif (!identifier) continue\n\t\tif (mode === 'file') {\n\t\t\tconst path = printString(`${assetDir}/${asset.name}`)\n\t\t\tlines.push(\n\t\t\t\t`const ${identifier} = \\`data:${asset.contentType};base64,\\${(await readFile(here(${path}))).toString('base64')}\\``\n\t\t\t)\n\t\t} else {\n\t\t\tlines.push(`const ${identifier} = ${printString(`data:${asset.contentType};base64,${toBase64(asset.bytes)}`)}`)\n\t\t}\n\t}\n\treturn lines\n}\n\n/** Base64 without `Buffer`, matching the rest of the library's isomorphic media handling. */\nfunction toBase64(bytes: Uint8Array): string {\n\tlet binary = ''\n\t// Chunked because String.fromCharCode is applied to the whole slice at once, and a\n\t// megabyte-sized spread overflows the argument limit.\n\tconst CHUNK = 0x8000\n\tfor (let i = 0; i < bytes.length; i += CHUNK) {\n\t\tbinary += String.fromCharCode(...bytes.subarray(i, i + CHUNK))\n\t}\n\treturn btoa(binary)\n}\n\n/**\n * One slide: a comment, the statement that creates it, then its slide-level properties and\n * its calls in z-order.\n *\n * `comment` and `construction` are the tier's business — one binds a layout by name at append\n * time, the other names a master up front — and everything after them is not.\n */\nexport function printSlide(\n\tslide: SlideIr,\n\tparts: { comment: string; construction: string },\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tconst notes = scopeNotes(collector, slide.number)\n\tconst identifier = `slide${slide.number}`\n\tconst lines = ['', `// ${parts.comment}`, `const ${identifier} = ${parts.construction}`]\n\n\tif (slide.name !== undefined) {\n\t\tnotes.note(\n\t\t\t'slide.name',\n\t\t\t'dropped',\n\t\t\t'unwritable',\n\t\t\t`the slide's own name (p:cSld@name, here ${JSON.stringify(slide.name)}) has no public write-API setter, so the generated slide is unnamed`\n\t\t)\n\t}\n\n\tif (slide.hidden) lines.push(`${identifier}.hidden = true`)\n\tif (slide.background) {\n\t\tlines.push(`${identifier}.background = ${printValue(slide.background as IrValue, 0, printAsset)}`)\n\t}\n\tif (slide.transition) {\n\t\tlines.push(`${identifier}.transition = ${printValue(asIrValue(slide.transition), 0, printAsset)}`)\n\t}\n\tif (slide.notesText !== undefined) {\n\t\tlines.push(printArguments(`${identifier}.addNotes`, [slide.notesText], 0, printAsset))\n\t}\n\n\tfor (const call of slide.calls) {\n\t\t// The source shape name makes a fidelity note navigable: a note carries the same\n\t\t// name, and without it a reader has no way to find the call it refers to.\n\t\tif (call.sourceName) lines.push(`// ${call.sourceName.replace(/\\s+/g, ' ')}`)\n\t\tlines.push(printArguments(`${identifier}.${call.method}`, call.args, 0, printAsset))\n\t}\n\n\treturn lines\n}\n\n/** The banner comment: `prose` as written, then every loss that applies to this output. */\nexport function header(prose: string[], notes: FidelityNote[]): string {\n\tconst lines = [...prose, '']\n\n\tif (notes.length === 0) {\n\t\tlines.push('FIDELITY: nothing was lost that this converter can detect.')\n\t} else {\n\t\tlines.push(\n\t\t\t`FIDELITY: ${notes.length} declared loss(es). Everything not listed here is expected to`,\n\t\t\t'survive unchanged; a difference that is not in this list is a defect, not a caveat.',\n\t\t\t''\n\t\t)\n\t\tfor (const [scope, group] of groupNotes(notes)) {\n\t\t\tlines.push(`${scope}:`)\n\t\t\tfor (const note of group) {\n\t\t\t\tconst where = note.shapeName ? ` (${note.shapeName})` : ''\n\t\t\t\tlines.push(\n\t\t\t\t\t...wrap(\n\t\t\t\t\t\t`- ${note.construct}${where} [${note.disposition}, ${note.cause}] — ${note.detail}`,\n\t\t\t\t\t\tCOMMENT_WIDTH,\n\t\t\t\t\t\t' '\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ['/*', ...lines.map((line) => (line ? ` * ${line}` : ' *')), ' */'].join('\\n')\n}\n\n/** Notes bucketed by slide, in deck order, so a reader meets them the way they meet the deck. */\nfunction groupNotes(notes: FidelityNote[]): Array<[string, FidelityNote[]]> {\n\tconst deckLevel = notes.filter((note) => note.slideNumber === null)\n\tconst bySlide = new Map<number, FidelityNote[]>()\n\tfor (const note of notes) {\n\t\tif (note.slideNumber === null) continue\n\t\tconst existing = bySlide.get(note.slideNumber)\n\t\tif (existing) existing.push(note)\n\t\telse bySlide.set(note.slideNumber, [note])\n\t}\n\n\tconst out: Array<[string, FidelityNote[]]> = []\n\tif (deckLevel.length > 0) out.push(['Deck', deckLevel])\n\tfor (const number of [...bySlide.keys()].sort((a, b) => a - b)) {\n\t\tout.push([`Slide ${number}`, bySlide.get(number) ?? []])\n\t}\n\treturn out\n}\n\n/** Wrap prose to `width`, indenting every line after the first by `continuation`. */\nfunction wrap(text: string, width: number, continuation: string): string[] {\n\tconst words = text.split(/\\s+/).filter(Boolean)\n\tconst lines: string[] = []\n\tlet current = ''\n\tfor (const word of words) {\n\t\tconst candidate = current ? `${current} ${word}` : `${continuation}${word}`\n\t\tif (current && candidate.length > width) {\n\t\t\tlines.push(current)\n\t\t\tcurrent = `${continuation}${word}`\n\t\t} else {\n\t\t\tcurrent = current ? candidate : word\n\t\t}\n\t}\n\tif (current) lines.push(current)\n\treturn lines\n}\n\n/**\n * Close out a printed script: the accumulated lines as one module source, plus the\n * asset side-car the caller has to write beside it.\n *\n * Both tiers end this way, and the `assetMode` test is the whole reason it is worth\n * naming. In `'inline'` mode the bytes are already in {@link PrintedScript.code} as\n * `data:` literals, so the map must come back **empty** — a tier that returned them\n * anyway would have its caller write every image to disk as well, and the script would\n * ignore the files it was handed.\n * @param {string[]} lines - the script's lines, in order\n * @param {DeckIr} ir - the IR being printed, for its assets\n * @param {AssetMode} assetMode - how image bytes reach the script\n * @param {FidelityNote[]} notes - the losses that apply to this output\n * @returns {PrintedScript} the finished script\n */\nexport function printedScript(lines: string[], ir: DeckIr, assetMode: AssetMode, notes: FidelityNote[]): PrintedScript {\n\treturn {\n\t\tcode: lines.join('\\n'),\n\t\tassets: new Map(\n\t\t\tassetMode === 'file' ? ir.assets.map((asset): [string, Uint8Array] => [asset.name, asset.bytes]) : []\n\t\t),\n\t\tnotes,\n\t}\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module, template-anchored. **Tier B.**\n *\n * **The tier.** The emitted script reuses the *source deck itself* as its template:\n * `Presentation.fromTemplate` strips a package's slides while leaving its masters, layouts,\n * theme, and document properties byte-identical, so the chrome is never regenerated — it is\n * the original. Only the slides are rebuilt, through the public write API, and grafted back\n * with `appendSlides`. That is why this tier's fidelity note list is short: everything the\n * converter cannot see or cannot write is confined to slide content, and the whole of the\n * deck's design survives because nothing ever tried to reproduce it.\n *\n * It also means the plan's \"strip the source slides\" step needs no helper. `fromTemplate`\n * already does exactly that, and does it without pruning shared parts, so the template\n * asset and the source deck are the same file.\n *\n * **Order is not rearranged.** Slides are emitted in source order and every operation\n * appends, so `p:sldIdLst` comes out in the original order without any position arithmetic.\n * Contiguous slides sharing a layout share one generator, because `appendSlides` binds\n * every slide in one call to a single layout — the batching is forced by that signature,\n * not chosen for tidiness.\n *\n * **This module may add fidelity notes.** A loss can belong to the *tier* rather than to\n * the conversion — a slide's `p:cSld@name` is read fine and would survive a byte copy, but\n * has no public write-API setter, so it dies here and nowhere else. {@link PrintedScript}\n * therefore returns the notes that actually apply to *this* output, which is also the set a\n * round-trip check should exclude from its diff.\n *\n * The standalone counterpart is `printStandaloneScript` (Tier A), which prints the same IR\n * with no template at all and pays for it in the note list.\n */\nimport type { DeckIr, SlideIr } from '../ir.js'\nimport { LAYOUT_NOTE_PREFIX, NoteCollector, scopeNotes } from '../fidelity.js'\nimport { inches } from '../from-read/values.js'\nimport { printString, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype AssetMode,\n\ttype PrintedScript,\n} from './common.js'\n\nexport type { AssetMode, PrintedScript } from './common.js'\n\nexport interface PrintScriptOptions {\n\t/**\n\t * Path the emitted script loads its template from, resolved against the script's own\n\t * location. This is the **source deck unchanged** — `fromTemplate` strips its slides.\n\t * @default './template.pptx'\n\t */\n\ttemplatePath?: string\n\t/** Path the emitted script writes to, resolved against the script's own location. @default './output.pptx' */\n\toutputPath?: string\n\t/** Directory the emitted script reads image assets from, when {@link assets} is `'file'`. @default './assets' */\n\tassetDir?: string\n\t/** @default 'file' */\n\tassets?: AssetMode\n\t/**\n\t * Import specifier the emitted script uses, with `/read` appended for the read half.\n\t * Defaults to this package's own published name; override it to point a generated\n\t * script at a local build or a fork.\n\t * @default '@shbernal/ts-pptx'\n\t */\n\tpackageName?: string\n}\n\n/**\n * Constructs the IR declares lost that a template-anchored output keeps anyway.\n *\n * Document properties are the obvious case: the read half notes that only five of the twelve\n * have write-API setters, which is true and matters for a standalone output — but this tier\n * never authors them at all. They ride in the template, untouched, all twelve of them.\n *\n * The whole of the chrome is the same story on a larger scale. The theme's format scheme, the\n * master's text styles and colour map, the layouts' decoration and placeholder definitions —\n * every one of them is a genuine loss for a script that has to rebuild the deck's design, and\n * none of them is touched here, because the design *is* the template. A caveat that does not\n * apply to the output in front of you is worse than no caveat: it teaches the reader to skim\n * the ones that do.\n *\n * Alongside this list, {@link isTemplateCarried} drops every note under\n * {@link LAYOUT_NOTE_PREFIX}. Those are the per-shape losses of re-authoring a layout's\n * decoration, recorded in the slide vocabulary because the shape mapper is shared — and every\n * one of them is about a layout, which this tier does not rebuild.\n */\nconst TEMPLATE_CARRIED_CONSTRUCTS = new Set([\n\t'deck.docProps',\n\t'master.background',\n\t'master.colorMap',\n\t'master.decoration',\n\t'master.multiple',\n\t// Both are about a layout *title* the standalone tier has to invent — deduplicated because\n\t// it doubles as a lookup key, whitespace-collapsed because the write path emits it as a raw\n\t// XML attribute value. Here the layout keeps its own `p:cSld@name`, untouched.\n\t'master.name',\n\t'master.nameCollision',\n\t'master.placeholders',\n\t'master.txStyles',\n\t'theme.fmtScheme',\n])\n\n/** `true` when the source deck carries this loss through untouched, so this tier does not have it. */\nfunction isTemplateCarried(construct: string): boolean {\n\treturn TEMPLATE_CARRIED_CONSTRUCTS.has(construct) || construct.startsWith(LAYOUT_NOTE_PREFIX)\n}\n\n/** Turn a deck IR into a runnable, template-anchored TypeScript module. */\nexport function printScript(ir: DeckIr, options: PrintScriptOptions = {}): PrintedScript {\n\tconst templatePath = options.templatePath ?? './template.pptx'\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst printAsset = assetPrinter(assetNames)\n\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst needsSource = ir.slides.some((slide) => slide.source === 'carried')\n\tconst needsFallbackLayout = ir.slides.some((slide) => slide.source === 'authored' && slide.layout === null)\n\n\t// Built last: the tier's own notes are only known once the slides have been walked.\n\tconst notes = [...ir.fidelity.filter((note) => !isTemplateCarried(note.construct)), ...collector.notes]\n\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t'Template-anchored: the source deck is reused as the template, so its slide masters,',\n\t\t\t\t'layouts, theme and document properties are the originals, byte for byte. Only the',\n\t\t\t\t'slide content below was rebuilt through the public write API.',\n\t\t\t\t'',\n\t\t\t\t`Expects ${templatePath} (the source deck, unmodified) beside this file${\n\t\t\t\t\tassetMode === 'file' && ir.assets.length > 0 ? `, plus ${ir.assets.length} media file(s) in ${assetDir}` : ''\n\t\t\t\t}.`,\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t\"import { readFile, writeFile } from 'node:fs/promises'\",\n\t\t\"import { fileURLToPath } from 'node:url'\",\n\t\t`import TsPptx from ${printString(packageName)}`,\n\t\t`import { Presentation } from ${printString(`${packageName}/read`)}`,\n\t\t'',\n\t\t'/** Resolve a path against this script rather than against the working directory. */',\n\t\t'const here = (name: string): string => fileURLToPath(new URL(name, import.meta.url))',\n\t\t'',\n\t\t'// The source deck is the template: fromTemplate strips its slides and leaves its masters,',\n\t\t'// layouts, theme and document properties exactly as they were.',\n\t\t`const deck = await Presentation.fromTemplate(here(${printString(templatePath)}))`,\n\t]\n\n\tif (needsSource) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// A second, unstripped handle on the same file, for the slides copied verbatim.',\n\t\t\t`const source = await Presentation.load(here(${printString(templatePath)}))`\n\t\t)\n\t}\n\n\tif (needsFallbackLayout) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t'// Some source slides resolved no layout of their own; they bind to the first one.',\n\t\t\t'const fallbackLayout = deck.layouts()[0]',\n\t\t\t\"if (!fallbackLayout) throw new Error('the template declares no slide layouts to bind to')\"\n\t\t)\n\t}\n\n\tconst assetLines = printAssetBindings(ir, assetNames, assetDir, assetMode)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tlines.push(\n\t\t'',\n\t\t'/**',\n\t\t' * A generator sized to the template. appendSlides compares slide sizes exactly and',\n\t\t' * throws when they differ, so the inches here must round-trip to the source EMU.',\n\t\t' */',\n\t\t'function generator(): TsPptx {',\n\t\t'\\tconst pptx = new TsPptx()',\n\t\t`\\tpptx.defineLayout({ name: 'source', width: ${inches(ir.slideSize.widthEmu)}, height: ${inches(ir.slideSize.heightEmu)} })`,\n\t\t\"\\tpptx.layout = 'source'\",\n\t\t'\\treturn pptx',\n\t\t'}',\n\t\t...body,\n\t\t'',\n\t\t`await writeFile(here(${printString(outputPath)}), await deck.save())`,\n\t\t''\n\t)\n\n\treturn printedScript(lines, ir, assetMode, notes)\n}\n\n/**\n * The slide statements, batched into generators, preceded by the layout handles they bind to.\n *\n * A batch ends when the layout changes or a carried slide interrupts, because\n * `appendSlides` binds one layout per call and a carried slide is not authored at all.\n *\n * Every layout `const` is hoisted above the first statement rather than emitted where it is\n * first used. `deck.layouts()` is a snapshot of the gallery, and `importSlide` — the call a\n * carried slide prints — grows that gallery with the source slide's own layout and master.\n * Resolving a handle after one has run is therefore resolving against a deck that has already\n * moved; capturing every handle up front is the only ordering that cannot.\n */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst declarations: string[] = []\n\tconst lines: string[] = []\n\tlet batch: SlideIr[] = []\n\tlet generatorIndex = 0\n\t// Two non-contiguous batches can share one layout, so its `const` must be emitted once.\n\tconst declaredLayouts = new Set<number>()\n\n\tconst flush = (): void => {\n\t\tif (batch.length === 0) return\n\t\tconst first = batch[0]\n\t\tif (!first) return\n\t\tconst name = `gen${++generatorIndex}`\n\t\tlines.push('', `const ${name} = generator()`)\n\t\tfor (const slide of batch) lines.push(...printAuthoredSlide(slide, name, collector, printAsset))\n\t\tlines.push('', printAppend(name, first, collector, declaredLayouts, declarations))\n\t\tbatch = []\n\t}\n\n\tfor (const slide of ir.slides) {\n\t\tif (slide.source === 'carried') {\n\t\t\tflush()\n\t\t\tlines.push(\n\t\t\t\t'',\n\t\t\t\t`// Slide ${slide.number} — copied from the source deck rather than rebuilt; see the fidelity notes.`,\n\t\t\t\t`deck.importSlide(source, ${slide.number - 1})`\n\t\t\t)\n\t\t\tcontinue\n\t\t}\n\t\t// A batch is one appendSlides call, which binds every slide in it to one layout.\n\t\tconst previous = batch[0]\n\t\tif (previous && previous.layout?.index !== slide.layout?.index) flush()\n\t\tbatch.push(slide)\n\t}\n\tflush()\n\n\treturn declarations.length > 0 ? ['', ...declarations, ...lines] : lines\n}\n\n/**\n * The `appendSlides` call closing a batch, binding by layout name where that is\n * unambiguous and by gallery position where it is not. Any handle it needs is appended to\n * `declarations`, which the caller hoists above every statement.\n *\n * Binding by name is preferred because it survives being re-pointed at a different\n * template and because it is legible. But `appendSlides` *throws* on an ambiguous name\n * rather than picking one, so the positional form resolves the case where the name does not\n * identify one layout: a multi-master deck that repeats layout names.\n *\n * A carried slide used to demote every binding in the script to a position too, because its\n * `importSlide` copied the source layout in under a second name-alike entry. `importSlide`\n * now binds to the chrome the template already holds (`read/api/ops/part-reuse.ts`), and\n * this deck's template *is* the source file, so the gallery no longer grows and the names\n * stay unambiguous.\n */\nfunction printAppend(\n\tgeneratorName: string,\n\tfirst: SlideIr,\n\tcollector: NoteCollector,\n\tdeclared: Set<number>,\n\tdeclarations: string[]\n): string {\n\tconst layout = first.layout\n\tif (!layout) return `await deck.appendSlides(${generatorName}, { layout: fallbackLayout })`\n\tif (layout.nameIsUnique) {\n\t\treturn `await deck.appendSlides(${generatorName}, { layout: ${printString(layout.name)} })`\n\t}\n\n\tscopeNotes(collector, first.number).note(\n\t\t'slide.layout',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t`more than one layout in the source deck is named ${JSON.stringify(layout.name)}, so this slide binds to gallery position ${layout.index} instead; re-pointing the script at a different template will not track the name`\n\t)\n\tconst identifier = `layout${layout.index}`\n\tif (!declared.has(layout.index)) {\n\t\tdeclared.add(layout.index)\n\t\tdeclarations.push(\n\t\t\t`const ${identifier} = deck.layouts()[${layout.index}] // ${JSON.stringify(layout.name)}`,\n\t\t\t`if (!${identifier}) throw new Error('the template has no layout at position ${layout.index}')`\n\t\t)\n\t}\n\treturn `await deck.appendSlides(${generatorName}, { layout: ${identifier} })`\n}\n\n/** One authored slide, plus the layout-binding note this tier is responsible for. */\nfunction printAuthoredSlide(\n\tslide: SlideIr,\n\tgeneratorName: string,\n\tcollector: NoteCollector,\n\tprintAsset: AssetPrinter\n): string[] {\n\tif (slide.layout === null) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.layout',\n\t\t\t'approximated',\n\t\t\t'unsupported',\n\t\t\t\"this slide resolves no layout of its own, so it binds to the template's first layout; that governs theme and clrMap resolution, which may differ from the source\"\n\t\t)\n\t}\n\n\t// A tier loss, and a narrow one: a transition's *stop-previous* form needs no relationship\n\t// and rides across fine, while an embedded start sound needs an audio part wired to the\n\t// appended slide. `extractSlides` never runs the registration pass that assigns it a\n\t// relationship id (`registerTransitionSounds` belongs to the package-assembly path), so the\n\t// emitter finds no `_sndRId` and writes no `p:sndAc` at all. That is a silent drop rather\n\t// than a dangling reference — which is the safe failure of the two, and still a loss the\n\t// reader has to be told about. The standalone tier writes a real package and keeps it.\n\tif (slide.transition?.sound?.data !== undefined) {\n\t\tscopeNotes(collector, slide.number).note(\n\t\t\t'slide.transitionSound',\n\t\t\t'dropped',\n\t\t\t'unsupported',\n\t\t\t\"this transition's start sound is dropped: the append path this tier rides does not register a transition's embedded audio part, so the sound does not reach the template. The assignment below still spells it out, and the WAV still ships beside the script, because both describe the source deck faithfully and would take effect the day the append path carries them — but this output is silent. Print the standalone variant to keep the sound\"\n\t\t)\n\t}\n\n\tconst layout = slide.layout === null ? 'no layout' : `layout ${JSON.stringify(slide.layout.name)}`\n\treturn printSlide(\n\t\tslide,\n\t\t{ comment: `Slide ${slide.number} — ${layout}`, construction: `${generatorName}.addSlide()` },\n\t\tcollector,\n\t\tprintAsset\n\t)\n}\n","/**\n * {@link DeckIr} → a runnable TypeScript module that depends on nothing but this package.\n * **Tier A.**\n *\n * **The trade, stated once.** The template-anchored printer (`printScript`) reuses the source\n * `.pptx` and gets the deck's entire design back byte for byte, at the cost of shipping that\n * file alongside the script and of leaving the design uneditable. This one ships a single\n * `.ts` file. Everything the source deck's chrome contained has to be *re-authored* from what\n * the read model exposes, and the read model deliberately exposes the property tiers a slide\n * inherits — colours, fonts, placeholder geometry — not the parts a slide merely sits on top\n * of. So the output is a deck that renders its slides faithfully and wears a different suit.\n *\n * **The ceiling is measured, not estimated, and no amount of printer work moves it.** Two\n * constructs are unreachable from *both* directions: `a:fmtScheme` (nothing reads it, and the\n * write path emits a hardcoded Office one) and `p:txStyles` (no reader, though\n * `SlideMasterProps.textStyles` could author it). A third, `p:clrMap`, is readable and has no\n * setter. Each is a fidelity note here and a `pass` in the other tier, which is the whole\n * reason the other tier shipped first. A **master's** own decoration joins them for a\n * structural reason rather than a reading one: `defineSlideMaster` creates a layout, so there\n * is no master shape tree to write to. A *layout's* decoration used to be on this list and is\n * not any more — it is transcribed into that layout's `objects`.\n *\n * **One structural difference beyond the chrome.** A slide marked `carried` has no source\n * package to be carried from here, so it is transcribed like any other and loses only the\n * construct that made it uncarryable — which each shape has already declared for itself. That\n * is why {@link DeckIr}'s calls are populated even for a carried slide.\n */\nimport type { DeckIr, IrValue, MasterIr } from '../ir.js'\nimport { NoteCollector, scopeNotes } from '../fidelity.js'\nimport { inches } from '../from-read/values.js'\nimport { printArguments, printString, printValue, type AssetPrinter } from './literal.js'\nimport {\n\tassetIdentifiers,\n\tassetPrinter,\n\theader,\n\tprintAssetBindings,\n\tprintSlide,\n\tprintedScript,\n\tresolvePrintOptions,\n\ttype AssetMode,\n\ttype PrintedScript,\n} from './common.js'\n\nexport interface PrintStandaloneScriptOptions {\n\t/** Path the emitted script writes to, resolved against the script's own location. @default './output.pptx' */\n\toutputPath?: string\n\t/** Directory the emitted script reads image assets from, when {@link assets} is `'file'`. @default './assets' */\n\tassetDir?: string\n\t/** @default 'file' */\n\tassets?: AssetMode\n\t/**\n\t * Import specifier the emitted script uses. Defaults to this package's own published\n\t * name; override it to point a generated script at a local build or a fork.\n\t * @default '@shbernal/ts-pptx'\n\t */\n\tpackageName?: string\n}\n\n/**\n * Notes the IR declares that do not describe *this* output.\n *\n * Only one, and it is the mirror of the other tier's list. `slide.carried` says a slide will\n * be copied from the source package rather than transcribed; there is no source package here,\n * so the slide is transcribed and the construct that made it uncarryable has already recorded\n * its own note. Reporting both would double-count one loss and describe a behaviour this\n * script does not have.\n */\nconst NOT_APPLICABLE = new Set(['slide.carried'])\n\n/** Turn a deck IR into a runnable TypeScript module that needs no template. */\nexport function printStandaloneScript(ir: DeckIr, options: PrintStandaloneScriptOptions = {}): PrintedScript {\n\tconst { outputPath, assetDir, assetMode, packageName } = resolvePrintOptions(options)\n\n\tconst collector = new NoteCollector()\n\tconst assetNames = assetIdentifiers(ir)\n\tconst printAsset = assetPrinter(assetNames)\n\n\t// Walked before the header is built: this tier's own notes are only known afterwards.\n\tconst masters = printMasters(ir, collector, printAsset)\n\tconst body = printSlides(ir, collector, printAsset)\n\tconst notes = [...ir.fidelity.filter((note) => !NOT_APPLICABLE.has(note.construct)), ...collector.notes]\n\n\tconst needsReadFile = assetMode === 'file' && ir.assets.length > 0\n\tconst lines: string[] = [\n\t\theader(\n\t\t\t[\n\t\t\t\t'Generated from a .pptx by ts-pptx/script.',\n\t\t\t\t'',\n\t\t\t\t`Standalone: this script needs nothing but ${packageName}${\n\t\t\t\t\tneedsReadFile ? ` and ${ir.assets.length} media file(s) in ${assetDir}` : ''\n\t\t\t\t}.`,\n\t\t\t\t\"The deck's theme, layouts and slide content are all re-authored through the public write\",\n\t\t\t\t'API, so every one of them is editable here — and the parts of the original design the read',\n\t\t\t\t'model cannot see are gone. They are listed below. For a byte-identical design at the cost',\n\t\t\t\t'of shipping the source deck alongside the script, print the template-anchored variant',\n\t\t\t\t'instead.',\n\t\t\t\t'',\n\t\t\t\t`Writes ${outputPath}. Needs an ESM context — it uses top-level await.`,\n\t\t\t],\n\t\t\tnotes\n\t\t),\n\t\t'',\n\t\t...(needsReadFile ? [\"import { readFile } from 'node:fs/promises'\"] : []),\n\t\t\"import { fileURLToPath } from 'node:url'\",\n\t\t`import TsPptx from ${printString(packageName)}`,\n\t\t'',\n\t\t'/** Resolve a path against this script rather than against the working directory. */',\n\t\t'const here = (name: string): string => fileURLToPath(new URL(name, import.meta.url))',\n\t\t'',\n\t\t'const pptx = new TsPptx()',\n\t\t`pptx.defineLayout({ name: 'source', width: ${inches(ir.slideSize.widthEmu)}, height: ${inches(ir.slideSize.heightEmu)} })`,\n\t\t\"pptx.layout = 'source'\",\n\t]\n\n\tconst theme = ir.chrome.theme as IrValue\n\tif (Object.keys(ir.chrome.theme).length > 0) {\n\t\tlines.push(\n\t\t\t'',\n\t\t\t\"// The theme's colour scheme and font faces. Its format scheme — the fill, line and effect\",\n\t\t\t'// style lists a shape references through p:style — has no counterpart on either side of the',\n\t\t\t\"// library, so the output carries Office's.\",\n\t\t\t`pptx.theme = ${printValue(theme, 0, printAsset)}`\n\t\t)\n\t}\n\n\tconst props = printDocProps(ir, collector)\n\tif (props.length > 0) lines.push('', ...props)\n\n\tconst assetLines = printAssetBindings(\n\t\tir,\n\t\tassetNames,\n\t\tassetDir,\n\t\tassetMode,\n\t\t'// Media bytes, inlined so this script is a single self-contained file.'\n\t)\n\tif (assetLines.length > 0) lines.push('', ...assetLines)\n\n\tif (masters.length > 0) lines.push('', ...masters)\n\tlines.push(...body, '', `await pptx.writeFile({ fileName: here(${printString(outputPath)}) })`, '')\n\n\treturn printedScript(lines, ir, assetMode, notes)\n}\n\n/**\n * The document properties the write API can set.\n *\n * Four of the twelve the read model exposes, which is the loss `deck.docProps` already\n * declares — and unlike the template-anchored tier, here it is a real one, because nothing\n * else carries them.\n */\nfunction printDocProps(ir: DeckIr, collector: NoteCollector): string[] {\n\tconst entries = Object.entries(ir.props).filter(([, value]) => typeof value === 'string')\n\n\t// A deck built through the write API is stamped with the library's own author, company,\n\t// subject, title and revision in the constructor, and a property cannot be unset — writing\n\t// `''` emits an empty element rather than removing it. So whatever the source left blank\n\t// comes back filled in, which is a change to the deck rather than a formatting detail.\n\tconst stamped = ['title', 'author', 'company', 'subject', 'revision'].filter((key) => !(key in ir.props))\n\tif (stamped.length > 0) {\n\t\tscopeNotes(collector, null).note(\n\t\t\t'deck.docPropsDefault',\n\t\t\t'approximated',\n\t\t\t'unwritable',\n\t\t\t`the source deck declares no ${stamped.join(', ')}, and a deck built through the write API is stamped with the library's own value for each in its constructor with no way to unset it, so the output declares ${stamped.length === 1 ? 'one' : 'these'} the source did not`\n\t\t)\n\t}\n\n\tif (entries.length === 0) return []\n\treturn [\n\t\t'// Document properties. Only these have write-API setters; see the fidelity notes.',\n\t\t...entries.map(([key, value]) => `pptx.${key} = ${printString(value as string)}`),\n\t]\n}\n\n/**\n * One `defineSlideMaster` per source layout.\n *\n * The naming is the write API's rather than OOXML's: a `defineSlideMaster` call creates a\n * *layout* under the single shared master, which is the right granularity for a source layout.\n * It carries the layout's name, its background, and its decoration — the bands, rules and\n * wordmarks that make the gallery recognisable rather than a list of blank rectangles. What it\n * still cannot carry is the layout's *placeholder definitions*, and that is a write-path\n * consequence rather than a reading one (see `from-read/chrome.ts`). The name earns its place\n * twice over: it is also what `addSlide({ masterTitle })` binds on.\n */\nfunction printMasters(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\t// Recorded before the early return, because the extra layout is there either way: it is\n\t// seeded in the constructor, not by anything printed below. Scoped to that layout's own\n\t// title rather than deck-wide, because the round trip matches a note's `shapeName` against\n\t// the identity of what differed, and an unscoped note would declare *any* extra layout.\n\tscopeNotes(collector, null, 'DEFAULT').note(\n\t\t'master.default',\n\t\t'approximated',\n\t\t'unsupported',\n\t\t\"the write path seeds every presentation with a blank layout of its own named DEFAULT, and there is no way to remove it, so the output deck's layout gallery carries one extra entry ahead of the source's layouts; nothing binds to it, but it is visible in PowerPoint's layout picker\"\n\t)\n\tif (ir.chrome.masters.length === 0) return []\n\treturn [\n\t\t'// One master per source layout, carrying its name, background and decoration. What a',\n\t\t'// layout does not bring across is its placeholder definitions; see the fidelity notes.',\n\t\t...ir.chrome.masters.map((master) => printArguments('pptx.defineSlideMaster', [master.props], 0, printAsset)),\n\t]\n}\n\n/** Every slide, in source order, each bound to the master its source layout became. */\nfunction printSlides(ir: DeckIr, collector: NoteCollector, printAsset: AssetPrinter): string[] {\n\tconst byLayout = new Map<number, MasterIr>()\n\tfor (const master of ir.chrome.masters) byLayout.set(master.layoutIndex, master)\n\n\tconst lines: string[] = []\n\tfor (const slide of ir.slides) {\n\t\tconst master = slide.layout === null ? undefined : byLayout.get(slide.layout.index)\n\t\tconst title = typeof master?.props['title'] === 'string' ? master.props['title'] : null\n\n\t\tif (title === null) {\n\t\t\tscopeNotes(collector, slide.number).note(\n\t\t\t\t'slide.layout',\n\t\t\t\t'approximated',\n\t\t\t\t'unsupported',\n\t\t\t\tslide.layout === null\n\t\t\t\t\t? \"this slide resolves no layout of its own, so it binds to the write path's default blank layout\"\n\t\t\t\t\t: `this slide's source layout (gallery position ${slide.layout.index}) produced no master to bind to, so it binds to the write path's default blank layout`\n\t\t\t)\n\t\t}\n\n\t\tlines.push(\n\t\t\t...printSlide(\n\t\t\t\tslide,\n\t\t\t\t{\n\t\t\t\t\tcomment: `Slide ${slide.number} — ${title === null ? 'no master' : `master ${JSON.stringify(title)}`}`,\n\t\t\t\t\tconstruction: title === null ? 'pptx.addSlide()' : `pptx.addSlide({ masterTitle: ${printString(title)} })`,\n\t\t\t\t},\n\t\t\t\tcollector,\n\t\t\t\tprintAsset\n\t\t\t)\n\t\t)\n\t}\n\treturn lines\n}\n","/**\n * A {@link DeckIr} reduced to the form a round-trip diff can compare.\n *\n * The round trip is `source → IR₁ → script → deck → IR₂`. Comparing those two IRs raw\n * produces thousands of differences, almost none of which are losses: the write path\n * spells out defaults that OOXML leaves implicit, and PowerPoint spells out defaults the\n * write path leaves implicit. Both directions are noise, and drowning the real losses in\n * it is the same as not checking at all.\n *\n * **Every rule here must be an equivalence, not a convenience.** A rule that merely makes\n * the report shorter hides a defect permanently and silently — the exact failure mode this\n * subsystem exists to catch. So each one below cites the OOXML default that makes the\n * explicit and the absent spelling mean the same thing, and none of them drops a value that\n * a viewer could render differently. When in doubt the value stays in and the difference is\n * reported: a noisy report is recoverable, a quiet one is not.\n *\n * Canonicalising is deliberately *symmetric* — it runs over both IRs, so it cannot favour\n * the output. A rule that only made sense in one direction would be an exclusion dressed up\n * as a normalisation.\n */\nimport { asIrValue, isAssetRef, type AssetIr, type DeckIr, type IrValue, type SlideIr } from '../ir.js'\n\n/** One write-API call, with the source shape name lifted out as an address rather than data. */\nexport interface CanonicalCall {\n\tmethod: string\n\t/** `p:cNvPr/@name` of the shape this call came from, used to point a difference at it. */\n\tshapeName: string | null\n\t/**\n\t * Every `objectName` appearing anywhere inside {@link args}, which for `addGroup` is the\n\t * group's children.\n\t *\n\t * A fidelity note about a group's child is scoped to that child's name, but the child is\n\t * not a call of its own — it is an argument to the group's. Without this the note and the\n\t * difference it predicted would carry different names and never match, and a declared loss\n\t * would be reported as a defect.\n\t */\n\tcontainedNames: string[]\n\targs: IrValue[]\n}\n\nexport interface CanonicalSlide {\n\tnumber: number\n\thidden: boolean\n\t/**\n\t * The name of the layout this slide binds to, which is the only part of the binding that\n\t * is portable — a gallery *index* shifts whenever the output's gallery differs from the\n\t * source's, which it always does for a standalone output.\n\t *\n\t * Here because the binding is otherwise invisible: a printer that bound every slide to the\n\t * wrong layout, or to none, would produce identical calls and compare clean. The layout\n\t * governs theme and colour-map resolution, so that is not a cosmetic difference.\n\t */\n\tlayoutName: string | null\n\tbackground: IrValue | null\n\tnotesText: string | null\n\t/**\n\t * The show transition, or `null`.\n\t *\n\t * Here for the same reason {@link layoutName} is: a printer that stopped emitting\n\t * transitions altogether would produce identical *calls* and compare clean, so the\n\t * projection has to carry the slide-level properties the write API sets by assignment\n\t * rather than by method. It is compared structurally (key by key), not as one opaque\n\t * value, so a note can declare the loss of a transition's *sound* without also excusing a\n\t * wrong transition *type*.\n\t */\n\ttransition: IrValue | null\n\tcalls: CanonicalCall[]\n}\n\n/**\n * The deck's chrome, reduced the same way its slides are.\n *\n * Included for one reason: without it the diff cannot see the standalone tier's whole job.\n * That tier re-authors the theme and one master per source layout, and a projection that\n * covers only slides would report a printer emitting *neither* as a clean round trip — the\n * same shape of hole mutation testing found in `added` differences, one level up. A\n * template-anchored output compares equal here by construction, which is the claim that tier\n * makes and is worth checking rather than assuming.\n */\nexport interface CanonicalChrome {\n\ttheme: IrValue\n\t/** Each master's `defineSlideMaster` props, in gallery order. */\n\tmasters: IrValue[]\n}\n\nexport interface CanonicalDeck {\n\tslideSize: { widthEmu: number; heightEmu: number }\n\t/** The `docProps` the write API can set. Absent from the projection, a printer that set none would compare clean. */\n\tprops: IrValue\n\tchrome: CanonicalChrome\n\tslides: CanonicalSlide[]\n}\n\n/**\n * Option values that mean exactly what their absence means.\n *\n * Keyed by option name because the IR's argument objects are the write API's own option\n * objects, where a name identifies a construct uniquely — there is no `bold` that means\n * something other than `a:rPr/@b`.\n *\n * Each entry is an OOXML default:\n *\n * - `bold`, `italic` — `a:rPr/@b` / `@i` are `ST_OnOff`, default `false`.\n * - `baseline` — `a:rPr/@baseline` is a percentage, default `0` (no super/subscript).\n * - `breakLine` — not OOXML but the IR's own flat encoding: a run that does not end its\n * paragraph. The final run of a text frame never carries one, so absent and `false` are\n * the same statement.\n * - `wrap` — `a:bodyPr/@wrap` defaults to `square`, which the write API spells `true`.\n * - `rotate` — `a:xfrm/@rot` defaults to `0`.\n * - `flipH`, `flipV` — `a:xfrm/@flipH` / `@flipV` default to `false`.\n * - `transparency` — an alpha of 0% removed, i.e. fully opaque, which is also the default\n * when no `a:alpha` transform is present.\n * - `indentLevel` — `a:p/@lvl` defaults to `0`.\n * - `dashType` — `a:ln`'s dash defaults to `solid` when no `a:prstDash` is present.\n * - `textDirection` — `a:bodyPr/@vert` and `a:tcPr/@vert` both default to `horz`.\n *\n * Line width is deliberately **absent**: `a:ln/@w` defaults to 0 (hairline) while the write\n * path defaults it to 1pt, so those two are not the same line and the difference is real.\n */\nconst IMPLIED_DEFAULTS: Record<string, IrValue> = {\n\tbold: false,\n\titalic: false,\n\tbaseline: 0,\n\tbreakLine: false,\n\twrap: true,\n\trotate: 0,\n\tflipH: false,\n\tflipV: false,\n\ttransparency: 0,\n\tindentLevel: 0,\n\tdashType: 'solid',\n\ttextDirection: 'horz',\n}\n\n/**\n * `a:bodyPr`'s default insets in inches, in the write API's `[top, right, bottom, left]`\n * order: 45720 EMU (0.05in, 3.6pt) top and bottom, 91440 EMU (0.1in, 7.2pt) left and right.\n * A body that spells them out is inset exactly as one that omits them.\n */\nconst DEFAULT_MARGIN: readonly number[] = [0.05, 0.1, 0.05, 0.1]\n\n/** Reduce a deck IR to the comparable form. */\nexport function canonicalDeckIr(ir: DeckIr): CanonicalDeck {\n\tconst digests = assetDigests(ir.assets)\n\treturn {\n\t\tslideSize: ir.slideSize,\n\t\tprops: canonicalValue(ir.props as IrValue, digests),\n\t\tchrome: {\n\t\t\ttheme: canonicalValue(ir.chrome.theme as IrValue, digests),\n\t\t\tmasters: ir.chrome.masters.map((master) => canonicalValue(master.props, digests)),\n\t\t},\n\t\tslides: ir.slides.map((slide) => canonicalSlide(slide, digests)),\n\t}\n}\n\nfunction canonicalSlide(slide: SlideIr, digests: Map<string, string>): CanonicalSlide {\n\treturn {\n\t\tnumber: slide.number,\n\t\thidden: slide.hidden,\n\t\tlayoutName: slide.layout?.name ?? null,\n\t\tbackground: slide.background === undefined ? null : canonicalValue(slide.background as IrValue, digests),\n\t\tnotesText: slide.notesText ?? null,\n\t\ttransition: slide.transition === undefined ? null : canonicalValue(asIrValue(slide.transition), digests),\n\t\tcalls: slide.calls.map((call) => {\n\t\t\tconst args = call.args.map((arg) => canonicalValue(arg, digests))\n\t\t\treturn {\n\t\t\t\tmethod: call.method,\n\t\t\t\tshapeName: call.sourceName ?? null,\n\t\t\t\tcontainedNames: [...collectObjectNames(args, new Set())],\n\t\t\t\targs,\n\t\t\t}\n\t\t}),\n\t}\n}\n\n/**\n * Every `objectName` value reachable in `value`, at any depth.\n *\n * Exported for the chrome half of the diff, which needs the same list for the same reason: a\n * layout's decoration is an argument to one `defineSlideMaster` call, so a note scoped to one\n * of those shapes has no call of its own to be matched against.\n */\nexport function collectObjectNames(value: IrValue, out: Set<string>): Set<string> {\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) collectObjectNames(item, out)\n\t\treturn out\n\t}\n\tif (value === null || typeof value !== 'object') return out\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key === 'objectName' && typeof item === 'string') out.add(item)\n\t\telse collectObjectNames(item as IrValue, out)\n\t}\n\treturn out\n}\n\n/**\n * Recursively drop implied defaults and resolve asset references to a content digest.\n *\n * The digest matters more than it looks: assets are named `image1.png`, `image2.png`, … in\n * the order the walk meets them, and the output deck can meet the same bytes in a different\n * order or under a different extension. Comparing names would report a swap that did not\n * happen and, worse, would *miss* one where two images traded places.\n */\nfunction canonicalValue(value: IrValue, digests: Map<string, string>): IrValue {\n\tif (isAssetRef(value)) return { $asset: digests.get(value.$asset) ?? `unknown:${value.$asset}` }\n\tif (Array.isArray(value)) return value.map((item) => canonicalValue(item, digests))\n\tif (value === null || typeof value !== 'object') return value\n\n\t// A run with no characters has no colour anyone can see, and the write path gives every\n\t// run it emits an explicit one. Narrowed to `color` deliberately: a size or a bullet on an\n\t// empty paragraph still affects line height and still draws a glyph, so those stay.\n\tconst blankRun = value['text'] === '' && typeof value['options'] === 'object' && value['options'] !== null\n\n\tconst out: Record<string, IrValue> = {}\n\tfor (const [key, item] of Object.entries(value)) {\n\t\tif (key in IMPLIED_DEFAULTS && item === IMPLIED_DEFAULTS[key]) continue\n\t\tif (key === 'margin' && isDefaultMargin(item)) continue\n\t\tif (blankRun && key === 'options') {\n\t\t\tconst visible = { ...(item as Record<string, IrValue>) }\n\t\t\tdelete visible['color']\n\t\t\tout[key] = canonicalValue(visible, digests)\n\t\t\tcontinue\n\t\t}\n\t\tout[key] = canonicalValue(item, digests)\n\t}\n\treturn out\n}\n\nfunction isDefaultMargin(value: IrValue): boolean {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length === DEFAULT_MARGIN.length &&\n\t\tvalue.every((item, index) => item === DEFAULT_MARGIN[index])\n\t)\n}\n\n/**\n * Content digests keyed by asset name, so the same bytes compare equal under any name.\n *\n * FNV-1a rather than a real hash: this identifies bytes for a comparison both sides of\n * which are in hand, so collision resistance against an adversary is not a property it\n * needs, and the library stays free of `node:crypto` and of the isomorphism problem\n * importing it would create.\n */\nfunction assetDigests(assets: AssetIr[]): Map<string, string> {\n\tconst out = new Map<string, string>()\n\tfor (const asset of assets) {\n\t\tlet hash = 0x811c9dc5\n\t\tfor (const byte of asset.bytes) {\n\t\t\thash ^= byte\n\t\t\thash = Math.imul(hash, 0x01000193) >>> 0\n\t\t}\n\t\tout.set(asset.name, `${asset.bytes.length}:${hash.toString(16)}`)\n\t}\n\treturn out\n}\n","/**\n * The round-trip oracle: does the deck a printed script builds match the deck it was read\n * from, everywhere the fidelity notes did not say it would not?\n *\n * **Why a projection diff and not byte identity.** The output package is not the input\n * package and never will be — different rel ids, different shape ids, a regenerated shape\n * tree, `dirty=\"0\"` on every run. Comparing bytes would report a total mismatch for every\n * deck and prove nothing. So the comparison happens one level up, on the IR: run the same\n * `readModelToIr` over the source deck and over the deck the script produced, and compare\n * those. Two decks that produce the same IR make the same write-API calls, which is exactly\n * the claim a generated script makes.\n *\n * **What a note is worth here.** A {@link FidelityNote} says a named construct will not\n * survive. That makes it an *exclusion with a signature*: the difference it predicts is\n * allowed, and every other difference is a defect. Without the notes there would be no way\n * to tell a known cost from a regression, and the check could only ever be a snapshot.\n *\n * **Two blind spots, both stated plainly, because a clean report is worth exactly what its\n * limits allow.**\n *\n * 1. *The reader is shared.* Both IRs come from `readModelToIr`, so a construct the read\n * model cannot see is missing from both and compares equal. This check cannot certify\n * anything the read path does not read; `pnpm run read:census` measures that surface, and\n * the two are complementary rather than overlapping.\n * 2. *The converter need not be injective.* Two different source constructs can map to the\n * same call, and then the round trip agrees while the deck has changed. Measured, not\n * hypothetical: the mapper once read an explicit `a:buNone` as the glyph `n`, so a\n * bulletless paragraph gained a bullet — and because the output's real `n` bullet read\n * back through the same wrong mapping, the diff was clean. Mutation testing is what\n * catches that class, and a mutation that survives here is a statement about this\n * check's reach rather than a mistake in it.\n *\n * A clean report means \"nothing the converter can distinguish was lost\", never \"nothing was\n * lost\".\n */\nimport { LAYOUT_NOTE_PREFIX, type FidelityNote } from '../fidelity.js'\nimport {\n\tcollectObjectNames,\n\ttype CanonicalCall,\n\ttype CanonicalChrome,\n\ttype CanonicalDeck,\n\ttype CanonicalSlide,\n} from './canonical.js'\nimport type { IrValue } from '../ir.js'\n\n/**\n * Which way a difference points.\n *\n * `lost` and `changed` are the ones the fidelity contract governs — the source said\n * something the output does not, or says differently. `added` is the write path being\n * explicit where the source was implicit, which is *usually* harmless and is reported\n * separately for a reason worth stating: this diff cannot tell whether the value the write\n * path chose is the one the source was inheriting. An `added` `color` is benign if the\n * shape was inheriting that colour and a silent repaint if it was not.\n */\nexport type DifferenceKind = 'lost' | 'added' | 'changed'\n\n/**\n * Options the write path materialises that the source deck left implicit, with the reason\n * each is not judgeable from here.\n *\n * This list exists because `added` differences cannot simply be waved through. Mutation\n * testing settled that: dropping the converter's explicit `valign` left the write path to\n * centre every text body, which showed up as an `added` and nothing failed. So `added` is\n * held to the same standard as the rest — a note must declare it, or its field must appear\n * here with a reason.\n *\n * Every entry names a write-path default whose *correctness* the round trip has no way to\n * assess, because the source's counterpart was inherited and the read model cannot resolve\n * what it was inheriting. That is an honest \"unknown\", not an \"ignore\" — each one names a\n * gap in the reader that could be closed later, and teaching the reader to resolve one turns\n * its entry here into a real comparison.\n */\nconst WRITER_DEFAULTS: Record<string, string> = {\n\t// The write path copies the object-level and first-run character properties onto every\n\t// run it emits. The source's bare runs inherited theirs from the list style, which is\n\t// unread, so there is nothing to compare the copied value against.\n\tfontSize: 'runs inherit size from an unread list style; the write path copies the shape size onto each run',\n\toptions: 'a run or cell that carried no options at all in the source now carries the ones below',\n\t// `a:tcBdr` borders come from the table style graph, which `resolvedFill`/`borders` fold\n\t// together rather than separating; the write path spells out an explicit border per edge.\n\tborder:\n\t\t'table cell borders are resolved through the style graph, which the read model cannot separate from the cell’s own',\n\t// `a:ln/@w` defaults to a hairline in OOXML and to 1pt here, and a source outline with no\n\t// explicit width is exactly the theme-`lnRef` case `line.width` already declares unread.\n\twidth:\n\t\t'an outline with no explicit width takes the write path’s 1pt default; the source’s came from the unread theme line style',\n\t// A shape with no geometry of its own — an unfilled placeholder — has no preset to name.\n\tshape: 'a shape that inherits its geometry from a layout is emitted as a plain rectangle',\n\ttype: 'a fill or line with no explicit kind takes the write path’s solid default',\n\t// Chart options the write path always emits; the read side reports only what the chart\n\t// part contains, and these are defaults rather than authored values.\n\tchartColors: 'the write path assigns a series palette; the source’s came from the theme',\n\tdataLabelFormatCode: 'a data label with no explicit number format takes the write path’s default',\n\tshowLeaderLines: 'leader lines are on by default in the write path',\n\t// The five docProps the write path seeds in its constructor ('ts-pptx',\n\t// 'ts-pptx Presentation', '1'). A source deck that declared none of a given property gets\n\t// the library's, and there is no way to unset one — assigning `''` writes an empty element\n\t// rather than removing it. Unlike the entries above, this is a *write*-side candidate, not\n\t// a read-side one: the fix is a way to author a deck with a property genuinely absent.\n\t// Restricted to `added` by construction, so a printer that stopped writing docProps still\n\t// fails: the source's own values become `changed`, which nothing here excuses.\n\ttitle: 'a deck that declares no title gets the write path’s own',\n\tauthor: 'a deck that declares no author gets the write path’s own',\n\tsubject: 'a deck that declares no subject gets the write path’s own',\n\tcompany: 'a deck that declares no company gets the write path’s own',\n\trevision: 'a deck that declares no revision gets the write path’s own',\n}\n\nexport interface IrDifference {\n\t/** 1-based source slide. */\n\tslideNumber: number\n\t/** Source shape name, when the difference sits inside a call that has one. */\n\tshapeName: string | null\n\t/**\n\t * Shape names nested inside the same call — a group's children. A note scoped to one of\n\t * these also declares differences reported against the call that carries it.\n\t */\n\tnestedNames: string[]\n\t/** Where in the slide's projection, e.g. `calls[4].args[1].line.width`. */\n\tpath: string\n\t/**\n\t * The option name the difference is about — the last object key on {@link path}, or\n\t * `'*'` when a whole call is present on one side only. This is what a note's `construct`\n\t * is matched against, which is why `construct` has to name a field path rather than\n\t * describe one.\n\t */\n\tfield: string\n\tkind: DifferenceKind\n\t/** The source value, JSON-encoded and truncated for reporting. `'—'` when absent. */\n\texpected: string\n\t/** The output value, likewise. */\n\tactual: string\n\t/** The note that declares this difference, when one does. */\n\tdeclaredBy: FidelityNote | null\n}\n\nexport interface RoundTripReport {\n\tslideCount: number\n\t/** Every difference found, in deck order. */\n\tdifferences: IrDifference[]\n\t/**\n\t * Differences neither a note nor a known write-path default accounts for.\n\t * **These are the defects**, and the number this check gates on.\n\t */\n\tundeclared: IrDifference[]\n\t/** Differences a note declared. The contract working. */\n\tdeclared: IrDifference[]\n\t/** `added` differences: the write path spelling out what the source left implicit. */\n\tadded: IrDifference[]\n\t/**\n\t * Notes that matched no difference.\n\t *\n\t * **Not a defect signal, despite the obvious reading.** Most notes name constructs the\n\t * read model cannot see at all — a bullet's `a:buFont`, a shape's theme `effectRef` —\n\t * so they are absent from *both* IRs and there is nothing for them to match. A note\n\t * here is a candidate for review, not a stale claim.\n\t */\n\tunmatchedNotes: FidelityNote[]\n}\n\n/**\n * Option names each note construct is a promise about.\n *\n * This table is the fidelity catalogue made mechanical. A note claims a construct will not\n * survive; without a mapping from that claim to the fields it covers, the claim cannot\n * exclude anything and the round trip degenerates into a snapshot.\n *\n * `'*'` covers every difference inside the call it is scoped to — correct only where the\n * note says the whole shape is gone or was copied wholesale, never as a shortcut for a\n * construct whose fields are merely tedious to enumerate.\n *\n * An empty list is meaningful and common: the construct is invisible to the IR on both\n * sides (a slide's build animations, a paragraph's `a:pPr/@marL`, a connector's shape\n * binding), so the note is a caveat for a human and there is nothing here to exclude. Saying\n * so explicitly is what keeps it from looking like an oversight. A construct can leave that\n * state — `slide.transition` was an empty entry until the converter learned to transcribe\n * transitions, and the IR gaining a field is exactly when its note gains a mapping.\n */\nconst NOTE_FIELDS: Record<string, readonly string[]> = {\n\t'chart.blanks': ['values'],\n\t'chart.combo': ['type'],\n\t'chart.type': ['type'],\n\t'chart.workbook': ['*'],\n\t'chartEx.all': ['*'],\n\t'connector.binding': [],\n\t'connector.line': ['color', 'width', 'dashType', 'beginArrowType', 'endArrowType'],\n\t'connector.rotation': ['rotate'],\n\t// Empty, and the temptation to list title/author/subject/revision here has to be\n\t// resisted: this note is about the *other* seven docProps, which have no setter and are\n\t// absent from the IR. Listing the four that do have setters would excuse a printer that\n\t// stopped writing them — measured, by exactly that mutation.\n\t'deck.docProps': [],\n\t// Nothing to exclude: the differences it predicts are `added`, which WRITER_DEFAULTS covers\n\t// by kind. The note exists so a reader of the emitted script learns the deck gained them.\n\t'deck.docPropsDefault': [],\n\t'deck.slideSize': ['widthEmu', 'heightEmu'],\n\t'diagram.all': ['*'],\n\t'fill.gradient.path': ['gradient', 'fill'],\n\t// Recorded only when an image-filled surface cannot carry its *bytes* — a linked blip, an\n\t// SVG the write path refuses, a part missing from the package. The fill option is then\n\t// absent from the output entirely, which is the same two keys `fill.schemeToken` covers.\n\t'fill.picture': ['fill', 'color'],\n\t// Empty, and deliberately so: this note declares that a picture fill's tiling, crop, DPI\n\t// and rotWithShape do not survive, and *none of them is in the IR on either side* — the\n\t// write API expresses a picture fill as bytes plus transparency, so the converter never\n\t// emits them. Widening this to `fill` would be the mistake it looks like a fix for: it\n\t// would excuse an image fill that failed to come back at all, which is the thing the\n\t// round trip is here to catch.\n\t'fill.picture.geometry': [],\n\t'fill.schemeToken': ['fill', 'color'],\n\t'graphicFrame.unknown': ['*'],\n\t'group.child': ['*'],\n\t'group.childSpace': ['x', 'y', 'w', 'h', 'rotate', 'flipH', 'flipV'],\n\t'group.empty': ['*'],\n\t'group.transform': ['rotate', 'flipH', 'flipV'],\n\t'image.data': ['data', '$asset'],\n\t'image.recolor': ['duotone', 'grayscale', 'biLevel', 'clrChange'],\n\t// Covers the picture's bytes, not just an `svg` option: an SVG picture's raster fallback\n\t// is regenerated rather than carried, so the blip the round trip compares is a different\n\t// image from the source's — which is precisely the loss this note is about.\n\t'image.svg': ['svg', 'data', '$asset'],\n\t'line.arrowSize': ['beginArrowType', 'endArrowType'],\n\t// The chrome notes. Most are empty for the reason stated above and it is the common case\n\t// here rather than the exception: `a:fmtScheme`, `p:txStyles`, a *master's* decoration and a\n\t// layout's placeholder definitions are all absent from the IR on *both* sides — the first two\n\t// because nothing reads them, the other two because nothing writes them — so there is nothing\n\t// for a note to exclude and the note exists for a human. A *layout's* decoration is the one\n\t// that left this state: it is now in the IR as `objects` and is genuinely compared, which is\n\t// what makes the `layout.` entries below worth stating separately.\n\t// `p:clrMap` is the subtle one: a remapped token changes what every scheme colour in the\n\t// deck resolves to, and the round trip still cannot see it, because the IR reports the token\n\t// verbatim rather than its resolved hex. That is exactly the blind spot this file's header\n\t// describes, and writing `[]` is the honest spelling of it.\n\t'master.background': ['background', 'color', 'data', 'master'],\n\t'master.colorMap': [],\n\t'master.decoration': [],\n\t'master.default': ['master'],\n\t'master.multiple': [],\n\t'master.name': ['title', 'layoutName'],\n\t'master.nameCollision': ['title', 'layoutName'],\n\t'master.placeholders': [],\n\t'master.txStyles': [],\n\t'theme.fmtScheme': [],\n\t// The two layout-shape notes with no slide counterpart to inherit a mapping from. Both are\n\t// empty for the same reason, and it is worth spelling out because both *look* like they\n\t// should exclude something. A table on a layout is absent from the `objects` array on both\n\t// sides — the source's because this converter skips it, the output's because it was never\n\t// written — so there is no difference to excuse. A flattened group is stronger still: the\n\t// source layout's group becomes N loose objects here and the output layout genuinely *has*\n\t// N loose objects, so the two agree exactly and the note is a caveat for a human reading the\n\t// emitted script, not an exclusion.\n\t'layout.decoration': [],\n\t'layout.group': [],\n\t'line.dash': ['dashType'],\n\t'line.width': ['width'],\n\t'media.audioVideo': ['*'],\n\t'notes.formatting': ['notesText'],\n\t'shape.custGeom.guides': ['points'],\n\t'shape.effects': ['shadow', 'glow'],\n\t'shape.empty': ['*'],\n\t'shape.frameInherited': ['x', 'y', 'w', 'h'],\n\t'shape.hidden': ['*'],\n\t'shape.placeholder': ['placeholder'],\n\t'slide.animation': [],\n\t'slide.background': ['background', 'color', 'transparency', 'image'],\n\t'slide.carried': ['*'],\n\t'slide.layout': ['layoutName'],\n\t'slide.name': [],\n\t// A transition the write vocabulary cannot name is dropped whole, so the difference lands\n\t// on the slide's `transition` key itself. Deliberately *not* widened to the keys inside it:\n\t// this note is only ever recorded when the whole transition is gone.\n\t'slide.transition': ['transition'],\n\t// The sound alone, one level down. Scoped to `sound` so it cannot also excuse a transition\n\t// whose type or timing came back wrong — the loss it declares is exactly the missing\n\t// `p:sndAc`, and `data`/`$asset` cover the case where the sound survives with other bytes.\n\t'slide.transitionSound': ['sound', 'data', '$asset'],\n\t// A dash outside `ST_PresetLineDashVal` cannot be written back, so the edge comes out as\n\t// a plain dashed rule. Scoped to `border`, which is where that difference lands.\n\t'table.cell.borders.dash': ['border', 'diagonal'],\n\t// `table.cell.fill` used to live here, for a cell whose own fill could not be told apart\n\t// from the one it inherited from the table style. `TableCell.hasOwnFill` tells them apart,\n\t// so the mapper emits the right one and records nothing — the note is gone rather than\n\t// unmapped. Its `.gradient` / `.picture` children below are separate constructs and stay.\n\t// Empty, and correctly so: `a:tc/@id` and `a:tcPr/a:headers` have no write option — the\n\t// IR has nowhere to put them on either side, so there is nothing to exclude. The note\n\t// exists so a reader of the emitted script learns the association was there and is gone.\n\t'table.cell.headers': [],\n\t// The cell-side twins of `fill.picture` / `fill.picture.geometry`, and mapped for the\n\t// same reasons.\n\t'table.cell.fill.picture': ['fill'],\n\t'table.cell.fill.picture.geometry': [],\n\t// The table-background twins. Scoped to `tableFill` rather than `fill`, because those are\n\t// two different options: one lands on `a:tblPr`, the other is stamped onto every cell.\n\t'table.fill.picture': ['tableFill'],\n\t'table.fill.picture.geometry': [],\n\t// A gradient that cannot be expressed falls back to no gradient, so the difference lands\n\t// on the fill option itself — `tableFill` for the background, `fill` for a cell.\n\t'table.fill.gradient': ['tableFill'],\n\t'table.fill.gradient.path': ['tableFill'],\n\t'table.cell.fill.gradient': ['fill'],\n\t'table.cell.fill.gradient.path': ['fill'],\n\t// Narrowed to the East-Asian `ST_TextVerticalType` modes `textDirection` cannot spell —\n\t// the four it can now round-trip, so this no longer excuses every vertical cell.\n\t'table.cell.vert': ['textDirection', 'vert'],\n\t'table.rowAuto': ['rowH'],\n\t'table.style': ['tableStyle'],\n\t'text.align': ['align'],\n\t// `text.bullet.numberStartAt` and `text.bullet.style` used to live here, for\n\t// `a:buAutoNum/@startAt` and for a bullet's own font/size/colour. `Paragraph.bulletDetail`\n\t// reads all four, so the mapper emits `numberStartAt` / `fontFace` / `size` / `color` and\n\t// records nothing — the notes are gone rather than unmapped. What remains of the size half\n\t// is `text.bullet.sizePt`, which is a genuinely unwritable unit rather than an unread value.\n\t'text.bullet.numberType': ['bullet'],\n\t// An absolute bullet size (`a:buSzPts`) has no write option at all — `bullet.size` is a\n\t// percentage of the run size — so the difference lands on the bullet option.\n\t'text.bullet.sizePt': ['bullet'],\n\t// A percentage outside 25–400%, which the write path rejects with a warning and replaces\n\t// with the run's own size.\n\t'text.bullet.sizePct': ['bullet'],\n\t// A bullet colour outside the ten scheme tokens the write path maps, baked to a literal.\n\t'text.bullet.schemeToken': ['bullet'],\n\t// A picture bullet (`a:buBlip`): readable, and `bullet.image` could author it, but the\n\t// paragraph mapper carries no asset resolver to re-embed the bytes with.\n\t'text.bullet.picture': ['bullet'],\n\t'text.color.default': ['color'],\n\t'text.color.inherited': ['color'],\n\t'text.color.schemeToken': ['color'],\n\t'text.equation': ['*'],\n\t'text.field': ['*'],\n\t'text.bullet.glyph': ['bullet'],\n\t// `text.bullet.inherited` used to live here — a paragraph stating no bullet of its own was\n\t// re-emitted with an explicit `a:buNone`, because omitting the write API's `bullet` is that\n\t// element rather than silence. `bullet: 'inherit'` says silence now, so the mapper carries\n\t// the state instead of excusing its loss and the note is gone rather than unmapped.\n\t//\n\t// `text.indent` used to live here, empty, because a paragraph's `a:pPr/@marL` and `@indent`\n\t// were in neither IR — the write API had no option for them, so the mapper never emitted one\n\t// and the diff compared two models both missing the field. `paraMarginLeft` / `paraIndent`\n\t// put it in both, which is what turns an empty entry into a comparison rather than a caveat,\n\t// so the note is gone rather than unmapped.\n\t'text.paraSpaceZero': ['paraSpaceBefore', 'paraSpaceAfter'],\n\t'text.vert': ['vert'],\n}\n\n/**\n * Every note construct this table knows how to match, for a test to check against. The\n * `layout.` spellings are not listed — they resolve through {@link isKnownNoteConstruct},\n * which is what a corpus check should use.\n */\nexport function knownNoteConstructs(): string[] {\n\treturn Object.keys(NOTE_FIELDS).sort()\n}\n\n/**\n * Compare the deck a script was generated from against the deck it produced.\n *\n * `notes` must be the set that actually applies to the printed output — `printScript`'s\n * returned `notes`, not `DeckIr.fidelity`. The two differ in both directions: the printer\n * suppresses notes its tier rescues and adds ones its tier causes, so diffing against the\n * IR's own list would both over- and under-exclude.\n */\nexport function diffDeckIr(expected: CanonicalDeck, actual: CanonicalDeck, notes: FidelityNote[]): RoundTripReport {\n\tconst differences: IrDifference[] = []\n\n\tif (expected.slideSize.widthEmu !== actual.slideSize.widthEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.widthEmu', 'widthEmu', expected.slideSize.widthEmu, actual.slideSize.widthEmu)) // prettier-ignore\n\t}\n\tif (expected.slideSize.heightEmu !== actual.slideSize.heightEmu) {\n\t\tdifferences.push(scalarDifference(0, null, [], 'slideSize.heightEmu', 'heightEmu', expected.slideSize.heightEmu, actual.slideSize.heightEmu)) // prettier-ignore\n\t}\n\n\tdiffValue(expected.props, actual.props, 'props', 'props', 0, null, [], differences)\n\tdiffChrome(expected.chrome, actual.chrome, differences)\n\n\tconst slideCount = Math.max(expected.slides.length, actual.slides.length)\n\tfor (let index = 0; index < slideCount; index++) {\n\t\tconst before = expected.slides[index]\n\t\tconst after = actual.slides[index]\n\t\tconst number = before?.number ?? after?.number ?? index + 1\n\t\tif (!before || !after) {\n\t\t\tdifferences.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: null,\n\t\t\t\tnestedNames: [],\n\t\t\t\tpath: `slides[${index}]`,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? 'slide' : '—',\n\t\t\t\tactual: after ? 'slide' : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tdiffSlide(before, after, differences)\n\t}\n\n\tfor (const difference of differences) difference.declaredBy = declaringNote(difference, notes)\n\tconst matched = new Set(differences.map((difference) => difference.declaredBy).filter(Boolean))\n\tconst accounted = (difference: IrDifference): boolean =>\n\t\tdifference.declaredBy !== null || (difference.kind === 'added' && difference.field in WRITER_DEFAULTS)\n\n\treturn {\n\t\tslideCount: expected.slides.length,\n\t\tdifferences,\n\t\tundeclared: differences.filter((difference) => !accounted(difference)),\n\t\tdeclared: differences.filter((difference) => difference.declaredBy !== null),\n\t\tadded: differences.filter((difference) => difference.kind === 'added'),\n\t\tunmatchedNotes: notes.filter((note) => !matched.has(note)),\n\t}\n}\n\n/**\n * The theme and the layout gallery.\n *\n * Reported at `slideNumber: 0`, the same deck-level bucket the slide size uses, so a\n * deck-scoped note (which carries `slideNumber: null` and matches any slide) can declare one.\n * Masters align by **title**, not by position, for the same reason calls align by shape name:\n * the write path always emits a blank layout of its own at gallery position 0, so positional\n * alignment reports every layout in the deck as renamed and buries the one real difference —\n * that extra layout — under a shift.\n *\n * And, exactly as with shape names, a title is only usable as a key where it is *unique on\n * both sides*. Uniqueness is supposed to be an invariant here — the converter deduplicates\n * titles because a title is also what `addSlide({ masterTitle })` binds on — but keying on it\n * unconditionally makes the check assume the thing it should be testing: a mutation that\n * removed the deduplication left two layouts sharing a title, both expected entries matched\n * the same actual one, and the round trip came back clean. Falling back to position when the\n * key repeats costs nothing when the invariant holds and catches it when it does not.\n */\nfunction diffChrome(expected: CanonicalChrome, actual: CanonicalChrome, out: IrDifference[]): void {\n\tdiffValue(expected.theme, actual.theme, 'chrome.theme', 'theme', 0, null, [], out)\n\n\t// A whole master appearing or disappearing is reported *scoped to its title*, using the\n\t// same `shapeName` channel a shape-scoped note uses. Without that, one note declaring the\n\t// blank layout the write path always adds would carry `field: 'master'` and excuse every\n\t// added layout — which is what a mutation that stopped deduplicating layout titles proved.\n\tconst report = (\n\t\tpath: string,\n\t\tkind: DifferenceKind,\n\t\tbefore: IrValue | undefined,\n\t\tafter: IrValue | undefined\n\t): void => {\n\t\tout.push({\n\t\t\tslideNumber: 0,\n\t\t\tshapeName: titleOf(before ?? after ?? null),\n\t\t\tnestedNames: decorationNames(before, after),\n\t\t\tpath,\n\t\t\tfield: 'master',\n\t\t\tkind,\n\t\t\texpected: brief(before),\n\t\t\tactual: brief(after),\n\t\t\tdeclaredBy: null,\n\t\t})\n\t}\n\n\tconst byTitle = uniqueByTitle(actual.masters)\n\tconst expectedTitles = uniqueByTitle(expected.masters)\n\tconst claimed = new Set<IrValue>()\n\tlet cursor = 0\n\tconst nextUnclaimed = (): IrValue | undefined => {\n\t\twhile (cursor < actual.masters.length) {\n\t\t\tconst candidate = actual.masters[cursor++]\n\t\t\tif (candidate !== undefined && !claimed.has(candidate)) return candidate\n\t\t}\n\t\treturn undefined\n\t}\n\n\texpected.masters.forEach((before, index) => {\n\t\tconst title = titleOf(before)\n\t\t// Usable only where the title identifies exactly one master on each side.\n\t\tconst named = title !== null && expectedTitles.has(title) ? byTitle.get(title) : undefined\n\t\tconst after = named !== undefined && !claimed.has(named) ? named : nextUnclaimed()\n\t\tif (after === undefined) {\n\t\t\treport(`chrome.masters[${index}]`, 'lost', before, undefined)\n\t\t\treturn\n\t\t}\n\t\tclaimed.add(after)\n\t\t// A layout's decoration rides inside this one value, so a note scoped to one of those\n\t\t// shapes has no call of its own to be matched against — the same problem a group's child\n\t\t// has on a slide, and the same answer.\n\t\tdiffValue(before, after, `chrome.masters[${index}]`, 'master', 0, null, decorationNames(before, after), out)\n\t})\n\n\tactual.masters.forEach((after, index) => {\n\t\tif (!claimed.has(after)) report(`chrome.masters[${index}]`, 'added', undefined, after)\n\t})\n}\n\n/** Masters keyed by title, keeping only titles that identify exactly one of them. */\nfunction uniqueByTitle(masters: IrValue[]): Map<string, IrValue> {\n\tconst counts = new Map<string, number>()\n\tfor (const master of masters) {\n\t\tconst title = titleOf(master)\n\t\tif (title !== null) counts.set(title, (counts.get(title) ?? 0) + 1)\n\t}\n\tconst out = new Map<string, IrValue>()\n\tfor (const master of masters) {\n\t\tconst title = titleOf(master)\n\t\tif (title !== null && counts.get(title) === 1) out.set(title, master)\n\t}\n\treturn out\n}\n\n/**\n * The `objectName`s of every decorative shape in a master's props, taking both sides so a\n * shape that dropped out is still named by the source's.\n */\nfunction decorationNames(before: IrValue | undefined, after: IrValue | undefined): string[] {\n\tconst names = new Set<string>()\n\tfor (const master of [before, after]) if (master !== undefined) collectObjectNames(master, names)\n\treturn [...names]\n}\n\n/** A canonical master's `title`, which is its identity across the round trip. */\nfunction titleOf(master: IrValue): string | null {\n\tif (master === null || typeof master !== 'object' || Array.isArray(master)) return null\n\tconst title = (master as Record<string, IrValue>)['title']\n\treturn typeof title === 'string' ? title : null\n}\n\nfunction diffSlide(expected: CanonicalSlide, actual: CanonicalSlide, out: IrDifference[]): void {\n\tconst number = expected.number\n\tconst at = (path: string, field: string, a: IrValue, b: IrValue): void => {\n\t\tif (JSON.stringify(a) !== JSON.stringify(b)) out.push(scalarDifference(number, null, [], path, field, a, b))\n\t}\n\tat('hidden', 'hidden', expected.hidden, actual.hidden)\n\tat('layoutName', 'layoutName', expected.layoutName, actual.layoutName)\n\tat('background', 'background', expected.background, actual.background)\n\tat('notesText', 'notesText', expected.notesText, actual.notesText)\n\t// Structural rather than whole-value, unlike the four above: a transition is a small object\n\t// whose parts are lost independently — the append path drops an embedded sound while\n\t// keeping the effect — and a whole-value compare would force the note that declares the\n\t// sound to carry `field: 'transition'`, which would then excuse a wrong type or duration too.\n\tdiffValue(expected.transition, actual.transition, 'transition', 'transition', number, null, [], out)\n\n\tfor (const [before, after] of alignCalls(expected.calls, actual.calls)) {\n\t\tconst name = before?.shapeName ?? after?.shapeName ?? null\n\t\t// Union of both sides: a child that dropped out is named only by the source's call.\n\t\tconst nested = [...new Set([...(before?.containedNames ?? []), ...(after?.containedNames ?? [])])]\n\t\tconst path = `calls[${before ? expected.calls.indexOf(before) : actual.calls.indexOf(after as CanonicalCall)}]`\n\t\tif (!before || !after) {\n\t\t\tout.push({\n\t\t\t\tslideNumber: number,\n\t\t\t\tshapeName: name,\n\t\t\t\tnestedNames: nested,\n\t\t\t\tpath,\n\t\t\t\tfield: '*',\n\t\t\t\tkind: before ? 'lost' : 'added',\n\t\t\t\texpected: before ? before.method : '—',\n\t\t\t\tactual: after ? after.method : '—',\n\t\t\t\tdeclaredBy: null,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tif (before.method !== after.method) {\n\t\t\tout.push(scalarDifference(number, name, nested, `${path}.method`, 'method', before.method, after.method))\n\t\t}\n\t\tdiffValue(before.args, after.args, `${path}.args`, 'args', number, name, nested, out)\n\t}\n}\n\n/**\n * Pair up the two slides' calls.\n *\n * Position alone is wrong the moment one shape drops out: every later call shifts by one\n * and the report fills with mismatches that are really one missing shape. Shape names\n * survive the round trip (the converter passes `objectName` through), so they are the\n * alignment key wherever they are present and unambiguous, with position as the fallback\n * for unnamed or duplicate-named shapes.\n */\nfunction alignCalls(\n\texpected: CanonicalCall[],\n\tactual: CanonicalCall[]\n): Array<[CanonicalCall | null, CanonicalCall | null]> {\n\tconst usable = (calls: CanonicalCall[]): Map<string, CanonicalCall> => {\n\t\tconst counts = new Map<string, number>()\n\t\tfor (const call of calls) {\n\t\t\tif (call.shapeName === null) continue\n\t\t\tcounts.set(call.shapeName, (counts.get(call.shapeName) ?? 0) + 1)\n\t\t}\n\t\tconst out = new Map<string, CanonicalCall>()\n\t\tfor (const call of calls) {\n\t\t\tif (call.shapeName !== null && counts.get(call.shapeName) === 1) out.set(call.shapeName, call)\n\t\t}\n\t\treturn out\n\t}\n\n\tconst byName = usable(actual)\n\tconst claimed = new Set<CanonicalCall>()\n\tconst pairs: Array<[CanonicalCall | null, CanonicalCall | null]> = []\n\t// Positional cursor for calls that names cannot align, advanced only past claimed calls\n\t// so a named match does not consume an unnamed call's slot.\n\tlet cursor = 0\n\tconst nextUnclaimed = (): CanonicalCall | null => {\n\t\twhile (cursor < actual.length) {\n\t\t\tconst candidate = actual[cursor++]\n\t\t\tif (candidate && !claimed.has(candidate)) return candidate\n\t\t}\n\t\treturn null\n\t}\n\n\tfor (const call of expected) {\n\t\tconst named = call.shapeName === null ? undefined : byName.get(call.shapeName)\n\t\tif (named && !claimed.has(named)) {\n\t\t\tclaimed.add(named)\n\t\t\tpairs.push([call, named])\n\t\t\tcontinue\n\t\t}\n\t\tconst positional = nextUnclaimed()\n\t\tif (positional) claimed.add(positional)\n\t\tpairs.push([call, positional])\n\t}\n\tfor (const call of actual) if (!claimed.has(call)) pairs.push([null, call])\n\treturn pairs\n}\n\nfunction diffValue(\n\texpected: IrValue,\n\tactual: IrValue,\n\tpath: string,\n\tfield: string,\n\tslideNumber: number,\n\tshapeName: string | null,\n\tnestedNames: string[],\n\tout: IrDifference[]\n): void {\n\tif (expected === actual) return\n\tconst kindOf = (value: IrValue): string => (value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value)\n\tif (kindOf(expected) !== kindOf(actual)) {\n\t\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n\t\treturn\n\t}\n\n\tif (Array.isArray(expected) && Array.isArray(actual)) {\n\t\tconst length = Math.max(expected.length, actual.length)\n\t\tfor (let index = 0; index < length; index++) {\n\t\t\tconst before = expected[index]\n\t\t\tconst after = actual[index]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}[${index}]`,\n\t\t\t\t\tfield,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}[${index}]`, field, slideNumber, shapeName, nestedNames, out)\n\t\t}\n\t\treturn\n\t}\n\n\tif (expected !== null && typeof expected === 'object' && actual !== null && typeof actual === 'object') {\n\t\tconst record = expected as Record<string, IrValue>\n\t\tconst other = actual as Record<string, IrValue>\n\t\tfor (const key of new Set([...Object.keys(record), ...Object.keys(other)])) {\n\t\t\tconst before = record[key]\n\t\t\tconst after = other[key]\n\t\t\tif (before === undefined || after === undefined) {\n\t\t\t\tout.push({\n\t\t\t\t\tslideNumber,\n\t\t\t\t\tshapeName,\n\t\t\t\t\tnestedNames,\n\t\t\t\t\tpath: `${path}.${key}`,\n\t\t\t\t\tfield: key,\n\t\t\t\t\tkind: before === undefined ? 'added' : 'lost',\n\t\t\t\t\texpected: brief(before),\n\t\t\t\t\tactual: brief(after),\n\t\t\t\t\tdeclaredBy: null,\n\t\t\t\t})\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdiffValue(before, after, `${path}.${key}`, key, slideNumber, shapeName, nestedNames, out)\n\t\t}\n\t\treturn\n\t}\n\n\tout.push(scalarDifference(slideNumber, shapeName, nestedNames, path, field, expected, actual))\n}\n\nfunction scalarDifference(\n\tslideNumber: number,\n\tshapeName: string | null,\n\tnestedNames: string[],\n\tpath: string,\n\tfield: string,\n\texpected: IrValue,\n\tactual: IrValue\n): IrDifference {\n\treturn {\n\t\tslideNumber,\n\t\tshapeName,\n\t\tnestedNames,\n\t\tpath,\n\t\tfield,\n\t\tkind: 'changed',\n\t\texpected: brief(expected),\n\t\tactual: brief(actual),\n\t\tdeclaredBy: null,\n\t}\n}\n\n/** The first note that covers this difference, or `null` if none does. */\nfunction declaringNote(difference: IrDifference, notes: FidelityNote[]): FidelityNote | null {\n\tfor (const note of notes) {\n\t\tif (note.slideNumber !== null && note.slideNumber !== difference.slideNumber) continue\n\t\t// A layout-shape note is about the chrome, which the diff reports in the deck-level bucket.\n\t\t// Without this a themed outline on a layout — recorded with no slide number, and named\n\t\t// after a shape whose name repeats between the layout and the slides bound to it — would\n\t\t// excuse the same difference on a *slide*, which is a loss nothing declared.\n\t\tif (note.construct.startsWith(LAYOUT_NOTE_PREFIX) && difference.slideNumber !== 0) continue\n\t\t// A shape-scoped note covers only that shape; a slide- or deck-scoped one covers any.\n\t\tif (\n\t\t\tnote.shapeName !== null &&\n\t\t\tnote.shapeName !== difference.shapeName &&\n\t\t\t!difference.nestedNames.includes(note.shapeName)\n\t\t) {\n\t\t\tcontinue\n\t\t}\n\t\tconst fields = noteFields(note.construct)\n\t\tif (!fields) continue\n\t\tif (fields.includes('*') || fields.includes(difference.field)) return note\n\t}\n\treturn null\n}\n\n/**\n * The fields a construct is a promise about.\n *\n * A layout-shape construct falls back to its slide counterpart, which is the whole point of\n * borrowing the vocabulary: `layout.line.width` is `line.width` on a layout and covers exactly\n * the same field. Only the two constructs with no slide twin need entries of their own.\n */\nfunction noteFields(construct: string): readonly string[] | undefined {\n\treturn NOTE_FIELDS[construct] ?? (construct.startsWith(LAYOUT_NOTE_PREFIX) ? NOTE_FIELDS[construct.slice(LAYOUT_NOTE_PREFIX.length)] : undefined) // prettier-ignore\n}\n\n/**\n * `true` when the coverage table can match this construct — directly or through the\n * layout-shape fallback. The check a corpus test runs over every note both printers emit.\n */\nexport function isKnownNoteConstruct(construct: string): boolean {\n\treturn noteFields(construct) !== undefined\n}\n\nfunction brief(value: IrValue | undefined): string {\n\tif (value === undefined) return '—'\n\tconst text = JSON.stringify(value)\n\treturn text.length > 80 ? `${text.slice(0, 80)}…` : text\n}\n"],"mappings":";;;;;;;;;;;;;AA6EA,IAAa,gBAAb,MAA2B;CAC1B,wBAAiB,IAAI,IAAY;CACjC,SAAkC,CAAC;;CAGnC,IAAI,MAA0B;EAC7B,MAAM,MAAM,GAAG,KAAK,YAAY,IAAI,KAAK,UAAU,IAAI,KAAK,UAAU,IAAI,KAAK,YAAY,IAAI,KAAK,MAAM,IAAI,KAAK;EACnH,IAAI,KAAKA,MAAM,IAAI,GAAG,GAAG;EACzB,KAAKA,MAAM,IAAI,GAAG;EAClB,KAAKC,OAAO,KAAK,IAAI;CACtB;;;;;CAMA,IAAI,QAAwB;EAC3B,OAAO,KAAKA;CACb;AACD;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,qBAAqB;;AAclC,SAAgB,WACf,WACA,aACA,YAA2B,MACf;CACZ,OAAO;EACN,KAAK,WAAW,aAAa,OAAO,QAAQ;GAC3C,UAAU,IAAI;IAAE;IAAa;IAAW;IAAW;IAAa;IAAO;GAAO,CAAC;EAChF;EACA,SAAS,MAAM;GACd,OAAO,WAAW,WAAW,aAAa,IAAI;EAC/C;CACD;AACD;;;;;;;;;;AAWA,SAAgB,iBAAiB,OAA6B;CAC7D,OAAO;EACN,KAAK,WAAW,aAAa,OAAO,QAAQ;GAC3C,MAAM,KAAK,GAAG,qBAAqB,aAAa,aAAa,OAAO,MAAM;EAC3E;EACA,SAAS,MAAM;GACd,OAAO,iBAAiB,MAAM,SAAS,IAAI,CAAC;EAC7C;CACD;AACD;;;;ACzHA,SAAgB,WAAW,OAAmC;CAC7D,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAQ,MAAmB,WAAW;AAC7F;;;;;;;;;;;;;AAsBA,SAAgB,UAAU,OAAwB;CACjD,OAAO;AACR;;;;AC7CA,MAAM,eAAe;;;;;AAMrB,MAAM,gBAAgB;;AAGtB,SAAgB,IAAI,OAAuB;CAC1C,OAAO,GAAG,KAAK,MAAM,KAAK,EAAE;AAC7B;;;;;AAMA,SAAgB,OAAO,UAA0B;CAChD,OAAO,QAAQ,WAAW,aAAA,CAAc,QAAQ,aAAa,CAAC;AAC/D;;;;;;;AAaA,SAAgB,eAAe,IAAoB;CAClD,OAAO,QAAQ,KAAK,GAAA,CAAI,QAAQ,aAAa,CAAC;AAC/C;;;;;;;;;;;;AAaA,MAAM,yCAAyB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;AAGD,SAAgB,sBAAsB,OAA+B;CACpE,OAAO,UAAU,QAAQ,uBAAuB,IAAI,KAAK;AAC1D;;AAGA,SAAgB,aAAa,KAAqB;CACjD,OAAO,IAAI,QAAQ,MAAM,EAAE,CAAC,CAAC,YAAY;AAC1C;;;;;;;;;;;;;AAcA,SAAgB,QAAQ,QAAkF;CACzG,MAAM,MAA+B,CAAC;CACtC,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,GAAG;EAC7C,MAAM,QAAQ,OAAO;EACrB,IAAI,UAAU,KAAA,GAAW;EACzB,IAAI,OAAO;EACX,MAAM;CACP;CACA,OAAO,MAAM,MAAM,KAAA;AACpB;;AAGA,SAAgB,gBAAgB,QAAsE;CACrG,OAAO,QAAQ,MAAM,KAAK,CAAC;AAC5B;;AAGA,SAAgB,YAAe,OAAgC;CAC9D,OAAO,UAAU,OAAO,KAAA,IAAY;AACrC;;;;;;;;;;AAWA,SAAgB,oBAAoB,OAAsD;CACzF,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO,KAAA;CAClD,OAAO,KAAK,OAAO,IAAI,SAAS,GAAG;AACpC;;;;;AAMA,SAAgB,gBAAgB,OAA8C;CAC7E,MAAM,MAAM,MAAM;CAClB,IAAI,CAAC,KAAK,OAAO,CAAC;CAClB,OAAO;EAAE,GAAG,IAAI,IAAI,IAAI;EAAG,GAAG,IAAI,IAAI,GAAG;EAAG,GAAG,IAAI,IAAI,KAAK;EAAG,GAAG,IAAI,IAAI,MAAM;CAAE;AACnF;;;;;;;;AC7HA,SAAgB,cAAc,UAAwB,OAAkB,OAA2C;CAClH,MAAM,QAAQ,SAAS,MACrB,KAAK,SAAS;EACd,MAAM,QAAQ,sBAAsB,KAAK,WAAW,IAChD,KAAK,cACN,KAAK,iBAAiB,OACrB,OACA,aAAa,KAAK,YAAY;EAClC,IAAI,UAAU,MAAM,OAAO;EAC3B,OAAO,QAAQ;GACd;GACA,UAAU,KAAK,OAAO,KAAK,YAAY,KAAK,GAAG;GAC/C,cAAc,oBAAoB,KAAK,KAAK;EAC7C,CAAC;CACF,CAAC,CAAC,CACD,QAAQ,SAA0B,SAAS,IAAI;CAEjD,IAAI,MAAM,SAAS,GAAG;EACrB,MAAM,KACL,GAAG,MAAM,YACT,WACA,eACA,wGACD;EACA;CACD;CAEA,IAAI,SAAS,SAAS,QAAQ;EAG7B,IAAI,SAAS,SAAS,QAAQ,SAAS,SAAS,UAC/C,MAAM,KACL,GAAG,MAAM,iBACT,gBACA,cACA,MAAM,SAAS,KAAK,qFACrB;EAED,OAAO;GAAE,MAAM;GAAU;EAAM;CAChC;CACA,OAAO,QAAQ;EAAE,MAAM;EAAU,OAAO,SAAS,YAAY;EAAG;CAAM,CAAC;AACxE;;;;;;;;;AAUA,SAAgB,cAAc,SAAkD;CAC/E,IAAI,CAAC,SAAS,QAAQ,OAAO,KAAA;CAC7B,OAAO;EACN,MAAM;EACN,SAAS,QAAQ;GAChB,QAAQ,QAAQ;GAChB,SAAS,QAAQ,aAAa,aAAa,QAAQ,WAAW,YAAY,IAAI,KAAA;GAC9E,SAAS,QAAQ,aAAa,aAAa,QAAQ,WAAW,YAAY,IAAI,KAAA;EAC/E,CAAC,KAAK,EAAE,QAAQ,QAAQ,OAAO;CAChC;AACD;;;;;;;ACnDA,SAAgB,kBACf,SACA,QACA,OACA,SACsB;CACtB,MAAM,QAAQ,aAAa,SAAS,QAAQ,OAAO,OAAO;CAC1D,IAAI,CAAC,OAAO,OAAO,KAAA;CAEnB,sBAAsB,SAAS,OAAO,OAAO;CAE7C,OAAO,gBAAgB;EACtB,MAAM;EACN,OAAO,EAAE,MAAM,MAAM;EAErB,cAAc,QAAQ,UAAU,IAAI,KAAA,IAAY,oBAAoB,QAAQ,KAAK;CAClF,CAAC;AACF;;AAGA,SAAS,aACR,SACA,QACA,OACA,SACkB;CAClB,MAAM,WAAW,QAAQ;CACzB,IAAI,aAAa,MAAM;EACtB,MAAM,KACL,QAAQ,WACR,WACA,eACA,GAAG,QAAQ,QAAQ,4BAA4B,QAAQ,QAAQ,oHAChE;EACA,OAAO;CACR;CAMA,IAAI,OAAO,cAAc,QAAQ,MAAM,iBAAiB;EACvD,MAAM,KACL,QAAQ,WACR,WACA,cACA,GAAG,QAAQ,QAAQ,gCAAgC,QAAQ,QAAQ,KAAK,SAAS,wFAClF;EACA,OAAO;CACR;CAEA,MAAM,QAAQ,OAAO,SAAS,QAAQ;CACtC,IAAI,CAAC,OAAO;EACX,MAAM,KACL,QAAQ,WACR,WACA,eACA,qBAAqB,QAAQ,QAAQ,IAAI,QAAQ,QAAQ,KAAK,SAAS,gEACxE;EACA,OAAO;CACR;CACA,OAAO;AACR;;AAGA,SAAS,UAAU,MAAgC;CAClD,OAAO,SAAS,SAAS,KAAK,SAAS,KAAK,KAAK,QAAQ,KAAK,KAAK,UAAU,KAAK,KAAK,WAAW;AACnG;;;;;;;AAQA,SAAS,sBAAsB,SAAsB,OAAkB,SAAmC;CACzG,MAAM,OAAiB,CAAC;CACxB,IAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,MAAM,KAAK,KAAK,iBAAiB;CACjF,IAAI,UAAU,QAAQ,OAAO,GAAG,KAAK,KAAK,6BAA6B;CACvE,IAAI,UAAU,QAAQ,QAAQ,GAAG,KAAK,KAAK,8CAA8C;CACzF,IAAI,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,GAAG,KAAK,KAAK,gCAAgC,QAAQ,IAAI,GAAG;CAGxG,IAAI,QAAQ,iBAAiB,OAAO,KAAK,KAAK,mDAAiD;CAC/F,IAAI,KAAK,WAAW,GAAG;CAEvB,MAAM,KACL,GAAG,QAAQ,UAAU,YACrB,gBACA,cACA,qBAAqB,QAAQ,QAAQ,0KAA0K,KAAK,KAAK,IAAI,EAAE,GAAG,KAAK,WAAW,IAAI,SAAS,KAAK,WACrQ;AACD;;;;;;;;;;;;;;;;;;;;;;;ACvGA,MAAM,UAAU;;AAGhB,MAAM,iCAAiB,IAAI,IAAI;CAAC;CAAM;CAAO;CAAgB;CAAS;AAAO,CAAC;AAgB9E,MAAM,eAAe;AAErB,SAAS,IAAI,SAAkB,cAAsB,WAA4B;CAChF,MAAM,KAAK;CACX,IAAI,CAAC,MAAM,OAAO,GAAG,2BAA2B,YAAY,OAAO;CACnE,OAAO,GAAG,uBAAuB,cAAc,SAAS,CAAC,CAAC,SAAS;AACpE;;;;;;;;;;AAWA,SAAS,MAAM,SAA6B,cAAsB,WAAuC;CACxG,IAAI,CAAC,SAAS,OAAO;CACrB,KAAK,IAAI,OAAO,QAAQ,YAAY,MAAM,OAAO,KAAK,aAAa;EAClE,IAAI,KAAK,aAAa,cAAc;EACpC,MAAM,KAAK;EACX,IAAI,GAAG,iBAAiB,gBAAgB,GAAG,cAAc,WAAW,OAAO;CAC5E;CACA,OAAO;AACR;;AAGA,SAAS,SAAS,SAA4C;CAC7D,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,MAAM,MAAqB,CAAC;CAC5B,KAAK,IAAI,OAAO,QAAQ,YAAY,MAAM,OAAO,KAAK,aACrD,IAAI,KAAK,aAAa,cAAc,IAAI,KAAK,IAA8B;CAE5E,OAAO;AACR;;;;;;;;;AAUA,SAAgB,aAAa,SAA2B;CACvD,OAAO,IAAI,SAAS,SAAS,GAAG,WAAW,KAAK,IAAI,SAAS,SAAS,GAAG,WAAW;AACrF;;;;;;;;;AAUA,SAAgB,YAAY,SAA2B;CACtD,OAAO,IAAI,SAAS,SAAS,OAAO;AACrC;;;;;;;;;;;;;;AAeA,SAAgB,UAAU,SAA2B;CAEpD,OAAO,MADQ,MAAM,SAA+B,SAAS,GAAG,QAC9C,GAAG,SAAS,GAAG,SAAS,CAAC,EAAE,aAAa,OAAO,MAAM;AACxE;;;;;;;;;;;;;AAcA,SAAgB,sBAAsB,SAA2B;CAChE,MAAM,OAAO,MAAM,MAAM,SAA+B,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM;CAClG,IAAI,CAAC,MAAM,OAAO;CAElB,MAAM,MAAM,MAAM,MAAM,SAAS,GAAG,KAAK;CACzC,MAAM,MAAM,MAAM,MAAM,SAAS,GAAG,KAAK;CACzC,MAAM,QAAQ,MAAM,MAAM,SAAS,GAAG,OAAO;CAC7C,MAAM,QAAQ,MAAM,MAAM,SAAS,GAAG,OAAO;CAC7C,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,OAAO;CAE7C,OACC,IAAI,aAAa,GAAG,MAAM,MAAM,aAAa,GAAG,KAChD,IAAI,aAAa,GAAG,MAAM,MAAM,aAAa,GAAG,KAChD,IAAI,aAAa,IAAI,MAAM,MAAM,aAAa,IAAI,KAClD,IAAI,aAAa,IAAI,MAAM,MAAM,aAAa,IAAI;AAEpD;;;;;;;;;AAUA,SAAgB,gBAAgB,SAA2B;CAC1D,OAAO,IAAI,SAAS,SAAS,GAAG,WAAW;AAC5C;;;;;;;;AASA,SAAgB,cAAc,SAA2B;CAExD,OAAO,SADU,MAAM,SAA+B,SAAS,GAAG,UAC3C,CAAC,CAAC,CAAC,MAAM,UAAU,SAAS,KAAK,CAAC,CAAC,SAAS,CAAC;AACrE;;;;;;;;;;;;;;;;AAiBA,SAAgB,mBAAmB,SAA2B;CAC7D,OAAO,IAAI,SAAS,SAAS,GAAG,IAAI;AACrC;;;;;;;;;;;;AAaA,SAAgB,oBAAoB,SAA2B;CAE9D,OAAO,SADQ,MAAM,MAAM,SAA+B,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QACtE,CAAC,CAAC,CAAC,MACtB,UACA,MAAM,iBAAiB,SAAS,KAAK,eAAe,IAAI,MAAM,aAAa,EAAE,KAAK,CAAC,mBAAmB,KAAK,CAC7G;AACD;;;;;;;;AC/KA,MAAM,QAAgC;CAAE,GAAG;CAAQ,KAAK;CAAU,GAAG;CAAS,MAAM;AAAU;;AAG9F,MAAMC,WAAiC;CAAE,GAAG;CAAO,KAAK;CAAU,GAAG;AAAS;;AAG9E,MAAM,MAA8B;CAAE,MAAM;CAAQ,aAAa;CAAU,WAAW;AAAS;;AAG/F,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAU;CAAQ;CAAiB;CAAQ;CAAW;CAAe;AAAgB,CAAC;;;;;;;;AASrH,MAAM,oCAAoB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;;;;;;AAaD,SAAS,aAAa,QAAsB,OAA2B;CAGtE,IAAI,OAAO,SAAS,QAAQ,OAAO;CAInC,IAAI,OAAO,SAAS,WAAW;EAC9B,MAAM,KACL,uBACA,gBACA,eACA,2KACD;EACA,OAAO;CACR;CAEA,MAAM,QAAQ,YAAY,QAAQ,KAAK;CAEvC,IAAI,OAAO,SAAS,WAAW;EAC9B,IAAI,CAAC,kBAAkB,IAAI,OAAO,MAAM,GAAG;GAC1C,MAAM,KACL,0BACA,gBACA,cACA,qBAAqB,OAAO,OAAO,uFACpC;GACA,OAAO,QAAQ;IAAE,MAAM;IAAU,GAAG,cAAc,OAAO,OAAO;IAAG,GAAG;GAAM,CAAC,KAAK,EAAE,MAAM,SAAS;EACpG;EACA,OACC,QAAQ;GAAE,MAAM;GAAU,YAAY,OAAO;GAAQ,GAAG,cAAc,OAAO,OAAO;GAAG,GAAG;EAAM,CAAC,KAAK,EACrG,MAAM,SACP;CAEF;CAMA,MAAM,OAAO,OAAO,KAAK,YAAY,CAAC,KAAK;CAC3C,IAAI,OAAO,OACV,MAAM,KACL,qBACA,gBACA,cACA,kBAAkB,KAAK,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,+IACnD;CAED,OAAO,QAAQ;EAAE,eAAe,KAAK,SAAS,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,GAAG,GAAG;EAAG,GAAG;CAAM,CAAC,KAAK,CAAC;AACnG;;;;;;;;;;;;;;AAeA,SAAS,iBAAiB,SAAwB,aAA2C;CAC5F,IAAI,YAAY,MAAM,OAAO;CAC7B,OAAO,gBAAgB,YAAY,KAAA,IAAY;AAChD;;;;;;;;AASA,SAAS,cAAc,SAAiD;CACvE,OAAO,YAAY,QAAQ,YAAY,IAAI,CAAC,IAAI,EAAE,eAAe,QAAQ;AAC1E;;;;;;;;AASA,SAAS,YAAY,QAAqB,OAA2C;CACpF,IAAI,OAAO,WAAW,MACrB,MAAM,KACL,sBACA,WACA,cACA,yLACD;CAKD,MAAM,UAAU,OAAO;CACvB,IAAI,YAAY,SAAS,UAAU,MAAM,UAAU,MAClD,MAAM,KACL,uBACA,gBACA,cACA,qBAAqB,QAAQ,4HAC9B;CAGD,OACC,QAAQ;EACP,UAAU,YAAY,OAAO,IAAI;EACjC,MAAM,YAAY,QAAQ,UAAU,MAAM,UAAU,MAAM,KAAA,IAAY;EACtE,OAAO,YAAY,QAAQ,KAAK;CACjC,CAAC,KAAK,CAAC;AAET;;;;;AAMA,SAAS,YAAY,QAAqB,OAAsC;CAC/E,MAAM,SAAS,OAAO;CACtB,IAAI,sBAAsB,MAAM,GAAG,OAAO;CAC1C,IAAI,OAAO,UAAU,MAAM,OAAO,aAAa,OAAO,KAAK;CAC3D,MAAM,WAAW,OAAO;CACxB,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,IAAI,WAAW,MACd,MAAM,KACL,2BACA,gBACA,cACA,yBAAyB,OAAO,8GACjC;CAED,OAAO,aAAa,SAAS,YAAY;AAC1C;;;;;;;;;;;;;AAcA,SAAgB,WAAW,KAAU,OAAuD;CAC3F,MAAM,YAAY,IAAI;CAEtB,OAAO,QAAQ;EACd,MAAM,YAAY,IAAI,IAAI;EAC1B,QAAQ,YAAY,IAAI,MAAM;EAC9B,WAAW,cAAc,OAAO,KAAA,IAAY,EAAE,OAAO,UAAU;EAC/D,QAAQ,YAAY,IAAI,MAAM;EAC9B,UAAU,YAAY,IAAI,UAAU;EACpC,UAAU,YAAY,IAAI,QAAQ;EAClC,OAAO,SAAS,KAAK,KAAK;EAC1B,WAAW,IAAI,YAAY,aAAa,IAAI,UAAU,YAAY,IAAI,KAAA;EACtE,MAAM,YAAY,IAAI,IAAI;EAG1B,UAAU,YAAY,IAAI,WAAW;EACrC,WAAW,gBAAgB,GAAG;CAC/B,CAAC;AACF;;;;;;;AAQA,SAAS,SAAS,KAAU,OAAsC;CACjE,MAAM,SAAS,IAAI;CACnB,IAAI,sBAAsB,MAAM,GAAG,OAAO;CAC1C,IAAI,WAAW,MAAM;EACpB,MAAM,KACL,0BACA,gBACA,cACA,kBAAkB,OAAO,8GAC1B;EACA,MAAM,WAAW,IAAI;EACrB,OAAO,WAAW,aAAa,SAAS,YAAY,IAAI,KAAA;CACzD;CACA,IAAI,IAAI,UAAU,MAAM,OAAO,aAAa,IAAI,KAAK;CAQrD,MAAM,YAAY,IAAI;CACtB,IAAI,CAAC,WAAW;EACf,MAAM,KACL,sBACA,gBACA,UACA,yPACD;EACA;CACD;CACA,MAAM,KACL,wBACA,aACA,eACA,0OACD;CACA,OAAO,aAAa,UAAU,YAAY;AAC3C;;;;;;AAOA,SAAS,gBAAgB,KAA+B;CACvD,MAAM,OAAO,IAAI;CACjB,IAAI,CAAC,MAAM,KAAK,OAAO,KAAA;CACvB,OAAO,QAAQ;EAAE,KAAK,KAAK;EAAK,SAAS,KAAK,WAAW,KAAA;CAAU,CAAC;AACrE;;AAGA,SAAS,iBAAiB,WAAsB,OAA2C;CAC1F,MAAM,UAAU,UAAU;CAC1B,MAAM,SAAS,UAAU;CACzB,MAAM,QAAQ,UAAU;CAExB,IAAI,UAAU,QAAQ,EAAE,SAAS,QAChC,MAAM,KACL,cACA,WACA,cACA,0BAA0B,MAAM,oFACjC;CAED,IAAI,UAAU,kBAAkB,KAAK,UAAU,iBAAiB,GAC/D,MAAM,KACL,sBACA,WACA,cACA,sPACD;CAMD,MAAM,cAAc,WAAW,OAAO,YAAY,aAAa,QAAQ,KAAK;CAE5E,OACC,QAAQ;EACP,OAAO,UAAU,OAAO,KAAA,IAAY,MAAM;EAC1C,aAAa,UAAU,UAAU,IAAI,KAAA,IAAY,UAAU;EAC3D,gBAAgB,iBAAiB,UAAU,cAAc,WAAW;EACpE,YAAY,iBAAiB,UAAU,UAAU,WAAW;EAC5D,iBAAiB,YAAY,UAAU,aAAa;EACpD,gBAAgB,YAAY,UAAU,YAAY;EAClD,aAAa,SAAS,SAAS,WAAW,QAAQ,UAAU,KAAA;EAC5D,qBAAqB,SAAS,SAAS,YAAY,QAAQ,UAAU,MAAM,KAAA;EAQ3E,QAAQ;CACT,CAAC,KAAK,CAAC;AAET;;;;;;;;AASA,SAAgB,SAAS,OAAkB,OAA6B;CACvE,MAAM,aAAa,MAAM;CACzB,MAAM,QAAmB,CAAC;CAE1B,WAAW,SAAS,WAAW,mBAAmB;EACjD,MAAM,WAAW,iBAAiB,WAAW,KAAK;EAClD,MAAM,OAAO,UAAU;EAGvB,MAAM,SAAS,iBAAiB,WAAW,SAAS;EAEpD,IAAI,KAAK,WAAW,GAAG;GACtB,MAAM,KAAK;IAAE,MAAM;IAAI,SAAS,QAAQ;KAAE,GAAG;KAAU,WAAW;IAAO,CAAC,KAAK,CAAC;GAAE,CAAC;GACnF;EACD;EAEA,KAAK,SAAS,KAAK,aAAa;GAC/B,MAAM,YAAY,aAAa,KAAK,SAAS;GAM7C,MAAM,eAAe,EAAE,GAAG,SAAS;GACnC,OAAO,aAAa;GACpB,MAAM,UAAU,QAAQ;IACvB,GAAI,aAAa,IAAI,WAAW;IAChC,GAAG,WAAW,KAAK,KAAK;IACxB,GAAI,aAAa,SAAS,EAAE,WAAW,KAAK,IAAI,CAAC;GAClD,CAAC;GACD,MAAM,KAAK,QAAQ;IAAE,MAAM,IAAI;IAAM;GAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,CAAC;EACtE,CAAC;CACF,CAAC;CAED,OAAO;AACR;;;;;;;;;AAUA,SAAgB,iBAAiB,OAAkB,OAA2C;CAC7F,MAAM,OAAO,MAAM;CACnB,MAAM,SAAS,MAAM;CACrB,MAAM,OAAO,MAAM,QAAQ;CAE3B,IAAI,SAAS,QAAQ,CAAC,cAAc,IAAI,IAAI,GAC3C,MAAM,KACL,aACA,WACA,cACA,mBAAmB,KAAK,gEACzB;CAGD,OACC,QAAQ;EAIP,QAAQ,WAAW,OAAO,QAAQA,SAAO;EAEzC,MAAM,MAAM,SAAS,QAAQ,MAAM,SAAS,KAAA,IAAY,KAAA,IAAY,KAAK,SAAS;EAClF,MAAM,SAAS,QAAQ,cAAc,IAAI,IAAI,IAAI,OAAO,KAAA;EACxD,KAAK,UAAU,OAAO,KAAK;EAC3B,QAAQ,aAAa,IAAI;CAC1B,CAAC,KAAK,CAAC;AAET;;;;;;;;;;;;;;;;AAiBA,SAAS,UAAU,OAAkB,OAAuC;CAC3E,MAAM,UAAU,MAAM;CACtB,IAAI,YAAY,MAAM,OAAO,KAAA;CAC7B,IAAI,YAAY,eAAe,OAAO,IAAI;CAE1C,MAAM,QAAQ,QAAQ;EACrB,WAAW,SAAS,MAAM,kBAAkB,aAAa,KAAK;EAC9D,gBAAgB,SAAS,MAAM,2BAA2B,kBAAkB,KAAK;CAClF,CAAC;CACD,OAAO,QAAQ;EAAE,MAAM;EAAU,GAAG;CAAM,IAAI,IAAI;AACnD;;AAGA,SAAS,SAAS,OAAsB,MAAc,OAAsC;CAC3F,IAAI,UAAU,MAAM,OAAO,KAAA;CAC3B,IAAI,SAAS,KAAK,SAAS,KAAK,OAAO;CACvC,MAAM,KACL,gBAAgB,QAChB,WACA,cACA,wBAAwB,KAAK,MAAM,MAAM,4FAC1C;AAED;;;;;;;;;;;;;AAcA,MAAM,oBAAoB;CAAE,MAAM;CAAK,OAAO;CAAK,KAAK;CAAK,QAAQ;AAAI;AAEzE,SAAS,aAAa,MAAkD;CACvE,MAAM,SAAS,MAAM;CACrB,IAAI,CAAC,QAAQ,OAAO,KAAA;CACpB,MAAM,EAAE,MAAM,OAAO,KAAK,WAAW;CACrC,IAAI,SAAS,KAAA,KAAa,UAAU,KAAA,KAAa,QAAQ,KAAA,KAAa,WAAW,KAAA,GAAW,OAAO,KAAA;CACnG,OAAO;EACN,eAAe,OAAO,kBAAkB,GAAG;EAC3C,eAAe,SAAS,kBAAkB,KAAK;EAC/C,eAAe,UAAU,kBAAkB,MAAM;EACjD,eAAe,QAAQ,kBAAkB,IAAI;CAC9C;AACD;;;;ACjeA,MAAM,oBAAwC;CAC7C,WAAW;CACX,SAAS;CACT,SAAS;AACV;;AAGA,MAAM,qBAAyC;CAC9C,WAAW;CACX,SAAS;CACT,SAAS;AACV;;AAGA,MAAM,SAAiC;CAAE,GAAG;CAAO,KAAK;CAAU,GAAG;AAAS;AAE9E,SAAgB,UAAU,OAAqB,OAAc,OAAkB,QAA+B;CAC7G,MAAM,UAAU,MAAM;CACtB,MAAM,WAAW,MAAM,kBAAkB;CACzC,MAAM,OAAkB,CAAC;CACzB,MAAM,aAAuB,CAAC;CAE9B,KAAK,MAAM,OAAO,MAAM,MAAM;EAC7B,MAAM,QAAmB,CAAC;EAC1B,KAAK,MAAM,QAAQ,IAAI,OAAO;GAI7B,IAAI,KAAK,qBAAqB;GAC9B,MAAM,KAAK,OAAO,MAAM,UAAU,OAAO,MAAM,CAAC;EACjD;EACA,KAAK,KAAK,KAAK;EACf,WAAW,KAAK,IAAI,aAAa,CAAC;CACnC;CAYA,MAAM,WAAW,WAAW,QAAQ,WAAW,WAAW,CAAC,CAAC,CAAC;CAC7D,IAAI,aAAa,WAAW,UAAU,WAAW,GAChD,MAAM,KACL,iBACA,gBACA,eACA,6MACD;MACM,IAAI,WAAW,GACrB,MAAM,KACL,iBACA,gBACA,eACA,4MACD;CAGD,IAAI,YAAY,MACf,MAAM,KACL,eACA,WACA,eACA,0FACD;CAGD,MAAM,eAAe,MAAM;CAiB3B,OAAO;EAAE,QAAQ;EAAY,MAAM,CAAC,MAhBpB,QAAQ;GACvB,GAAG,gBAAgB,KAAK;GACxB,YAAY,MAAM,QAAQ,KAAA;GAG1B,YAAY,YAAY,OAAO;GAI/B,WAAW,UAAU,OAAO,OAAO,MAAM;GACzC,WAAW,MAAM,iBAAiB,OAAO,KAAA;GACzC,eAAe,MAAM,aAAa,OAAO,KAAA;GACzC,MAAM,aAAa,OAAO,MAAM,MAAM,IAAI,IAAI,KAAA,IAAY,aAAa,KAAK,MAAM,OAAO,KAAK,CAAC,CAAC;GAChG,MAAM,WAAW,OAAO,MAAM,MAAM,CAAC,IAAI,KAAA,IAAY,WAAW,IAAI,MAAM;EAC3E,CAEgD,KAAK,CAAC,CAAC;EAAG,GAAI,MAAM,OAAO,EAAE,YAAY,MAAM,KAAK,IAAI,CAAC;CAAG;AAC7G;;;;;;;;;;AAWA,SAAS,UAAU,OAAc,OAAkB,QAA4C;CAC9F,MAAM,WAAW,MAAM;CACvB,IAAI,UAAU;EACb,MAAM,QAAQ,cAAc,UAAU,OAAO,YAAY;EACzD,IAAI,OAAO,OAAO;GAAE,MAAM;GAAY,UAAU;EAAM;CACvD;CAEA,MAAM,UAAU,cAAc,MAAM,WAAW;CAC/C,IAAI,SAAS,OAAO;CAEpB,MAAM,UAAU,MAAM;CACtB,IAAI,SAAS,OAAO,kBAAkB,SAAS,QAAQ,OAAO,kBAAkB;CAEhF,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,MAAM,OAAO,EAAE,OAAO,OAAO;CAE5C,MAAM,WAAW,MAAM;CACvB,OAAO,WAAW,EAAE,OAAO,aAAa,SAAS,YAAY,EAAE,IAAI,KAAA;AACpE;;;;;;;;AASA,SAAS,OAAO,MAAiB,UAAmB,OAAkB,QAAgC;CACrG,MAAM,QAAQ,KAAK;CACnB,MAAM,SAAS,KAAK;CACpB,MAAM,UAAU,KAAK;CAOrB,IAAI,KAAK,OAAO,QAAQ,KAAK,UAAU,SAAS,GAC/C,MAAM,KACL,sBACA,WACA,cACA,yOACD;CAGD,MAAM,UAAU,QAAQ;EACvB,MAAM,SAAS,MAAM,UAAU,OAAO,MAAM;EAC5C,QAAQ,YAAY,MAAM,KAAK;EAC/B,UAAU,cAAc,MAAM,KAAK;EACnC,WAAW,KAAK,YAAY,OAAO,KAAA;EACnC,QAAQ,WAAW,IAAI;EACvB,QAAQ,WAAW,OAAO,KAAA,IAAY,OAAO;EAI7C,eAAe,kBAAkB,MAAM,KAAK;EAG5C,cAAc,KAAK,iBAAiB,UAAU,KAAK,iBAAiB,aAAa,KAAK,eAAe,KAAA;EACrG,SAAS,KAAK,WAAW,IAAI,KAAK,WAAW,KAAA;EAC7C,SAAS,KAAK,UAAU,IAAI,KAAK,UAAU,KAAA;EAE3C,QAAQ,UACL;GAAC,OAAO,QAAQ,OAAO,CAAC;GAAG,OAAO,QAAQ,SAAS,CAAC;GAAG,OAAO,QAAQ,UAAU,CAAC;GAAG,OAAO,QAAQ,QAAQ,CAAC;EAAC,IAC7G,KAAA;EAGH,GAAI,OAAO,WAAW,EAAE,EAAE,KAAK,KAAM,WAAW,MAAM,WAAW,EAAE,CAAC,KAAK,IAAI,KAAK,KAAK,CAAC,IAAK,CAAC;CAC/F,CAAC;CAED,OAAO,QAAQ;EAAE,MAAM,QAAQ,SAAS,OAAO,KAAK,IAAI,KAAK;EAAM;CAAQ,CAAC,KAAK,EAAE,MAAM,GAAG;AAC7F;;;;;;;;AASA,SAAS,cAAc,MAAiB,OAAuC;CAC9E,MAAM,UAAU,KAAK;CACrB,IAAI,CAAC,WAAY,CAAC,QAAQ,UAAU,CAAC,QAAQ,QAAS,OAAO,KAAA;CAC7D,OAAO,QAAQ;EACd,QAAQ,QAAQ,SAAS,SAAS,QAAQ,QAAQ,KAAK,IAAI,KAAA;EAC3D,QAAQ,QAAQ,SAAS,SAAS,QAAQ,QAAQ,KAAK,IAAI,KAAA;CAC5D,CAAC;AACF;;;;;;;;;AAUA,SAAS,WAAW,MAAsC;CACzD,MAAM,SAAS,KAAK;CACpB,IAAI,CAAC,QAAQ,OAAO,KAAA;CACpB,MAAM,MAAM,OAAO;CACnB,OACC,QAAQ;EACP,QAAQ,YAAY,OAAO,MAAM,MAAM;EACvC,OAAO,YAAY,OAAO,MAAM,OAAO;EACvC,QAAQ,YAAY,OAAO,MAAM,QAAQ;EACzC,UAAU,YAAY,OAAO,QAAQ;EAGrC,UAAU,KAAK,OAAO,IAAI,MAAM;GAAE,KAAK,IAAI;GAAK,KAAK,IAAI;EAAI,IAAI,KAAA;CAClE,CAAC,KAAK,CAAC;AAET;;AAGA,MAAM,2CAA2B,IAAI,IAAI;CAAC;CAAQ;CAAQ;CAAW;AAAa,CAAC;;;;;;;;;AAUnF,SAAS,kBAAkB,MAAiB,OAAuC;CAClF,MAAM,OAAO,KAAK;CAClB,IAAI,SAAS,QAAQ,SAAS,QAAQ,OAAO,KAAA;CAC7C,IAAI,yBAAyB,IAAI,IAAI,GAAG,OAAO;CAC/C,MAAM,KACL,mBACA,WACA,cACA,iCAAiC,KAAK,+GACvC;AAED;;;;;;;;;;;;;;;;;AAkBA,SAAS,SAAS,MAAiB,UAAmB,OAAkB,QAA4C;CAMnH,IAAI,KAAK,YAAY,OAAO,EAAE,MAAM,OAAO;CAM3C,MAAM,WAAW,KAAK;CACtB,IAAI,UAAU;EACb,MAAM,QAAQ,cAAc,UAAU,OAAO,iBAAiB;EAC9D,IAAI,OAAO,OAAO;GAAE,MAAM;GAAY,UAAU;EAAM;CACvD;CAEA,MAAM,UAAU,cAAc,KAAK,WAAW;CAC9C,IAAI,SAAS,OAAO;CAEpB,MAAM,UAAU,KAAK;CACrB,IAAI,SAAS,OAAO,kBAAkB,SAAS,QAAQ,OAAO,iBAAiB;CAE/E,MAAM,SAAS,KAAK;CACpB,IAAI,WAAW,MAAM,OAAO,EAAE,OAAO,OAAO;CAK5C,IAAI,YAAY,CAAC,KAAK,YAAY,OAAO,KAAA;CAEzC,MAAM,WAAW,KAAK;CACtB,IAAI,CAAC,UAAU,OAAO,KAAA;CAKtB,OAAO,EAAE,OAAO,aAAa,SAAS,YAAY,EAAE;AACrD;;;;;;;;AASA,SAAS,YAAY,MAAiB,OAAuC;CAC5E,MAAM,UAAU,KAAK;CACrB,IAAI,CAAC,SAAS,OAAO,KAAA;CAErB,MAAM,QAAQ;EAAC,QAAQ;EAAK,QAAQ;EAAO,QAAQ;EAAQ,QAAQ;CAAI;CACvE,IAAI,MAAM,OAAO,SAAS,SAAS,IAAI,GAAG,OAAO,KAAA;CAEjD,OAAO,MAAM,KAAK,SAAS,SAAS,MAAM,KAAK,CAAC;AACjD;;AAGA,MAAMC,oCAAkB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;;;AAUD,SAAS,SAAS,MAAyB,OAA2B;CACrE,IAAI,CAAC,MAAM,OAAO,CAAC;CACnB,IAAI,KAAK,QAAQ,OAAO,EAAE,MAAM,OAAO;CACvC,MAAM,OAAO,KAAK;CAClB,MAAM,QAAQ,SAAS,QAAQA,kBAAgB,IAAI,IAAI;CACvD,IAAI,CAAC,OACJ,MAAM,KACL,2BACA,gBACA,eACA,wCAAwC,KAAK,gFAC9C;CAED,OACC,QAAQ;EACP,MAAM,SAAS,QAAQ,SAAS,UAAU,UAAU;EAEpD,UAAU,SAAS,SAAS,QAAQ,SAAS,UAAU,OAAO,KAAA;EAC9D,OAAO,KAAK,gBAAgB,KAAK,UAAU,OAAO,KAAA,IAAY,aAAa,KAAK,KAAK;EACrF,OAAO,YAAY,KAAK,OAAO;CAChC,CAAC,KAAK,CAAC;AAET;;;;;;;;;ACnWA,MAAM,aAAqC;CAC1C,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,QAAQ;CACR,UAAU;CACV,UAAU;CACV,MAAM;CACN,QAAQ;CACR,KAAK;CACL,OAAO;CACP,OAAO;CACP,SAAS;CACT,OAAO;CACP,SAAS;CACT,WAAW;AACZ;;AAGA,MAAM,aAAqC;CAAE,GAAG;CAAK,GAAG;CAAK,GAAG;CAAK,GAAG;CAAK,IAAI;AAAK;AAEtF,SAAgB,UAAU,OAAqB,OAAc,OAAiC;CAC7F,MAAM,aAAa,MAAM;CACzB,MAAM,OAAO,eAAe,OAAO,KAAA,IAAY,WAAW;CAC1D,IAAI,CAAC,MAAM;EACV,MAAM,KACL,cACA,WACA,cACA,eAAe,cAAc,OAAO,wDACrC;EACA,OAAO;CACR;CAEA,IAAI,MAAM,WAAW,SAAS,GAC7B,MAAM,KACL,eACA,aACA,eACA,kBAAkB,MAAM,WAAW,KAAK,KAAK,EAAE,2BAA2B,KAAK,0FAChF;CAGD,MAAM,KACL,kBACA,gBACA,eACA,8LACD;CAEA,MAAM,OAAO,WAAW,OAAO,KAAK;CACpC,IAAI,KAAK,WAAW,GAAG;EACtB,MAAM,KAAK,cAAc,WAAW,eAAe,8CAA8C;EACjG,OAAO;CACR;CAgBA,OAAO;EACN,QAAQ;EACR,MAAM,CAAC,MAbQ,QAAQ;GACvB;GACA,GAAG,gBAAgB,KAAK;GACxB,YAAY,MAAM,QAAQ,KAAA;GAC1B,GAAG,aAAa,KAAK;GACrB,GAAG,cAAc,KAAK;GACtB,GAAG,aAAa,KAAK;GACrB,GAAG,YAAY,KAAK;GACpB,aAAa,aAAa,KAAK;EAChC,CAIoB,KAAK,EAAE,KAAK,CAAC;EAChC,GAAI,MAAM,OAAO,EAAE,YAAY,MAAM,KAAK,IAAI,CAAC;CAChD;AACD;;;;;;AAOA,SAAS,WAAW,OAAc,OAA6B;CAC9D,MAAM,aAAa,MAAM,WAAW,KAAK,UAAU,SAAS,EAAE;CAC9D,IAAI,WAAW;CAEf,MAAM,OAAO,MAAM,OAAO,KAAK,QAAQ,UAAU;EAChD,MAAM,SAAS,OAAO,OAAO,KAAK,UAAU;GAC3C,IAAI,UAAU,MAAM,WAAW;GAC/B,OAAO,SAAS;EACjB,CAAC;EACD,OACC,QAAQ;GACP,MAAM,YAAY,OAAO,IAAI;GAC7B;GAEA,QAAQ,UAAU,KAAK,WAAW,SAAS,IAAI,aAAa,KAAA;EAC7D,CAAC,KAAK,EAAE,OAAO;CAEjB,CAAC;CAED,IAAI,UACH,MAAM,KACL,gBACA,gBACA,cACA,2LACD;CAED,OAAO;AACR;AAEA,SAAS,aAAa,OAAmD;CACxE,MAAM,QAAQ,MAAM;CACpB,OAAO,UAAU,OAAO,CAAC,IAAI;EAAE,WAAW;EAAM;CAAM;AACvD;AAEA,SAAS,cAAc,OAAmD;CACzE,MAAM,SAAS,MAAM;CACrB,IAAI,CAAC,QAAQ,OAAO,EAAE,YAAY,MAAM;CACxC,OAAO;EACN,YAAY;EACZ,WAAW,OAAO,aAAa,OAAO,KAAA,IAAY,WAAW,OAAO;CACrE;AACD;AAEA,SAAS,aAAa,OAAmD;CACxE,MAAM,SAAS,MAAM;CACrB,IAAI,CAAC,QAAQ,OAAO,CAAC;CACrB,OAAO;EACN,WAAW,OAAO,aAAa,KAAA;EAC/B,aAAa,OAAO,kBAAkB,KAAA;EACtC,aAAa,OAAO,oBAAoB,KAAA;EACxC,aAAa,OAAO,eAAe,KAAA;EACnC,eAAe,OAAO,iBAAiB,KAAA;EACvC,iBAAiB,OAAO,mBAAmB,KAAA;EAC3C,mBAAmB,YAAY,OAAO,QAAQ;EAC9C,qBAAqB,OAAO,cAAc,cAAc,KAAA;CACzD;AACD;;;;;AAMA,SAAS,YAAY,OAAmD;CACvE,MAAM,MAAM,MAAM;CAClB,MAAM,MAAM,MAAM;CAClB,OAAO;EACN,eAAe,KAAK,SAAS,OAAO,KAAA;EACpC,cAAc,KAAK,SAAS,KAAA;EAC5B,eAAe,KAAK,SAAS,OAAO,KAAA;EACpC,cAAc,KAAK,SAAS,KAAA;EAC5B,eAAe,KAAK,OAAO,KAAA;EAC3B,eAAe,KAAK,OAAO,KAAA;EAC3B,kBAAkB,KAAK,aAAa,KAAA;EACpC,wBAAwB,KAAK,cAAc,cAAc,KAAA;CAC1D;AACD;;;;;;;AAQA,SAAS,aAAa,OAAmC;CACxD,MAAM,SAAS,MAAM;CACrB,IAAI,OAAO,WAAW,GAAG,OAAO,KAAA;CAChC,MAAM,SAAmB,CAAC;CAC1B,KAAK,MAAM,OAAO,QAAQ;EAEzB,MAAM,MADO,IAAI,MACC;EAClB,IAAI,CAAC,KAAK,OAAO,KAAA;EACjB,OAAO,KAAK,aAAa,GAAG,CAAC;CAC9B;CACA,OAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjJA,MAAM,qBAAyC;CAC9C,WAAW;CACX,SAAS;CACT,SAAS;AACV;;AAGA,MAAM,kCAAkB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAW;CAAQ;CAAW;AAAU,CAAC;;AAG3F,MAAM,kCAAkB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;AAQD,MAAM,aAA0D;CAC/D,MAAM;CACN,IAAI;CACJ,KAAK;AACN;;;;;AAMA,SAAgB,UAAU,OAAiB,OAAkB,QAAsC;CAClG,MAAM,SAAS,MAAM,SAAS,MAAM,QAAQ,IAAI;CAEhD,IAAI,MAAM,QAAQ;EACjB,WAAW,MAAM;EACjB,OAAO;CACR;CAEA,IAAI,aAAa,KAAK,GAAG,OAAO,UAAU,OAAO,QAAQ,MAAM;CAC/D,IAAI,UAAU,KAAK,GAAG,OAAO,YAAY,OAAO,QAAQ,MAAM;CAC9D,IAAI,YAAY,KAAK,GAAG,OAAO,cAAc,OAAO,MAAM;CAC1D,IAAI,eAAe,KAAK,GAAG,OAAO,iBAAiB,OAAO,QAAQ,MAAM;CACxE,IAAI,YAAY,KAAK,GAAG,OAAO,cAAc,OAAO,QAAQ,MAAM;CAKlE,OAAO;AACR;;;;;;AAOA,SAAS,WAAW,OAAwB;CAC3C,MAAM,KACL,gBACA,WACA,cACA,uFACD;AACD;;;;;;;;AAWA,SAAS,gBAAgB,OAAiB,OAA4C;CACrF,MAAM,QAAQ,MAAM;CACpB,IAAI,OAAO,OAAO;EAAE,GAAG,IAAI,MAAM,IAAI;EAAG,GAAG,IAAI,MAAM,GAAG;EAAG,GAAG,IAAI,MAAM,KAAK;EAAG,GAAG,IAAI,MAAM,MAAM;CAAE;CAOrG,MAAM,WAAW,MAAM;CACvB,IAAI,CAAC,UAAU,OAAO,CAAC;CACvB,OAAO,KACN,wBACA,aACA,eACA,0EAA0E,SAAS,OAAO,sHAAsH,SAAS,QAC1N;CACA,OAAO;EAAE,GAAG,IAAI,SAAS,IAAI;EAAG,GAAG,IAAI,SAAS,GAAG;EAAG,GAAG,IAAI,SAAS,KAAK;EAAG,GAAG,IAAI,SAAS,MAAM;CAAE;AACvG;;;;;AAMA,SAAS,iBAAiB,OAAsD;CAC/E,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAS,QAAQ,MAAM,WAAY,MAAM,YAAY;CAC3D,OAAO;EACN,QAAQ,WAAW,IAAI,KAAA,IAAY;EACnC,OAAQ,OAAO,SAAS,MAAM,QAAS,OAAO,KAAA;EAC9C,OAAQ,OAAO,SAAS,MAAM,QAAS,OAAO,KAAA;CAC/C;AACD;;;;;;;;;AAUA,SAAS,WAAW,OAAiB,OAAkB,QAA4C;CAClG,MAAM,WAAW,MAAM;CACvB,IAAI,UAAU;EACb,MAAM,QAAQ,cAAc,UAAU,OAAO,MAAM;EACnD,IAAI,OAAO,OAAO;GAAE,MAAM;GAAY,UAAU;EAAM;CACvD;CAEA,MAAM,UAAU,cAAc,MAAM,WAAW;CAC/C,IAAI,SAAS,OAAO;CAMpB,MAAM,UAAU,MAAM;CACtB,IAAI,SAAS,OAAO,kBAAkB,SAAS,QAAQ,OAAO,kBAAkB;CAEhF,MAAM,SAAS,MAAM;CACrB,IAAI,sBAAsB,MAAM,GAAG,OAAO,EAAE,OAAO,OAAiB;CACpE,IAAI,MAAM,cAAc,MAAM,OAAO,EAAE,OAAO,aAAa,MAAM,SAAS,EAAE;CAE5E,MAAM,WAAW,MAAM;CACvB,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,IAAI,WAAW,MACd,MAAM,KACL,oBACA,gBACA,cACA,uBAAuB,OAAO,8GAC/B;CAED,OAAO,QAAQ;EACd,OAAO,aAAa,SAAS,YAAY;EACzC,cAAc,oBAAoB,SAAS,KAAK;CACjD,CAAC;AACF;;;;;;;;;;AAWA,SAAS,WAAW,OAAiB,OAAuD;CAC3F,IAAI,MAAM,YAAY,OAAO,EAAE,MAAM,OAAO;CAE5C,MAAM,WAAW,MAAM;CACvB,IAAI,UAAU;EACb,MAAM,QAAQ,cAAc,UAAU,OAAO,MAAM;EACnD,IAAI,OAAO,OAAO;GAAE,MAAM;GAAY,UAAU;EAAM;CACvD;CAEA,MAAM,UAAU,MAAM;CACtB,MAAM,OAAO,MAAM;CACnB,MAAM,MAAM,MAAM;CAClB,MAAM,SAAS,MAAM;CACrB,MAAM,WAAW,MAAM;CAEvB,IAAI;CACJ,IAAI,sBAAsB,MAAM,GAAG,QAAQ;MACtC,IAAI,MAAM,cAAc,MAAM,QAAQ,aAAa,MAAM,SAAS;MAClE,IAAI,UAAU,QAAQ,aAAa,SAAS,YAAY;CAI7D,IAAI,aAAa,QAAQ,MAAM,cAAc,QAAQ,WAAW,QAAQ,YAAY,MACnF,MAAM,KACL,cACA,WACA,UACA,gLACD;CAED,IAAI,SAAS,QAAQ,CAAC,gBAAgB,IAAI,IAAI,GAC7C,MAAM,KACL,aACA,gBACA,cACA,eAAe,KAAK,iFACrB;CAOD,IAAI,MAAM,cAAc,MACvB,MAAM,KACL,cACA,WACA,cACA,4LACD;CAWD,OARgB,QAAQ;EACvB;EACA,OAAO,YAAY,OAAO;EAC1B,UAAU,SAAS,QAAQ,gBAAgB,IAAI,IAAI,IAAI,OAAO,KAAA;EAC9D,KAAK,QAAQ,OAAO,KAAA,IAAY,WAAW;EAC3C,cAAc,oBAAoB,UAAU,KAAK;EACjD,GAAG,aAAa,OAAO,KAAK;CAC7B,CACa;AACd;;AAGA,SAAS,aAAa,OAAiB,OAAuD;CAC7F,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM,OAAO,CAAC;CAEnB,IADc,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,QAAQ,QAAQ,IAAI,UAAU,QAAQ,IAAI,WAAW,KACxF,GACP,MAAM,KACL,kBACA,WACA,cACA,mHACD;CAED,OAAO;EACN,gBAAgB,KAAK,QAAQ,gBAAgB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,OAAO,KAAA;EACpF,cAAc,KAAK,QAAQ,gBAAgB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,OAAO,KAAA;CACnF;AACD;;AAGA,SAAS,aAAa,OAAiB,OAAuC;CAC7E,IAAI,MAAM,cAAc,MAAM,UAC7B,MAAM,KACL,iBACA,WACA,cACA,+FACD;CAGD,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAS,SAAS,MAAM;CAC9B,IAAI,CAAC,QAAQ,OAAO,KAAA;CAEpB,OAAO,QAAQ;EACd,MAAM,QAAQ,UAAU;EACxB,OAAO,OAAO,UAAU,OAAO,KAAA,IAAY,aAAa,OAAO,KAAK;EACpE,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,OAAO,OAAO;EACd,cAAc,oBAAoB,OAAO,KAAK;CAC/C,CAAC;AACF;;AAGA,SAAS,WAAW,OAAsC;CACzD,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,OAAO,QAAQ;EACd,MAAM,KAAK;EACX,OAAO,KAAK,UAAU,OAAO,KAAA,IAAY,aAAa,KAAK,KAAK;EAChE,SAAS,KAAK;CACf,CAAC;AACF;;AAGA,SAAS,aAAa,OAAiB,OAAkB,QAA4D;CACpH,OAAO;EACN,MAAM,WAAW,OAAO,OAAO,MAAM;EACrC,MAAM,WAAW,OAAO,KAAK;EAC7B,QAAQ,aAAa,OAAO,KAAK;EACjC,MAAM,WAAW,KAAK;CACvB;AACD;;;;;;AASA,SAAS,cAAc,OAAkB,OAAkB,QAAsC;CAChG,MAAM,SAAS,MAAM;CACrB,MAAM,SAAS,MAAM;CACrB,MAAM,QAAQ,MAAM,eAAe,MAAM,YAAY;CAMrD,MAAM,UAAU,UAAU,OAAO,KAAK,MAAM,WAAW,SAAS,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;CAC5G,MAAM,UAAU,QAAQ,SAAS;CAGjC,IAAI,UAAU,QAAQ,MAAM,KAAK,WAAW,MAAM,EAAE,CAAC,CAAC,SAAS,QAAQ,QACtE,MAAM,KACL,cACA,WACA,UACA,8JACD;CAKD,IAAI,UAAU,QAAQ,YAAY,MAAM,QAAQ,GAC/C,MAAM,KACL,iBACA,WACA,UACA,+KACD;CAGD,IAAI,MAAM,aACT,MAAM,KACL,qBACA,aACA,eACA,gIACD;CAGD,MAAM,SAAS;EACd,GAAG,gBAAgB,OAAO,KAAK;EAC/B,GAAG,iBAAiB,KAAK;EACzB,GAAG,aAAa,OAAO,OAAO,MAAM;EACpC,YAAY,MAAM,QAAQ,KAAA;CAC3B;CAEA,IAAI,QAAQ;EACX,MAAM,KACL,yBACA,WACA,UACA,wIACD;EAEA,OAAO;GAAE,QAAQ;GAAY,MAAM,CAAC,YADpB,QAAQ;IAAE,GAAG;IAAQ,QAAQ,qBAAqB,OAAO,MAAM;GAAE,CAC3B,KAAK,CAAC,CAAC;GAAG,GAAG,OAAO,KAAK;EAAE;CAClF;CAEA,IAAI,WAAW,UAAU,MAAM;EAI9B,MAAM,UAAU,QAAQ;GACvB,GAAG;GACH,GAAG,iBAAiB,OAAO,KAAK;GAChC,GAAI,UAAU,MAAM,QAAQ,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;GACvD,GAAI,WAAW,OAAO,CAAC,IAAI;IAAE,OAAO;IAAQ,GAAG,cAAc,KAAK;GAAE;EACrE,CAAC;EACD,OAAO;GAAE,QAAQ;GAAW,MAAM,CAAC,SAAS,OAAO,KAAK,GAAG,WAAW,CAAC,CAAC;GAAG,GAAG,OAAO,KAAK;EAAE;CAC7F;CAOA,IAAI,WAAW,MAAM;EACpB,MAAM,KACL,eACA,WACA,eACA,+KACD;EACA,OAAO;CACR;CAEA,OAAO;EAAE,QAAQ;EAAY,MAAM,CAAC,QADpB,QAAQ;GAAE,GAAG;GAAQ,GAAG,cAAc,KAAK;EAAE,CACX,KAAK,CAAC,CAAC;EAAG,GAAG,OAAO,KAAK;CAAE;AAC9E;;;;;;;;;AAUA,SAAS,cAAc,OAAuD;CAC7E,MAAM,SAAS,MAAM;CACrB,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,GAAG;EAC9C,MAAM,QAAQ,kBAAkB,MAAM,OAAO,SAAS,GAAA,CAAI,KAAK,CAAC;EAChE,IAAI,CAAC,QAAQ,IAAI;EACjB,OAAO,KAAK;GAAE;GAAM,OAAO,OAAO,MAAM,EAAE,IAAI;EAAc,CAAC;CAC9D;CACA,OAAO,OAAO,SAAS,EAAE,aAAa,OAAO,IAAI,CAAC;AACnD;;;;;;;;AASA,SAAS,qBAAqB,OAAkB,QAAiC;CAChF,MAAM,QAAQ,MAAM;CACpB,MAAM,SAAoB,CAAC;CAE3B,KAAK,MAAM,QAAQ,OAAO,OAAO;EAChC,MAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,MAAM,QAAQ,KAAK,IAAI;EACxD,MAAM,KAAK,KAAK,IAAI,KAAK,QAAQ,MAAM,SAAS,KAAK,IAAI;EACzD,MAAM,MAAM,MAAsB,IAAI,IAAI,EAAE;EAC5C,MAAM,MAAM,MAAsB,IAAI,IAAI,EAAE;EAE5C,KAAK,MAAM,WAAW,KAAK,UAC1B,QAAQ,QAAQ,KAAhB;GACC,KAAK;IACJ,OAAO,KAAK;KAAE,GAAG,GAAG,QAAQ,CAAC;KAAG,GAAG,GAAG,QAAQ,CAAC;KAAG,QAAQ;IAAK,CAAC;IAChE;GACD,KAAK;IACJ,OAAO,KAAK;KAAE,GAAG,GAAG,QAAQ,CAAC;KAAG,GAAG,GAAG,QAAQ,CAAC;IAAE,CAAC;IAClD;GACD,KAAK;IACJ,OAAO,KAAK;KACX,GAAG,GAAG,QAAQ,CAAC;KACf,GAAG,GAAG,QAAQ,CAAC;KACf,OAAO;MAAE,MAAM;MAAS,IAAI,GAAG,QAAQ,EAAE;MAAG,IAAI,GAAG,QAAQ,EAAE;MAAG,IAAI,GAAG,QAAQ,EAAE;MAAG,IAAI,GAAG,QAAQ,EAAE;KAAE;IACxG,CAAC;IACD;GACD,KAAK;IACJ,OAAO,KAAK;KACX,GAAG,GAAG,QAAQ,CAAC;KACf,GAAG,GAAG,QAAQ,CAAC;KACf,OAAO;MAAE,MAAM;MAAa,IAAI,GAAG,QAAQ,EAAE;MAAG,IAAI,GAAG,QAAQ,EAAE;KAAE;IACpE,CAAC;IACD;GACD,KAAK;IAGJ,OAAO,KAAK,EACX,OAAO;KAAE,MAAM;KAAO,IAAI,GAAG,QAAQ,EAAE;KAAG,IAAI,GAAG,QAAQ,EAAE;KAAG,OAAO,QAAQ;KAAO,OAAO,QAAQ;IAAM,EAC1G,CAAC;IACD;GACD,KAAK,SACJ,OAAO,KAAK,EAAE,OAAO,KAAK,CAAC;EAE7B;CAEF;CACA,OAAO;AACR;;;;;;;;;;;AAYA,SAAS,YAAY,OAAgB,OAAkB,QAAsC;CAC5F,IAAI,aAAa,MAAM,QAAQ,GAC9B,MAAM,KACL,oBACA,aACA,UACA,gLACD;CAOD,MAAM,WAAW,MAAM,eAAe,MAAM;CAC5C,IAAI,CAAC,UAAU;EACd,MAAM,KACL,cACA,WACA,eACA,8GACD;EACA,OAAO;CACR;CACA,MAAM,QAAQ,OAAO,SAAS,QAAQ;CACtC,IAAI,CAAC,OAAO;EACX,MAAM,KAAK,cAAc,WAAW,eAAe,cAAc,SAAS,+BAA+B;EACzG,OAAO;CACR;CAEA,IAAI,MAAM,eAAe,MAAM,eAC9B,MAAM,KACL,aACA,gBACA,eACA,wOACD;CAED,IAAI,MAAM,SACT,MAAM,KACL,iBACA,WACA,cACA,8FACD;CAGD,MAAM,OAAO,MAAM;CAanB,OAAO;EAAE,QAAQ;EAAY,MAAM,CAAC;GAAE,GAZtB,QAAQ;IACvB,GAAG,gBAAgB,OAAO,KAAK;IAC/B,GAAG,iBAAiB,KAAK;IACzB,YAAY,MAAM,QAAQ,KAAA;IAM1B,MACC,SAAS,OAAO,KAAA,IAAY;KAAE,GAAG,KAAK,OAAO;KAAK,GAAG,KAAK,MAAM;KAAK,GAAG,KAAK,QAAQ;KAAK,GAAG,KAAK,SAAS;IAAI;GACjH,CAC+C;GAAG,MAAM;EAAM,CAAC;EAAG,GAAG,OAAO,KAAK;CAAE;AACpF;;;;;;;;AASA,MAAM,sBAAsB;CAAC;CAAS;CAAS;CAAY;CAAkB;AAAc;;;;;;;;;;;;AAa3F,SAAS,cAAc,OAAkB,OAAiC;CACzE,MAAM,QAAQ,MAAM;CACpB,IAAI,CAAC,OAAO,OAAO;CAEnB,IAAI,MAAM,mBAAmB,MAAM,eAClC,MAAM,KACL,qBACA,WACA,eACA,2JACD;CAED,IAAI,MAAM,UACT,MAAM,KACL,sBACA,WACA,cACA,wHACD;CAGD,MAAM,OAAO,WAAW,OAAO,KAAK,KAAK,CAAC;CAC1C,MAAM,SAAkC,CAAC;CACzC,KAAK,MAAM,OAAO,qBAAqB;EACtC,MAAM,QAAQ,KAAK;EACnB,IAAI,UAAU,KAAA,GAAW,OAAO,OAAO;CACxC;CACA,IAAI,KAAK,YAAY,cAAc,KAAK,oBAAoB,KAAA,GAC3D,MAAM,KACL,kBACA,aACA,cACA,mKACD;CAGD,MAAM,QAAQ,MAAM,OAAO,MAAM;CACjC,MAAM,SAAS,MAAM,MAAM,MAAM;CACjC,OAAO;EACN,QAAQ;EACR,MAAM,CACL,QAAQ;GAGP,MAAM;GACN,IAAI,IAAI,MAAM,QAAQ,QAAQ,MAAM,IAAI;GACxC,IAAI,IAAI,MAAM,QAAQ,SAAS,MAAM,GAAG;GACxC,IAAI,IAAI,MAAM,QAAQ,MAAM,OAAO,KAAK;GACxC,IAAI,IAAI,MAAM,QAAQ,MAAM,MAAM,MAAM;GACxC,YAAY,MAAM,QAAQ,KAAA;GAC1B,GAAG;EACJ,CAAC,KAAK,CAAC,CACR;EACA,GAAG,OAAO,KAAK;CAChB;AACD;;;;;;;;;;;;AAaA,SAAgB,uBAAuB,OAA+D;CACrG,IAAI,MAAM,SAAS,MAAM,OAAO,OAAO;CACvC,IAAI,MAAM,YAAY,OAAO;CAC7B,IAAI,MAAM,YAAY,OAAO;CAC7B,OAAO;AACR;;AAGA,SAAS,iBAAiB,OAAqB,OAAkB,QAAsC;CACtG,MAAM,QAAQ,MAAM;CACpB,IAAI,OAAO,OAAO,UAAU,OAAO,OAAO,OAAO,MAAM;CAEvD,MAAM,QAAQ,MAAM;CACpB,IAAI,OAAO,OAAO,UAAU,OAAO,OAAO,KAAK;CAK/C,QAAQ,uBAAuB,KAAK,GAApC;EACC,KAAK;GACJ,MAAM,KACL,eACA,WACA,cACA,0GACD;GACA,OAAO;EACR,KAAK;GAIJ,MAAM,KACL,eACA,WACA,cACA,uMACD;GACA,OAAO;EACR;GACC,MAAM,KACL,wBACA,WACA,UACA,oJACD;GACA,OAAO;CACT;AACD;;;;;;;;;;;;;;;AAgBA,SAAS,UAAU,OAAmB,OAAkB,QAAsC;CAC7F,MAAM,WAAsB,CAAC;CAC7B,KAAK,MAAM,SAAS,MAAM,QAAQ;EACjC,MAAM,OAAO,UAAU,OAAO,OAAO,MAAM;EAC3C,IAAI,CAAC,MAAM;EACX,MAAM,SAAS,aAAa,IAAI;EAChC,IAAI,CAAC,QAAQ;GACZ,MAAM,KACL,eACA,WACA,eACA,uBAAuB,KAAK,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAAC,YAAY,EAAE,kGACtE;GACA;EACD;EACA,SAAS,KAAK,MAAM;CACrB;CACA,IAAI,SAAS,WAAW,GAAG;EAC1B,MAAM,KACL,eACA,WACA,eACA,sHACD;EACA,OAAO;CACR;CAEA,IAAI,CAAC,sBAAsB,MAAM,QAAQ,GACxC,MAAM,KACL,oBACA,aACA,eACA,oNACD;CASD,IAAI,MAAM,aAAa,KAAK,MAAM,SAAS,MAAM,OAChD,MAAM,KACL,mBACA,aACA,eACA,gQACD;CAGD,OAAO;EACN,QAAQ;EACR,MAAM,CAAC,UAAU,QAAQ;GAAE,GAAG,gBAAgB,OAAO,KAAK;GAAG,YAAY,MAAM,QAAQ,KAAA;EAAU,CAAC,KAAK,CAAC,CAAC;EACzG,GAAG,OAAO,KAAK;CAChB;AACD;;;;;AAMA,SAAS,aAAa,MAA8B;CACnD,MAAM,SAAS,mBAAmB,IAAI;CACtC,IAAI,QAAQ,OAAO;CACnB,MAAM,CAAC,OAAO,UAAU,KAAK;CAC7B,QAAQ,KAAK,QAAb;EACC,KAAK,YACJ,OAAO,EAAE,OAAO,QAAQ;GAAE,UAAU;GAAO,SAAS;EAAO,CAAC,KAAK,CAAC,EAAE;EACrE,SAEC,OAAO;CACT;AACD;;;;;;;;;;;AAYA,SAAS,mBAAmB,MAA8B;CACzD,MAAM,CAAC,OAAO,UAAU,KAAK;CAC7B,QAAQ,KAAK,QAAb;EACC,KAAK,WACJ,OAAO,EAAE,MAAM,QAAQ;GAAE,MAAM;GAAO,SAAS;EAAO,CAAC,KAAK,CAAC,EAAE;EAChE,KAAK,YACJ,OAAO,EAAE,OAAO,QAAQ;GAAE,MAAM;GAAO,SAAS;EAAO,CAAC,KAAK,CAAC,EAAE;EACjE,KAAK,YACJ,OAAO,EAAE,OAAO,SAAS,CAAC,EAAE;EAC7B,SACC,OAAO;CACT;AACD;;AAGA,SAAS,OAAO,OAA0C;CACzD,OAAO,MAAM,OAAO,EAAE,YAAY,MAAM,KAAK,IAAI,CAAC;AACnD;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,aAAa,OAAiB,OAAkB,QAAuC;CAEtG,IAAI,YAAY,KAAK,GAAG;EACvB,MAAM,SAAS,MAAM,SAAS,MAAM,QAAQ,IAAI;EAChD,IAAI,MAAM,QAAQ;GACjB,WAAW,MAAM;GACjB,OAAO;EACR;EACA,OAAO,gBAAgB,OAAO,MAAM;CACrC;CAEA,MAAM,OAAO,UAAU,OAAO,OAAO,MAAM;CAC3C,IAAI,CAAC,MAAM,OAAO;CAElB,MAAM,SAAS,mBAAmB,IAAI;CACtC,IAAI,QAAQ,OAAO;CAEnB,MAAM,CAAC,OAAO,UAAU,KAAK;CAC7B,QAAQ,KAAK,QAAb;EACC,KAAK,YAAY;GAKhB,MAAM,UAAU,WAAW,QAAQ,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC,WAAW,MAAM,IAAI,SAAS;GAC1H,MAAM,OAAO,UAAU;GACvB,IAAI,SAAS,KAAA,KAAa,UAAU,KAAA,GAAW,OAAO;GACtD,OAAO,EAAE,OAAO,QAAQ;IAAE;IAAM,MAAM;IAAO,MAAM;GAAQ,CAAC,KAAK,CAAC,EAAE;EACrE;EACA;GACC,MACE,SAAS,MAAM,QAAQ,IAAI,CAAC,CAC5B,KACA,cACA,WACA,cACA,KAAK,KAAK,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAAC,YAAY,EAAE,qLACpD;GACD,OAAO;CACT;AACD;;;;;;;;;;;;;;;;;AAkBA,SAAS,gBAAgB,OAAkB,OAAkC;CAC5E,IAAI,CAAC,MAAM,eAAe,OAAO;CAEjC,IAAI,MAAM,mBAAmB,MAAM,eAClC,MAAM,KACL,qBACA,WACA,eACA,6IACD;CAgBD,OAAO,EAAE,OAAO,QAAQ;EAAE,MAAM;EAAQ,SAVxB,QAAQ;GACvB,GAAG,gBAAgB,OAAO,KAAK;GAC/B,GAAG,iBAAiB,KAAK;GACzB,MAAM,WAAW,OAAO,KAAK;GAC7B,QAAQ,aAAa,OAAO,KAAK;GACjC,MAAM,WAAW,KAAK;GACtB,YAAY,MAAM,QAAQ,KAAA;EAC3B,CAGiD,KAAW,CAAC;CAAE,CAAC,KAAK,CAAC,EAAE;AACzE;;;;ACr5BA,SAAgB,WAAW,MAAoB,OAAkB,QAAiC;CACjG,MAAM,UAAU,KAAK,QAAQ;CAE7B,IAAI,QAAQ,SAAS,GACpB,MAAM,KACL,mBACA,aACA,eACA,iBAAiB,QAAQ,OAAO,8LACjC;CAID,MAAM,QADQ,QAAQ,EACH,EAAE,SAAS;CAC9B,mBAAmB,SAAS,OAAO,KAAK;CAExC,OAAO;EAAE,OAAO,UAAU,KAAK;EAAG,SAAS,YAAY,SAAS,OAAO,MAAM;CAAE;AAChF;;AAGA,SAAS,UAAU,OAA8B;CAChD,IAAI,CAAC,OAAO,OAAO,CAAC;CAEpB,MAAM,SAAS,MAAM;CACrB,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,MAAM,GAC9C,IAAI,QAAQ,MAAM,OAAO,QAAQ,aAAa,GAAG;CAGlD,MAAM,QAAQ,MAAM;CACpB,OAAO,QAAQ;EACd,cAAc,YAAY,OAAO,MAAM,SAAS,IAAI;EACpD,cAAc,YAAY,OAAO,MAAM,SAAS,IAAI;EACpD,gBAAgB,YAAY,OAAO,MAAM,MAAM,IAAI;EACnD,gBAAgB,YAAY,OAAO,MAAM,MAAM,IAAI;EACnD,gBAAgB,YAAY,OAAO,MAAM,MAAM,IAAI;EACnD,gBAAgB,YAAY,OAAO,MAAM,MAAM,IAAI;EACnD,aAAa,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA;CACxD,CAAC;AACF;;AAGA,SAAS,mBAAmB,SAAwB,OAAqB,OAAwB;CAChG,IAAI,SAAS,gBAAgB,MAAM,QAAQ,GAC1C,MAAM,KACL,mBACA,gBACA,UACA,+UACD;CAGD,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,OAAO,OAAO,KAAK,IAAI;EAC7B,IAAI,cAAc,IAAI,GACrB,MAAM,KACL,mBACA,WACA,UACA,kSACD;EAED,IAAI,oBAAoB,IAAI,GAC3B,MAAM,KACL,qBACA,WACA,cACA,6VACD;EAGD,MAAM,MAAM,OAAO;EACnB,MAAM,WAAW,OAAO,QAAQ,iBAAiB,CAAC,CAAC,QACjD,CAAC,OAAO,UAAU,IAAI,WAA+B,IACvD;EACA,IAAI,SAAS,SAAS,GACrB,MAAM,KACL,mBACA,WACA,cACA,sBAAsB,SAAS,KAAK,CAAC,WAAW,KAAK,CAAC,CAAC,KAAK,IAAI,EAAE,yLACnE;CAEF;AACD;;;;;;;;;;AAWA,SAAS,YAAY,SAAwB,OAAkB,QAAmC;CACjG,MAAM,MAAkB,CAAC;CACzB,MAAM,uBAAO,IAAI,IAAY;CAI7B,IAAI,mBAAmB;CACvB,IAAI,qBAAqB;CAEzB,MAAM,UAAoB,CAAC;CAC3B,MAAM,WAAqB,CAAC;CAE5B,KAAK,MAAM,UAAU,SACpB,KAAK,MAAM,UAAU,OAAO,SAAS;EACpC,MAAM,QAAQ,IAAI;EAClB,MAAM,YAAY,sBAAsB,OAAO,IAAI;EACnD,IAAI,cAAc,OAAO,MAAM,QAAQ,KAAK,GAAG,KAAK,UAAU,OAAO,IAAI,EAAE,KAAK,KAAK,UAAU,SAAS,GAAG;EAC3G,MAAM,OAAO,aAAa,UAAU,QAAQ;EAC5C,IAAI,QAAQ;EACZ,KAAK,IAAI,SAAS,GAAG,KAAK,IAAI,KAAK,GAAG,UAAU,QAAQ,GAAG,KAAK,IAAI,OAAO;EAC3E,IAAI,UAAU,MAAM,SAAS,KAAK,GAAG,KAAK,UAAU,IAAI,EAAE,KAAK,KAAK,UAAU,KAAK,GAAG;EACtF,KAAK,IAAI,KAAK;EAEd,MAAM,eAAe,OAAO,aAAa;EACzC,IAAI,eAAe,GAAG;GACrB,oBAAoB;GACpB;EACD;EAIA,MAAM,aAAa,gBAAgB,OAAO,cAAc,OAAO,YAAY,OAAO,MAAM;EACxF,MAAM,UAAU,cAAc,QAAQ,OAAO,MAAM;EACnD,IAAI,KAAK;GACR,aAAa;GACb,OAAO,QAAQ;IACd;IACA;IACA,SAAS,QAAQ,SAAS,IAAI,UAAU,KAAA;GACzC,CAAC;EACF,CAAC;CACF;CAGD,IAAI,SAAS,SAAS,GACrB,MAAM,KACL,wBACA,gBACA,eACA,GAAG,SAAS,OAAO,sTAAsT,SAAS,KAAK,IAAI,GAC5V;CAED,IAAI,QAAQ,SAAS,GACpB,MAAM,KACL,eACA,aACA,cACA,GAAG,QAAQ,OAAO,2TAA2T,QAAQ,KAAK,IAAI,GAC/V;CAED,IAAI,mBAAmB,GACtB,MAAM,KACL,uBACA,WACA,eACA,OAAO,iBAAiB,oCAAoC,mBAAmB,gTAChF;CAGD,OAAO;AACR;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAS,cAAc,QAAqB,OAAkB,QAAkC;CAC/F,MAAM,MAAiB,CAAC;CACxB,eAAe,OAAO,QAAQ,KAAK,iBAAiB,KAAK,GAAG,MAAM;CAClE,OAAO;AACR;;AAGA,SAAS,eAAe,QAAoB,KAAgB,OAAkB,QAA6B;CAC1G,KAAK,MAAM,SAAS,QAAQ;EAC3B,IAAI,mBAAmB,MAAM,QAAQ,GAAG;EAExC,IAAI,aAAa,KAAK,GAAG;GACxB,MACE,SAAS,MAAM,QAAQ,IAAI,CAAC,CAC5B,KACA,SACA,aACA,cACA,mTACD;GACD,eAAe,MAAM,QAAQ,KAAK,OAAO,MAAM;GAC/C;EACD;EAIA,MAAM,SAAS,aAAa,OAAO,OAAO,MAAM;EAChD,IAAI,WAAW,MAAM,IAAI,KAAK,MAAM;CACrC;AACD;;;;;;;;;;;;AAaA,SAAS,sBAAsB,OAAuB;CACrD,OAAO,MAAM,QAAQ,cAAc,GAAG;AACvC;;AAGA,SAAS,gBACR,YACA,OACA,QACsB;CACtB,IAAI,CAAC,cAAc,WAAW,SAAS,QAAQ,OAAO,KAAA;CAEtD,QAAQ,WAAW,MAAnB;EACC,KAAK,SACJ,OAAO,WAAW,QAAQ,EAAE,OAAO,aAAa,WAAW,MAAM,YAAY,EAAE,IAAI,KAAA;EACpF,KAAK,SAAS;GACb,MAAM,QAAQ,WAAW,aAAa,OAAO,OAAO,OAAO,SAAS,WAAW,QAAQ;GACvF,OAAO,QAAQ,EAAE,MAAM,MAAM,IAAI,KAAA;EAClC;EACA,KAAK,YAAY;GAIhB,MAAM,OAAO,WAAW;GACxB,IAAI,MAAM,SAAS,WAAW,KAAK,OAAO;IACzC,MAAM,KACL,qBACA,aACA,cACA,6MACD;IACA,OAAO,EAAE,OAAO,aAAa,KAAK,MAAM,YAAY,EAAE;GACvD;GACA,MAAM,KACL,qBACA,WACA,cACA,4IACD;GACA;EACD;EACA;GACC,MAAM,KACL,qBACA,WACA,eACA,KAAK,WAAW,KAAK,6HACtB;GACA;CACF;AACD;;;;;;;;;;;;ACnSA,MAAM,iBAA+C;CACpD,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,MAAM;CACN,OAAO;CACP,KAAK;CACL,SAAS;CACT,UAAU;CACV,MAAM;CACN,WAAW;CACX,MAAM;CACN,MAAM;CACN,MAAM;CACN,QAAQ;CACR,WAAW;CACX,OAAO;CACP,QAAQ;CACR,OAAO;CACP,OAAO;CACP,MAAM;CACN,MAAM;AACP;;;;;;;;;;;;;;AAeA,SAAS,WAAW,MAA+B;CAClD,OAAO,KAAK,cAAc,OAAO,OAAO,OAAO,gBAAgB,KAAK,IAAI;AACzE;;;;;;;AAQA,SAAgB,eAAe,OAAc,OAAkB,QAAiD;CAC/G,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM,OAAO,KAAA;CAElB,IAAI,CAAC,WAAW,IAAI,GAAG;EACtB,MAAM,KACL,oBACA,WACA,cACA,gBAAgB,KAAK,cAAc,MAAM,KAAK,GAAG,KAAK,UAAU,KAAK,KAAK,KAAK,qFAC9E,KAAK,cAAc,MAAM,KAAK,kFAC9B,mDACF;EACA;CACD;CAIA,MAAM,QAAQ,UAAU,OAAO,MAAM,OAAO,MAAM;CAClD,OAAO;EACN,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,GAAI,KAAK,eAAe,OAAO,CAAC,IAAI,EAAE,YAAY,KAAK,WAAW;EAGlE,GAAI,KAAK,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,MAAM;EACvD,GAAI,KAAK,mBAAmB,OAAO,CAAC,IAAI,EAAE,gBAAgB,KAAK,eAAe;EAC9E,GAAI,OAAO,KAAK,KAAK,OAAO,CAAC,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,QAAQ,EAAE,IAAI,CAAC;EAC/E,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC1B;AACD;;;;;;;;;;AAWA,SAAS,UACR,OACA,MACA,OACA,QACgC;CAChC,MAAM,QAAQ,KAAK;CACnB,IAAI,CAAC,OAAO,OAAO,KAAA;CACnB,IAAI,MAAM,SAAS,QAAQ,OAAO,EAAE,cAAc,KAAK;CAEvD,MAAM,WAAW,cAAc,OAAO,MAAM,QAAQ;CACpD,MAAM,QAAQ,aAAa,OAAO,OAAO,OAAO,SAAS,QAAQ;CACjE,IAAI,CAAC,OAAO;EACX,MAAM,KACL,yBACA,WACA,eACA,kCAAkC,MAAM,YAAY,aAAa,4FAClE;EACA;CACD;CAEA,OAAO;EACN,MAAM;EACN,GAAI,MAAM,SAAS,OAAO,CAAC,IAAI,EAAE,MAAM,MAAM,KAAK;EAElD,GAAI,MAAM,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AACD;;AAGA,SAAS,cAAc,OAAc,UAAwC;CAC5E,IAAI,CAAC,UAAU,OAAO;CACtB,MAAM,eAAe,MAAM,cAAc,IAAI,QAAQ;CAGrD,IAAI,CAAC,gBAAgB,aAAa,eAAe,YAAY,OAAO;CACpE,OAAO,MAAM,cAAc,cAAc,QAAQ;AAClD;;;;AC3IA,MAAM,qBAAqB;CAAE,UAAU;CAAS,WAAW;AAAQ;;AAGnE,MAAM,mBAA2C;CAChD,aAAa;CACb,cAAc;CACd,aAAa;CACb,aAAa;CACb,cAAc;CACd,cAAc;CACd,eAAe;CACf,eAAe;CACf,iBAAiB;CAGjB,eAAe;CACf,aAAa;CACb,cAAc;AACf;;;;;;;;;;;;;AAcA,IAAM,SAAN,MAAsC;CAKR;CAJ7B,8BAAuB,IAAI,IAAsB;CACjD,UAA8B,CAAC;CAC/B,0BAAmB,IAAI,IAAoB;CAE3C,YAAY,MAAqC;EAApB,KAAA,OAAA;CAAqB;CAElD,SAAS,UAAmC;EAC3C,MAAM,WAAW,KAAKC,YAAY,IAAI,QAAQ;EAC9C,IAAI,UAAU,OAAO;EAErB,MAAM,OAAO,KAAK,KAAK,IAAI,KAAK,QAAQ;EACxC,IAAI,CAAC,MAAM,OAAO;EAElB,MAAM,YAAY,iBAAiB,KAAK,gBAAgB,SAAS,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;EACrF,MAAM,OAAO,KAAK,YAAY,WAAW,QAAQ,IAAI,UAAU;EAC/D,MAAM,SAAS,KAAKE,QAAQ,IAAI,IAAI,KAAK,KAAK;EAC9C,KAAKA,QAAQ,IAAI,MAAM,KAAK;EAC5B,MAAM,OAAO,GAAG,OAAO,MAAM,GAAG;EAChC,MAAM,MAAgB,EAAE,QAAQ,KAAK;EACrC,KAAKF,YAAY,IAAI,UAAU,GAAG;EAClC,KAAKC,QAAQ,KAAK;GAAE;GAAM,aAAa,KAAK;GAAa,OAAO,KAAK;EAAM,CAAC;EAC5E,OAAO;CACR;CAEA,cAAc,UAAiC;EAC9C,OAAO,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC,EAAE,eAAe;CACrD;CAEA,IAAI,SAAoB;EACvB,OAAO,KAAKA;CACb;AACD;;AAGA,SAAgB,cAAc,MAA4B;CACzD,MAAM,YAAY,IAAI,cAAc;CACpC,MAAM,SAAS,IAAI,OAAO,IAAI;CAC9B,MAAM,OAAO,KAAK;CAClB,MAAM,YAAY,WAAW,WAAW,IAAI;CAE5C,IAAI,CAAC,MACJ,UAAU,KACT,kBACA,gBACA,eACA,4DAA4D,mBAAmB,WAAW,OAAO,OAAO,mBAAmB,YAAY,OAAO,WAC/I;CAGD,MAAM,UAAU,cAAc,IAAI;CAIlC,MAAM,SAAS,WAAW,MAAM,WAAW,MAAM;CACjD,MAAM,SAAS,KAAK,OAAO,KAAK,OAAO,UAAU,UAAU,OAAO,QAAQ,GAAG,WAAW,QAAQ,OAAO,CAAC;CAExG,OAAO;EACN,WAAW,OAAO;GAAE,UAAU,KAAK;GAAU,WAAW,KAAK;EAAU,IAAI;EAC3E,OAAO,UAAU,MAAM,SAAS;EAChC;EACA;EACA,QAAQ,OAAO;EACf,UAAU,UAAU;CACrB;AACD;;;;;;;AAQA,SAAS,UAAU,MAAoB,OAA+B;CACrE,MAAM,OAAO,KAAK;CAElB,IAAI;EADa;EAAY;EAAe;EAAY;EAAiB;CAC/D,CAAC,CAAC,MAAM,QAAQ,KAAK,SAAS,KAAA,CAAS,GAChD,MAAM,KACL,iBACA,WACA,cACA,0JACD;CAED,OACC,QAAQ;EACP,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,SAAS,KAAK;EACd,UAAU,KAAK;CAChB,CAAC,KAAK,CAAC;AAET;;;;;;;;;AAUA,SAAS,cAAc,MAAgD;CACtE,MAAM,UAAU,KAAK,QAAQ;CAC7B,MAAM,6BAAa,IAAI,IAAoB;CAC3C,KAAK,MAAM,UAAU,SAAS,WAAW,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,IAAI,KAAK,KAAK,CAAC;CAEhG,OAAO,IAAI,IACV,QAAQ,KAAK,QAAQ,UAAU,CAC9B,OAAO,UACP;EAAE,MAAM,OAAO;EAAM;EAAO,eAAe,WAAW,IAAI,OAAO,IAAI,KAAK,OAAO;CAAE,CACpF,CAAC,CACF;AACD;AAEA,SAAS,UACR,OACA,QACA,WACA,QACA,SACU;CACV,MAAM,QAAQ,WAAW,WAAW,MAAM;CAC1C,MAAM,iBAAiB,MAAM,QAAQ;CACrC,MAAM,OAAO;EACZ;EACA,SAAS,mBAAmB,KAAA,IAAY,KAAA,IAAY,QAAQ,IAAI,cAAc,MAAM;EACpF,QAAQ,MAAM;EACd,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;EACzC,GAAG,aAAa,OAAO,KAAK;EAC5B,GAAG,QAAQ,OAAO,KAAK;CACxB;CAEA,MAAM,aAAa,eAAe,OAAO,OAAO,MAAM;CACtD,MAAM,UAAU,qBAAqB,KAAK;CAC1C,IAAI,SACH,MAAM,KACL,iBACA,aACA,cACA,iWACD;CAMD,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,SAAS,MAAM,QAAQ;EACjC,MAAM,OAAO,UAAU,OAAO,OAAO,MAAM;EAC3C,IAAI,MAAM,MAAM,KAAK,IAAI;CAC1B;CAIA,oBAAoB,OAAO,KAAK;CAEhC,OAAO;EACN,GAAG;EACH,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACnC,QAAQ,UAAU,YAAY;EAC9B;CACD;AACD;;;;;;;;;;AAWA,SAAS,qBAAqB,OAAuB;CACpD,MAAM,SAAS,WACd,OAAO,MAAM,UAAU;EACtB,IAAI,aAAa,KAAK,GAAG,OAAO,MAAM,MAAM,MAAM;EAClD,OAAO,eAAe,KAAK,KAAK,uBAAuB,KAAK,MAAM;CACnE,CAAC;CACF,OAAO,MAAM,MAAM,MAAM;AAC1B;AAEA,SAAS,aAAa,OAAc,OAAiD;CACpF,MAAM,aAAa,MAAM;CAGzB,IAAI,CAAC,cAAc,WAAW,WAAW,SAAS,OAAO,CAAC;CAE1D,QAAQ,WAAW,MAAnB;EACC,KAAK,SACJ,OAAO,WAAW,QACf,EAAE,YAAY,QAAQ,EAAE,OAAO,WAAW,MAAM,aAAa,QAAQ,MAAM,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,EAAE,IAChG,CAAC;EACL,KAAK,QACJ,OAAO,CAAC;EACT;GACC,MAAM,KACL,oBACA,WACA,eACA,KAAK,WAAW,KAAK,2HACtB;GACA,OAAO,CAAC;CACV;AACD;AAEA,SAAS,QAAQ,OAAc,OAA0C;CACxE,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,MAAM,OAAO,CAAC;CACnB,MAAM,QAAQ,MAAM;CACpB,IAAI,SAAS,MAAM,WAAW,MAAM,cAAc,UAAU,KAAK,MAAM,QAAQ,IAAI,QAAQ,IAAI,MAAM,CAAC,GACrG,MAAM,KACL,oBACA,aACA,eACA,6GACD;CAED,OAAO,EAAE,WAAW,KAAK;AAC1B;;;;;;;;;;AAWA,SAAS,oBAAoB,OAAc,OAAwB;CAClE,IAAI,MAAM,eACT,MAAM,KACL,mBACA,WACA,UACA,+JACD;AAEF;;;;;;;;;;;;;;;;;;;;;;;;AClRA,MAAM,YAAY;;;;;AAMlB,MAAM,cAAc;;AAGpB,MAAM,aAAa;;;;;;;;AAiBnB,SAAgB,YAAY,OAAuB;CAClD,IAAI,MAAM;CACV,KAAK,MAAM,QAAQ,OAClB,QAAQ,MAAR;EACC,KAAK;GACJ,OAAO;GACP;EACD,KAAK;GACJ,OAAO;GACP;EACD,KAAK;GACJ,OAAO;GACP;EACD,KAAK;GACJ,OAAO;GACP;EACD,KAAK;GACJ,OAAO;GACP;EACD,SAAS;GACR,MAAM,OAAO,KAAK,YAAY,CAAC,KAAK;GAQpC,OADe,OAAO,MAAS,QAAQ,OAAQ,QAAQ,OAAS,SAAS,QAAU,SAAS,OAC5E,QAAQ,KAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,IAAI;EAC9D;CACD;CAED,OAAO,GAAG,IAAI;AACf;;;;;;;;AASA,SAAS,YAAY,OAAuB;CAC3C,IAAI,CAAC,OAAO,SAAS,KAAK,GACzB,MAAM,IAAI,mBAAmB,6BAA6B,qCAAqC,OAAO;CACvG,OAAO,OAAO,KAAK;AACpB;;AAGA,SAAS,SAAS,KAAqB;CACtC,OAAO,WAAW,KAAK,GAAG,IAAI,MAAM,YAAY,GAAG;AACpD;;AAGA,SAAS,OAAO,OAAgB,OAA6B;CAC5D,IAAI,UAAU,MAAM,OAAO;CAC3B,IAAI,OAAO,UAAU,WAAW,OAAO,OAAO,KAAK;CACnD,IAAI,OAAO,UAAU,UAAU,OAAO,YAAY,KAAK;CACvD,IAAI,OAAO,UAAU,UAAU,OAAO,YAAY,KAAK;CACvD,IAAI,WAAW,KAAK,GAAG,OAAO,MAAM,KAAK;CACzC,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,IAAI,MAAM,KAAK,SAAS,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;CAEzF,MAAM,OAAO,OAAO,KAAK,KAAK;CAC9B,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,OAAO,KAAK,KAAK,KAAK,QAAQ,GAAG,SAAS,GAAG,EAAE,IAAI,OAAO,MAAM,MAAiB,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;AACvG;;;;;;;;AASA,SAAgB,WAAW,OAAgB,aAAqB,OAA6B;CAC5F,MAAM,OAAO,OAAO,OAAO,KAAK;CAChC,IAAI,cAAc,cAAc,KAAK,UAAU,WAAW,OAAO;CAGjE,MAAM,MAAM,IAAK,OAAO,WAAW;CACnC,MAAM,QAAQ,IAAK,OAAO,cAAc,CAAC;CAEzC,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzB,IAAI,MAAM,WAAW,GAAG,OAAO;EAE/B,OAAO,MADO,MAAM,KAAK,SAAS,GAAG,QAAQ,WAAW,MAAM,cAAc,GAAG,KAAK,EAAE,EACrE,CAAC,CAAC,KAAK,IAAI,EAAE,IAAI,IAAI;CACvC;CAEA,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,WAAW,KAAK,GAAG;EACtE,MAAM,OAAO,OAAO,KAAK,KAAK;EAC9B,IAAI,KAAK,WAAW,GAAG,OAAO;EAI9B,OAAO,MAHS,KAAK,KACnB,QAAQ,GAAG,QAAQ,SAAS,GAAG,EAAE,IAAI,WAAW,MAAM,MAAiB,cAAc,GAAG,KAAK,EAAE,EAE9E,CAAC,CAAC,KAAK,IAAI,EAAE,IAAI,IAAI;CACzC;CAEA,OAAO;AACR;;;;;;;;AASA,SAAgB,eAAe,QAAgB,MAAiB,aAAqB,OAA6B;CACjH,MAAM,MAAM,IAAK,OAAO,WAAW;CACnC,MAAM,OAAO,GAAG,MAAM,OAAO,GAAG,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;CACjF,IAAI,cAAc,cAAc,KAAK,SAAS,IAAI,UAAU,WAAW,OAAO;CAI9E,MAAM,QAAQ,IAAK,OAAO,cAAc,CAAC;CAEzC,OAAO,GAAG,MAAM,OAAO,KADP,KAAK,KAAK,QAAQ,GAAG,QAAQ,WAAW,KAAK,cAAc,GAAG,KAAK,GACjD,CAAC,CAAC,KAAK,KAAK,EAAE,IAAI,IAAI;AACzD;;;;;;;;ACtGA,SAAgB,oBAAoB,SAKX;CACxB,OAAO;EACN,YAAY,QAAQ,cAAc;EAGlC,WAAW,QAAQ,YAAY,WAAA,CAAY,QAAQ,OAAO,EAAE;EAC5D,WAAW,QAAQ,UAAU;EAC7B,aAAa,QAAQ,eAAA;CACtB;AACD;;AAGA,MAAM,gBAAgB;;;;;;;;;AAUtB,SAAgB,iBAAiB,IAAiC;CACjE,MAAM,sBAAM,IAAI,IAAoB;CACpC,MAAM,uBAAO,IAAI,IAAY;CAC7B,KAAK,MAAM,SAAS,GAAG,QAAQ;EAC9B,MAAM,OAAO,MAAM,KAAK,QAAQ,YAAY,EAAE,CAAC,CAAC,QAAQ,mBAAmB,GAAG;EAC9E,IAAI,aAAa,cAAc,KAAK,IAAI,IAAI,OAAO,IAAI;EACvD,IAAI,SAAS;EACb,OAAO,KAAK,IAAI,UAAU,GAAG,aAAa,GAAG,KAAK,GAAG;EACrD,KAAK,IAAI,UAAU;EACnB,IAAI,IAAI,MAAM,MAAM,UAAU;CAC/B;CACA,OAAO;AACR;;AAGA,SAAgB,aAAa,aAAgD;CAC5E,QAAQ,QAA0B;EACjC,MAAM,aAAa,YAAY,IAAI,IAAI,MAAM;EAC7C,IAAI,CAAC,YACJ,MAAM,IAAI,mBACT,qCACA,mBAAmB,IAAI,OAAO,+BAC/B;EACD,OAAO;CACR;AACD;;;;;;;;;AAUA,SAAgB,mBACf,IACA,aACA,UACA,MACA,gBAAgB,2EACL;CACX,IAAI,GAAG,OAAO,WAAW,GAAG,OAAO,CAAC;CAEpC,MAAM,QACL,SAAS,SAAS,CAAC,qEAAqE,IAAI,CAAC,aAAa;CAE3G,KAAK,MAAM,SAAS,GAAG,QAAQ;EAC9B,MAAM,aAAa,YAAY,IAAI,MAAM,IAAI;EAC7C,IAAI,CAAC,YAAY;EACjB,IAAI,SAAS,QAAQ;GACpB,MAAM,OAAO,YAAY,GAAG,SAAS,GAAG,MAAM,MAAM;GACpD,MAAM,KACL,SAAS,WAAW,YAAY,MAAM,YAAY,kCAAkC,KAAK,0BAC1F;EACD,OACC,MAAM,KAAK,SAAS,WAAW,KAAK,YAAY,QAAQ,MAAM,YAAY,UAAU,SAAS,MAAM,KAAK,GAAG,GAAG;CAEhH;CACA,OAAO;AACR;;AAGA,SAAS,SAAS,OAA2B;CAC5C,IAAI,SAAS;CAGb,MAAM,QAAQ;CACd,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,OACtC,UAAU,OAAO,aAAa,GAAG,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC;CAE9D,OAAO,KAAK,MAAM;AACnB;;;;;;;;AASA,SAAgB,WACf,OACA,OACA,WACA,YACW;CACX,MAAM,QAAQ,WAAW,WAAW,MAAM,MAAM;CAChD,MAAM,aAAa,QAAQ,MAAM;CACjC,MAAM,QAAQ;EAAC;EAAI,MAAM,MAAM;EAAW,SAAS,WAAW,KAAK,MAAM;CAAc;CAEvF,IAAI,MAAM,SAAS,KAAA,GAClB,MAAM,KACL,cACA,WACA,cACA,2CAA2C,KAAK,UAAU,MAAM,IAAI,EAAE,oEACvE;CAGD,IAAI,MAAM,QAAQ,MAAM,KAAK,GAAG,WAAW,eAAe;CAC1D,IAAI,MAAM,YACT,MAAM,KAAK,GAAG,WAAW,gBAAgB,WAAW,MAAM,YAAuB,GAAG,UAAU,GAAG;CAElG,IAAI,MAAM,YACT,MAAM,KAAK,GAAG,WAAW,gBAAgB,WAAW,UAAU,MAAM,UAAU,GAAG,GAAG,UAAU,GAAG;CAElG,IAAI,MAAM,cAAc,KAAA,GACvB,MAAM,KAAK,eAAe,GAAG,WAAW,YAAY,CAAC,MAAM,SAAS,GAAG,GAAG,UAAU,CAAC;CAGtF,KAAK,MAAM,QAAQ,MAAM,OAAO;EAG/B,IAAI,KAAK,YAAY,MAAM,KAAK,MAAM,KAAK,WAAW,QAAQ,QAAQ,GAAG,GAAG;EAC5E,MAAM,KAAK,eAAe,GAAG,WAAW,GAAG,KAAK,UAAU,KAAK,MAAM,GAAG,UAAU,CAAC;CACpF;CAEA,OAAO;AACR;;AAGA,SAAgB,OAAO,OAAiB,OAA+B;CACtE,MAAM,QAAQ,CAAC,GAAG,OAAO,EAAE;CAE3B,IAAI,MAAM,WAAW,GACpB,MAAM,KAAK,4DAA4D;MACjE;EACN,MAAM,KACL,aAAa,MAAM,OAAO,gEAC1B,uFACA,EACD;EACA,KAAK,MAAM,CAAC,OAAO,UAAU,WAAW,KAAK,GAAG;GAC/C,MAAM,KAAK,GAAG,MAAM,EAAE;GACtB,KAAK,MAAM,QAAQ,OAAO;IACzB,MAAM,QAAQ,KAAK,YAAY,KAAK,KAAK,UAAU,KAAK;IACxD,MAAM,KACL,GAAG,KACF,KAAK,KAAK,YAAY,MAAM,IAAI,KAAK,YAAY,IAAI,KAAK,MAAM,MAAM,KAAK,UAC3E,eACA,IACD,CACD;GACD;EACD;CACD;CAEA,OAAO;EAAC;EAAM,GAAG,MAAM,KAAK,SAAU,OAAO,MAAM,SAAS,IAAK;EAAG;CAAK,CAAC,CAAC,KAAK,IAAI;AACrF;;AAGA,SAAS,WAAW,OAAwD;CAC3E,MAAM,YAAY,MAAM,QAAQ,SAAS,KAAK,gBAAgB,IAAI;CAClE,MAAM,0BAAU,IAAI,IAA4B;CAChD,KAAK,MAAM,QAAQ,OAAO;EACzB,IAAI,KAAK,gBAAgB,MAAM;EAC/B,MAAM,WAAW,QAAQ,IAAI,KAAK,WAAW;EAC7C,IAAI,UAAU,SAAS,KAAK,IAAI;OAC3B,QAAQ,IAAI,KAAK,aAAa,CAAC,IAAI,CAAC;CAC1C;CAEA,MAAM,MAAuC,CAAC;CAC9C,IAAI,UAAU,SAAS,GAAG,IAAI,KAAK,CAAC,QAAQ,SAAS,CAAC;CACtD,KAAK,MAAM,UAAU,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,GAC5D,IAAI,KAAK,CAAC,SAAS,UAAU,QAAQ,IAAI,MAAM,KAAK,CAAC,CAAC,CAAC;CAExD,OAAO;AACR;;AAGA,SAAS,KAAK,MAAc,OAAe,cAAgC;CAC1E,MAAM,QAAQ,KAAK,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC9C,MAAM,QAAkB,CAAC;CACzB,IAAI,UAAU;CACd,KAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,YAAY,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,eAAe;EACrE,IAAI,WAAW,UAAU,SAAS,OAAO;GACxC,MAAM,KAAK,OAAO;GAClB,UAAU,GAAG,eAAe;EAC7B,OACC,UAAU,UAAU,YAAY;CAElC;CACA,IAAI,SAAS,MAAM,KAAK,OAAO;CAC/B,OAAO;AACR;;;;;;;;;;;;;;;;AAiBA,SAAgB,cAAc,OAAiB,IAAY,WAAsB,OAAsC;CACtH,OAAO;EACN,MAAM,MAAM,KAAK,IAAI;EACrB,QAAQ,IAAI,IACX,cAAc,SAAS,GAAG,OAAO,KAAK,UAAgC,CAAC,MAAM,MAAM,MAAM,KAAK,CAAC,IAAI,CAAC,CACrG;EACA;CACD;AACD;;;;;;;;;;;;;;;;;;;;;;ACtNA,MAAM,8CAA8B,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACA;CAIA;CACA;CACA;CACA;CACA;AACD,CAAC;;AAGD,SAAS,kBAAkB,WAA4B;CACtD,OAAO,4BAA4B,IAAI,SAAS,KAAK,UAAU,WAAA,SAA6B;AAC7F;;AAGA,SAAgB,YAAY,IAAY,UAA8B,CAAC,GAAkB;CACxF,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,EAAE,YAAY,UAAU,WAAW,gBAAgB,oBAAoB,OAAO;CAEpF,MAAM,YAAY,IAAI,cAAc;CACpC,MAAM,aAAa,iBAAiB,EAAE;CAGtC,MAAM,OAAOE,cAAY,IAAI,WAFV,aAAa,UAEiB,CAAC;CAClD,MAAM,cAAc,GAAG,OAAO,MAAM,UAAU,MAAM,WAAW,SAAS;CACxE,MAAM,sBAAsB,GAAG,OAAO,MAAM,UAAU,MAAM,WAAW,cAAc,MAAM,WAAW,IAAI;CAG1G,MAAM,QAAQ,CAAC,GAAG,GAAG,SAAS,QAAQ,SAAS,CAAC,kBAAkB,KAAK,SAAS,CAAC,GAAG,GAAG,UAAU,KAAK;CAEtG,MAAM,QAAkB;EACvB,OACC;GACC;GACA;GACA;GACA;GACA;GACA;GACA,WAAW,aAAa,iDACvB,cAAc,UAAU,GAAG,OAAO,SAAS,IAAI,UAAU,GAAG,OAAO,OAAO,oBAAoB,aAAa,GAC3G;GACD,UAAU,WAAW;EACtB,GACA,KACD;EACA;EACA;EACA;EACA,sBAAsB,YAAY,WAAW;EAC7C,gCAAgC,YAAY,GAAG,YAAY,MAAM;EACjE;EACA;EACA;EACA;EACA;EACA;EACA,qDAAqD,YAAY,YAAY,EAAE;CAChF;CAEA,IAAI,aACH,MAAM,KACL,IACA,oFACA,+CAA+C,YAAY,YAAY,EAAE,GAC1E;CAGD,IAAI,qBACH,MAAM,KACL,IACA,sFACA,4CACA,2FACD;CAGD,MAAM,aAAa,mBAAmB,IAAI,YAAY,UAAU,SAAS;CACzE,IAAI,WAAW,SAAS,GAAG,MAAM,KAAK,IAAI,GAAG,UAAU;CAEvD,MAAM,KACL,IACA,OACA,uFACA,qFACA,OACA,kCACA,8BACA,gDAAgD,OAAO,GAAG,UAAU,QAAQ,EAAE,YAAY,OAAO,GAAG,UAAU,SAAS,EAAE,MACzH,2BACA,gBACA,KACA,GAAG,MACH,IACA,wBAAwB,YAAY,UAAU,EAAE,wBAChD,EACD;CAEA,OAAO,cAAc,OAAO,IAAI,WAAW,KAAK;AACjD;;;;;;;;;;;;;AAcA,SAASA,cAAY,IAAY,WAA0B,YAAoC;CAC9F,MAAM,eAAyB,CAAC;CAChC,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAmB,CAAC;CACxB,IAAI,iBAAiB;CAErB,MAAM,kCAAkB,IAAI,IAAY;CAExC,MAAM,cAAoB;EACzB,IAAI,MAAM,WAAW,GAAG;EACxB,MAAM,QAAQ,MAAM;EACpB,IAAI,CAAC,OAAO;EACZ,MAAM,OAAO,MAAM,EAAE;EACrB,MAAM,KAAK,IAAI,SAAS,KAAK,eAAe;EAC5C,KAAK,MAAM,SAAS,OAAO,MAAM,KAAK,GAAG,mBAAmB,OAAO,MAAM,WAAW,UAAU,CAAC;EAC/F,MAAM,KAAK,IAAI,YAAY,MAAM,OAAO,WAAW,iBAAiB,YAAY,CAAC;EACjF,QAAQ,CAAC;CACV;CAEA,KAAK,MAAM,SAAS,GAAG,QAAQ;EAC9B,IAAI,MAAM,WAAW,WAAW;GAC/B,MAAM;GACN,MAAM,KACL,IACA,YAAY,MAAM,OAAO,8EACzB,4BAA4B,MAAM,SAAS,EAAE,EAC9C;GACA;EACD;EAEA,MAAM,WAAW,MAAM;EACvB,IAAI,YAAY,SAAS,QAAQ,UAAU,MAAM,QAAQ,OAAO,MAAM;EACtE,MAAM,KAAK,KAAK;CACjB;CACA,MAAM;CAEN,OAAO,aAAa,SAAS,IAAI;EAAC;EAAI,GAAG;EAAc,GAAG;CAAK,IAAI;AACpE;;;;;;;;;;;;;;;;;AAkBA,SAAS,YACR,eACA,OACA,WACA,UACA,cACS;CACT,MAAM,SAAS,MAAM;CACrB,IAAI,CAAC,QAAQ,OAAO,2BAA2B,cAAc;CAC7D,IAAI,OAAO,cACV,OAAO,2BAA2B,cAAc,cAAc,YAAY,OAAO,IAAI,EAAE;CAGxF,WAAW,WAAW,MAAM,MAAM,CAAC,CAAC,KACnC,gBACA,gBACA,eACA,oDAAoD,KAAK,UAAU,OAAO,IAAI,EAAE,4CAA4C,OAAO,MAAM,iFAC1I;CACA,MAAM,aAAa,SAAS,OAAO;CACnC,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,GAAG;EAChC,SAAS,IAAI,OAAO,KAAK;EACzB,aAAa,KACZ,SAAS,WAAW,oBAAoB,OAAO,MAAM,OAAO,KAAK,UAAU,OAAO,IAAI,KACtF,QAAQ,WAAW,4DAA4D,OAAO,MAAM,GAC7F;CACD;CACA,OAAO,2BAA2B,cAAc,cAAc,WAAW;AAC1E;;AAGA,SAAS,mBACR,OACA,eACA,WACA,YACW;CACX,IAAI,MAAM,WAAW,MACpB,WAAW,WAAW,MAAM,MAAM,CAAC,CAAC,KACnC,gBACA,gBACA,eACA,kKACD;CAUD,IAAI,MAAM,YAAY,OAAO,SAAS,KAAA,GACrC,WAAW,WAAW,MAAM,MAAM,CAAC,CAAC,KACnC,yBACA,WACA,eACA,wbACD;CAGD,MAAM,SAAS,MAAM,WAAW,OAAO,cAAc,UAAU,KAAK,UAAU,MAAM,OAAO,IAAI;CAC/F,OAAO,WACN,OACA;EAAE,SAAS,SAAS,MAAM,OAAO,KAAK;EAAU,cAAc,GAAG,cAAc;CAAa,GAC5F,WACA,UACD;AACD;;;;;;;;;;;;AC1QA,MAAM,iCAAiB,IAAI,IAAI,CAAC,eAAe,CAAC;;AAGhD,SAAgB,sBAAsB,IAAY,UAAwC,CAAC,GAAkB;CAC5G,MAAM,EAAE,YAAY,UAAU,WAAW,gBAAgB,oBAAoB,OAAO;CAEpF,MAAM,YAAY,IAAI,cAAc;CACpC,MAAM,aAAa,iBAAiB,EAAE;CACtC,MAAM,aAAa,aAAa,UAAU;CAG1C,MAAM,UAAU,aAAa,IAAI,WAAW,UAAU;CACtD,MAAM,OAAO,YAAY,IAAI,WAAW,UAAU;CAClD,MAAM,QAAQ,CAAC,GAAG,GAAG,SAAS,QAAQ,SAAS,CAAC,eAAe,IAAI,KAAK,SAAS,CAAC,GAAG,GAAG,UAAU,KAAK;CAEvG,MAAM,gBAAgB,cAAc,UAAU,GAAG,OAAO,SAAS;CACjE,MAAM,QAAkB;EACvB,OACC;GACC;GACA;GACA,6CAA6C,cAC5C,gBAAgB,QAAQ,GAAG,OAAO,OAAO,oBAAoB,aAAa,GAC1E;GACD;GACA;GACA;GACA;GACA;GACA;GACA,UAAU,WAAW;EACtB,GACA,KACD;EACA;EACA,GAAI,gBAAgB,CAAC,6CAA6C,IAAI,CAAC;EACvE;EACA,sBAAsB,YAAY,WAAW;EAC7C;EACA;EACA;EACA;EACA;EACA,8CAA8C,OAAO,GAAG,UAAU,QAAQ,EAAE,YAAY,OAAO,GAAG,UAAU,SAAS,EAAE;EACvH;CACD;CAEA,MAAM,QAAQ,GAAG,OAAO;CACxB,IAAI,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC,SAAS,GACzC,MAAM,KACL,IACA,8FACA,gGACA,+CACA,gBAAgB,WAAW,OAAO,GAAG,UAAU,GAChD;CAGD,MAAM,QAAQ,cAAc,IAAI,SAAS;CACzC,IAAI,MAAM,SAAS,GAAG,MAAM,KAAK,IAAI,GAAG,KAAK;CAE7C,MAAM,aAAa,mBAClB,IACA,YACA,UACA,WACA,yEACD;CACA,IAAI,WAAW,SAAS,GAAG,MAAM,KAAK,IAAI,GAAG,UAAU;CAEvD,IAAI,QAAQ,SAAS,GAAG,MAAM,KAAK,IAAI,GAAG,OAAO;CACjD,MAAM,KAAK,GAAG,MAAM,IAAI,yCAAyC,YAAY,UAAU,EAAE,OAAO,EAAE;CAElG,OAAO,cAAc,OAAO,IAAI,WAAW,KAAK;AACjD;;;;;;;;AASA,SAAS,cAAc,IAAY,WAAoC;CACtE,MAAM,UAAU,OAAO,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,GAAG,WAAW,OAAO,UAAU,QAAQ;CAMxF,MAAM,UAAU;EAAC;EAAS;EAAU;EAAW;EAAW;CAAU,CAAC,CAAC,QAAQ,QAAQ,EAAE,OAAO,GAAG,MAAM;CACxG,IAAI,QAAQ,SAAS,GACpB,WAAW,WAAW,IAAI,CAAC,CAAC,KAC3B,wBACA,gBACA,cACA,+BAA+B,QAAQ,KAAK,IAAI,EAAE,+JAA+J,QAAQ,WAAW,IAAI,QAAQ,QAAQ,oBACzP;CAGD,IAAI,QAAQ,WAAW,GAAG,OAAO,CAAC;CAClC,OAAO,CACN,sFACA,GAAG,QAAQ,KAAK,CAAC,KAAK,WAAW,QAAQ,IAAI,KAAK,YAAY,KAAe,GAAG,CACjF;AACD;;;;;;;;;;;;AAaA,SAAS,aAAa,IAAY,WAA0B,YAAoC;CAK/F,WAAW,WAAW,MAAM,SAAS,CAAC,CAAC,KACtC,kBACA,gBACA,eACA,yRACD;CACA,IAAI,GAAG,OAAO,QAAQ,WAAW,GAAG,OAAO,CAAC;CAC5C,OAAO;EACN;EACA;EACA,GAAG,GAAG,OAAO,QAAQ,KAAK,WAAW,eAAe,0BAA0B,CAAC,OAAO,KAAK,GAAG,GAAG,UAAU,CAAC;CAC7G;AACD;;AAGA,SAAS,YAAY,IAAY,WAA0B,YAAoC;CAC9F,MAAM,2BAAW,IAAI,IAAsB;CAC3C,KAAK,MAAM,UAAU,GAAG,OAAO,SAAS,SAAS,IAAI,OAAO,aAAa,MAAM;CAE/E,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,SAAS,GAAG,QAAQ;EAC9B,MAAM,SAAS,MAAM,WAAW,OAAO,KAAA,IAAY,SAAS,IAAI,MAAM,OAAO,KAAK;EAClF,MAAM,QAAQ,OAAO,QAAQ,MAAM,aAAa,WAAW,OAAO,MAAM,WAAW;EAEnF,IAAI,UAAU,MACb,WAAW,WAAW,MAAM,MAAM,CAAC,CAAC,KACnC,gBACA,gBACA,eACA,MAAM,WAAW,OACd,mGACA,gDAAgD,MAAM,OAAO,MAAM,sFACvE;EAGD,MAAM,KACL,GAAG,WACF,OACA;GACC,SAAS,SAAS,MAAM,OAAO,KAAK,UAAU,OAAO,cAAc,UAAU,KAAK,UAAU,KAAK;GACjG,cAAc,UAAU,OAAO,oBAAoB,gCAAgC,YAAY,KAAK,EAAE;EACvG,GACA,WACA,UACD,CACD;CACD;CACA,OAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvHA,MAAM,mBAA4C;CACjD,MAAM;CACN,QAAQ;CACR,UAAU;CACV,WAAW;CACX,MAAM;CACN,QAAQ;CACR,OAAO;CACP,OAAO;CACP,cAAc;CACd,aAAa;CACb,UAAU;CACV,eAAe;AAChB;;;;;;AAOA,MAAM,iBAAoC;CAAC;CAAM;CAAK;CAAM;AAAG;;AAG/D,SAAgB,gBAAgB,IAA2B;CAC1D,MAAM,UAAU,aAAa,GAAG,MAAM;CACtC,OAAO;EACN,WAAW,GAAG;EACd,OAAO,eAAe,GAAG,OAAkB,OAAO;EAClD,QAAQ;GACP,OAAO,eAAe,GAAG,OAAO,OAAkB,OAAO;GACzD,SAAS,GAAG,OAAO,QAAQ,KAAK,WAAW,eAAe,OAAO,OAAO,OAAO,CAAC;EACjF;EACA,QAAQ,GAAG,OAAO,KAAK,UAAU,eAAe,OAAO,OAAO,CAAC;CAChE;AACD;AAEA,SAAS,eAAe,OAAgB,SAA8C;CACrF,OAAO;EACN,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,YAAY,MAAM,QAAQ,QAAQ;EAClC,YAAY,MAAM,eAAe,KAAA,IAAY,OAAO,eAAe,MAAM,YAAuB,OAAO;EACvG,WAAW,MAAM,aAAa;EAC9B,YAAY,MAAM,eAAe,KAAA,IAAY,OAAO,eAAe,UAAU,MAAM,UAAU,GAAG,OAAO;EACvG,OAAO,MAAM,MAAM,KAAK,SAAS;GAChC,MAAM,OAAO,KAAK,KAAK,KAAK,QAAQ,eAAe,KAAK,OAAO,CAAC;GAChE,OAAO;IACN,QAAQ,KAAK;IACb,WAAW,KAAK,cAAc;IAC9B,gBAAgB,CAAC,GAAG,mBAAmB,sBAAM,IAAI,IAAI,CAAC,CAAC;IACvD;GACD;EACD,CAAC;CACF;AACD;;;;;;;;AASA,SAAgB,mBAAmB,OAAgB,KAA+B;CACjF,IAAI,MAAM,QAAQ,KAAK,GAAG;EACzB,KAAK,MAAM,QAAQ,OAAO,mBAAmB,MAAM,GAAG;EACtD,OAAO;CACR;CACA,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,KAAK,GAC7C,IAAI,QAAQ,gBAAgB,OAAO,SAAS,UAAU,IAAI,IAAI,IAAI;MAC7D,mBAAmB,MAAiB,GAAG;CAE7C,OAAO;AACR;;;;;;;;;AAUA,SAAS,eAAe,OAAgB,SAAuC;CAC9E,IAAI,WAAW,KAAK,GAAG,OAAO,EAAE,QAAQ,QAAQ,IAAI,MAAM,MAAM,KAAK,WAAW,MAAM,SAAS;CAC/F,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,KAAK,SAAS,eAAe,MAAM,OAAO,CAAC;CAClF,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CAKxD,MAAM,WAAW,MAAM,YAAY,MAAM,OAAO,MAAM,eAAe,YAAY,MAAM,eAAe;CAEtG,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,KAAK,GAAG;EAChD,IAAI,OAAO,oBAAoB,SAAS,iBAAiB,MAAM;EAC/D,IAAI,QAAQ,YAAY,gBAAgB,IAAI,GAAG;EAC/C,IAAI,YAAY,QAAQ,WAAW;GAClC,MAAM,UAAU,EAAE,GAAI,KAAiC;GACvD,OAAO,QAAQ;GACf,IAAI,OAAO,eAAe,SAAS,OAAO;GAC1C;EACD;EACA,IAAI,OAAO,eAAe,MAAM,OAAO;CACxC;CACA,OAAO;AACR;AAEA,SAAS,gBAAgB,OAAyB;CACjD,OACC,MAAM,QAAQ,KAAK,KACnB,MAAM,WAAW,eAAe,UAChC,MAAM,OAAO,MAAM,UAAU,SAAS,eAAe,MAAM;AAE7D;;;;;;;;;AAUA,SAAS,aAAa,QAAwC;CAC7D,MAAM,sBAAM,IAAI,IAAoB;CACpC,KAAK,MAAM,SAAS,QAAQ;EAC3B,IAAI,OAAO;EACX,KAAK,MAAM,QAAQ,MAAM,OAAO;GAC/B,QAAQ;GACR,OAAO,KAAK,KAAK,MAAM,QAAU,MAAM;EACxC;EACA,IAAI,IAAI,MAAM,MAAM,GAAG,MAAM,MAAM,OAAO,GAAG,KAAK,SAAS,EAAE,GAAG;CACjE;CACA,OAAO;AACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtLA,MAAM,kBAA0C;CAI/C,UAAU;CACV,SAAS;CAGT,QACC;CAGD,OACC;CAED,OAAO;CACP,MAAM;CAGN,aAAa;CACb,qBAAqB;CACrB,iBAAiB;CAQjB,OAAO;CACP,QAAQ;CACR,SAAS;CACT,SAAS;CACT,UAAU;AACX;;;;;;;;;;;;;;;;;;;AAwEA,MAAM,cAAiD;CACtD,gBAAgB,CAAC,QAAQ;CACzB,eAAe,CAAC,MAAM;CACtB,cAAc,CAAC,MAAM;CACrB,kBAAkB,CAAC,GAAG;CACtB,eAAe,CAAC,GAAG;CACnB,qBAAqB,CAAC;CACtB,kBAAkB;EAAC;EAAS;EAAS;EAAY;EAAkB;CAAc;CACjF,sBAAsB,CAAC,QAAQ;CAK/B,iBAAiB,CAAC;CAGlB,wBAAwB,CAAC;CACzB,kBAAkB,CAAC,YAAY,WAAW;CAC1C,eAAe,CAAC,GAAG;CACnB,sBAAsB,CAAC,YAAY,MAAM;CAIzC,gBAAgB,CAAC,QAAQ,OAAO;CAOhC,yBAAyB,CAAC;CAC1B,oBAAoB,CAAC,QAAQ,OAAO;CACpC,wBAAwB,CAAC,GAAG;CAC5B,eAAe,CAAC,GAAG;CACnB,oBAAoB;EAAC;EAAK;EAAK;EAAK;EAAK;EAAU;EAAS;CAAO;CACnE,eAAe,CAAC,GAAG;CACnB,mBAAmB;EAAC;EAAU;EAAS;CAAO;CAC9C,cAAc,CAAC,QAAQ,QAAQ;CAC/B,iBAAiB;EAAC;EAAW;EAAa;EAAW;CAAW;CAIhE,aAAa;EAAC;EAAO;EAAQ;CAAQ;CACrC,kBAAkB,CAAC,kBAAkB,cAAc;CAYnD,qBAAqB;EAAC;EAAc;EAAS;EAAQ;CAAQ;CAC7D,mBAAmB,CAAC;CACpB,qBAAqB,CAAC;CACtB,kBAAkB,CAAC,QAAQ;CAC3B,mBAAmB,CAAC;CACpB,eAAe,CAAC,SAAS,YAAY;CACrC,wBAAwB,CAAC,SAAS,YAAY;CAC9C,uBAAuB,CAAC;CACxB,mBAAmB,CAAC;CACpB,mBAAmB,CAAC;CASpB,qBAAqB,CAAC;CACtB,gBAAgB,CAAC;CACjB,aAAa,CAAC,UAAU;CACxB,cAAc,CAAC,OAAO;CACtB,oBAAoB,CAAC,GAAG;CACxB,oBAAoB,CAAC,WAAW;CAChC,yBAAyB,CAAC,QAAQ;CAClC,iBAAiB,CAAC,UAAU,MAAM;CAClC,eAAe,CAAC,GAAG;CACnB,wBAAwB;EAAC;EAAK;EAAK;EAAK;CAAG;CAC3C,gBAAgB,CAAC,GAAG;CACpB,qBAAqB,CAAC,aAAa;CACnC,mBAAmB,CAAC;CACpB,oBAAoB;EAAC;EAAc;EAAS;EAAgB;CAAO;CACnE,iBAAiB,CAAC,GAAG;CACrB,gBAAgB,CAAC,YAAY;CAC7B,cAAc,CAAC;CAIf,oBAAoB,CAAC,YAAY;CAIjC,yBAAyB;EAAC;EAAS;EAAQ;CAAQ;CAGnD,2BAA2B,CAAC,UAAU,UAAU;CAQhD,sBAAsB,CAAC;CAGvB,2BAA2B,CAAC,MAAM;CAClC,oCAAoC,CAAC;CAGrC,sBAAsB,CAAC,WAAW;CAClC,+BAA+B,CAAC;CAGhC,uBAAuB,CAAC,WAAW;CACnC,4BAA4B,CAAC,WAAW;CACxC,4BAA4B,CAAC,MAAM;CACnC,iCAAiC,CAAC,MAAM;CAGxC,mBAAmB,CAAC,iBAAiB,MAAM;CAC3C,iBAAiB,CAAC,MAAM;CACxB,eAAe,CAAC,YAAY;CAC5B,cAAc,CAAC,OAAO;CAMtB,0BAA0B,CAAC,QAAQ;CAGnC,sBAAsB,CAAC,QAAQ;CAG/B,uBAAuB,CAAC,QAAQ;CAEhC,2BAA2B,CAAC,QAAQ;CAGpC,uBAAuB,CAAC,QAAQ;CAChC,sBAAsB,CAAC,OAAO;CAC9B,wBAAwB,CAAC,OAAO;CAChC,0BAA0B,CAAC,OAAO;CAClC,iBAAiB,CAAC,GAAG;CACrB,cAAc,CAAC,GAAG;CAClB,qBAAqB,CAAC,QAAQ;CAW9B,sBAAsB,CAAC,mBAAmB,gBAAgB;CAC1D,aAAa,CAAC,MAAM;AACrB;;;;;;AAOA,SAAgB,sBAAgC;CAC/C,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,KAAK;AACtC;;;;;;;;;AAUA,SAAgB,WAAW,UAAyB,QAAuB,OAAwC;CAClH,MAAM,cAA8B,CAAC;CAErC,IAAI,SAAS,UAAU,aAAa,OAAO,UAAU,UACpD,YAAY,KAAK,iBAAiB,GAAG,MAAM,CAAC,GAAG,sBAAsB,YAAY,SAAS,UAAU,UAAU,OAAO,UAAU,QAAQ,CAAC;CAEzI,IAAI,SAAS,UAAU,cAAc,OAAO,UAAU,WACrD,YAAY,KAAK,iBAAiB,GAAG,MAAM,CAAC,GAAG,uBAAuB,aAAa,SAAS,UAAU,WAAW,OAAO,UAAU,SAAS,CAAC;CAG7I,UAAU,SAAS,OAAO,OAAO,OAAO,SAAS,SAAS,GAAG,MAAM,CAAC,GAAG,WAAW;CAClF,WAAW,SAAS,QAAQ,OAAO,QAAQ,WAAW;CAEtD,MAAM,aAAa,KAAK,IAAI,SAAS,OAAO,QAAQ,OAAO,OAAO,MAAM;CACxE,KAAK,IAAI,QAAQ,GAAG,QAAQ,YAAY,SAAS;EAChD,MAAM,SAAS,SAAS,OAAO;EAC/B,MAAM,QAAQ,OAAO,OAAO;EAC5B,MAAM,SAAS,QAAQ,UAAU,OAAO,UAAU,QAAQ;EAC1D,IAAI,CAAC,UAAU,CAAC,OAAO;GACtB,YAAY,KAAK;IAChB,aAAa;IACb,WAAW;IACX,aAAa,CAAC;IACd,MAAM,UAAU,MAAM;IACtB,OAAO;IACP,MAAM,SAAS,SAAS;IACxB,UAAU,SAAS,UAAU;IAC7B,QAAQ,QAAQ,UAAU;IAC1B,YAAY;GACb,CAAC;GACD;EACD;EACA,UAAU,QAAQ,OAAO,WAAW;CACrC;CAEA,KAAK,MAAM,cAAc,aAAa,WAAW,aAAa,cAAc,YAAY,KAAK;CAC7F,MAAM,UAAU,IAAI,IAAI,YAAY,KAAK,eAAe,WAAW,UAAU,CAAC,CAAC,OAAO,OAAO,CAAC;CAC9F,MAAM,aAAa,eAClB,WAAW,eAAe,QAAS,WAAW,SAAS,WAAW,WAAW,SAAS;CAEvF,OAAO;EACN,YAAY,SAAS,OAAO;EAC5B;EACA,YAAY,YAAY,QAAQ,eAAe,CAAC,UAAU,UAAU,CAAC;EACrE,UAAU,YAAY,QAAQ,eAAe,WAAW,eAAe,IAAI;EAC3E,OAAO,YAAY,QAAQ,eAAe,WAAW,SAAS,OAAO;EACrE,gBAAgB,MAAM,QAAQ,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC;CAC1D;AACD;;;;;;;;;;;;;;;;;;;AAoBA,SAAS,WAAW,UAA2B,QAAyB,KAA2B;CAClG,UAAU,SAAS,OAAO,OAAO,OAAO,gBAAgB,SAAS,GAAG,MAAM,CAAC,GAAG,GAAG;CAMjF,MAAM,UACL,MACA,MACA,QACA,UACU;EACV,IAAI,KAAK;GACR,aAAa;GACb,WAAW,QAAQ,UAAU,SAAS,IAAI;GAC1C,aAAa,gBAAgB,QAAQ,KAAK;GAC1C;GACA,OAAO;GACP;GACA,UAAU,MAAM,MAAM;GACtB,QAAQ,MAAM,KAAK;GACnB,YAAY;EACb,CAAC;CACF;CAEA,MAAM,UAAU,cAAc,OAAO,OAAO;CAC5C,MAAM,iBAAiB,cAAc,SAAS,OAAO;CACrD,MAAM,0BAAU,IAAI,IAAa;CACjC,IAAI,SAAS;CACb,MAAM,sBAA2C;EAChD,OAAO,SAAS,OAAO,QAAQ,QAAQ;GACtC,MAAM,YAAY,OAAO,QAAQ;GACjC,IAAI,cAAc,KAAA,KAAa,CAAC,QAAQ,IAAI,SAAS,GAAG,OAAO;EAChE;CAED;CAEA,SAAS,QAAQ,SAAS,QAAQ,UAAU;EAC3C,MAAM,QAAQ,QAAQ,MAAM;EAE5B,MAAM,QAAQ,UAAU,QAAQ,eAAe,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAA;EACjF,MAAM,QAAQ,UAAU,KAAA,KAAa,CAAC,QAAQ,IAAI,KAAK,IAAI,QAAQ,cAAc;EACjF,IAAI,UAAU,KAAA,GAAW;GACxB,OAAO,kBAAkB,MAAM,IAAI,QAAQ,QAAQ,KAAA,CAAS;GAC5D;EACD;EACA,QAAQ,IAAI,KAAK;EAIjB,UAAU,QAAQ,OAAO,kBAAkB,MAAM,IAAI,UAAU,GAAG,MAAM,gBAAgB,QAAQ,KAAK,GAAG,GAAG;CAC5G,CAAC;CAED,OAAO,QAAQ,SAAS,OAAO,UAAU;EACxC,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAG,OAAO,kBAAkB,MAAM,IAAI,SAAS,KAAA,GAAW,KAAK;CACtF,CAAC;AACF;;AAGA,SAAS,cAAc,SAA0C;CAChE,MAAM,yBAAS,IAAI,IAAoB;CACvC,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,QAAQ,QAAQ,MAAM;EAC5B,IAAI,UAAU,MAAM,OAAO,IAAI,QAAQ,OAAO,IAAI,KAAK,KAAK,KAAK,CAAC;CACnE;CACA,MAAM,sBAAM,IAAI,IAAqB;CACrC,KAAK,MAAM,UAAU,SAAS;EAC7B,MAAM,QAAQ,QAAQ,MAAM;EAC5B,IAAI,UAAU,QAAQ,OAAO,IAAI,KAAK,MAAM,GAAG,IAAI,IAAI,OAAO,MAAM;CACrE;CACA,OAAO;AACR;;;;;AAMA,SAAS,gBAAgB,QAA6B,OAAsC;CAC3F,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,UAAU,CAAC,QAAQ,KAAK,GAAG,IAAI,WAAW,KAAA,GAAW,mBAAmB,QAAQ,KAAK;CAChG,OAAO,CAAC,GAAG,KAAK;AACjB;;AAGA,SAAS,QAAQ,QAAgC;CAChD,IAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG,OAAO;CACnF,MAAM,QAAS,OAAmC;CAClD,OAAO,OAAO,UAAU,WAAW,QAAQ;AAC5C;AAEA,SAAS,UAAU,UAA0B,QAAwB,KAA2B;CAC/F,MAAM,SAAS,SAAS;CACxB,MAAM,MAAM,MAAc,OAAe,GAAY,MAAqB;EACzE,IAAI,KAAK,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,GAAG,IAAI,KAAK,iBAAiB,QAAQ,MAAM,CAAC,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CAC5G;CACA,GAAG,UAAU,UAAU,SAAS,QAAQ,OAAO,MAAM;CACrD,GAAG,cAAc,cAAc,SAAS,YAAY,OAAO,UAAU;CACrE,GAAG,cAAc,cAAc,SAAS,YAAY,OAAO,UAAU;CACrE,GAAG,aAAa,aAAa,SAAS,WAAW,OAAO,SAAS;CAKjE,UAAU,SAAS,YAAY,OAAO,YAAY,cAAc,cAAc,QAAQ,MAAM,CAAC,GAAG,GAAG;CAEnG,KAAK,MAAM,CAAC,QAAQ,UAAU,WAAW,SAAS,OAAO,OAAO,KAAK,GAAG;EACvE,MAAM,OAAO,QAAQ,aAAa,OAAO,aAAa;EAEtD,MAAM,SAAS,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAI,QAAQ,kBAAkB,CAAC,GAAI,GAAI,OAAO,kBAAkB,CAAC,CAAE,CAAC,CAAC;EACjG,MAAM,OAAO,SAAS,SAAS,SAAS,MAAM,QAAQ,MAAM,IAAI,OAAO,MAAM,QAAQ,KAAsB,EAAE;EAC7G,IAAI,CAAC,UAAU,CAAC,OAAO;GACtB,IAAI,KAAK;IACR,aAAa;IACb,WAAW;IACX,aAAa;IACb;IACA,OAAO;IACP,MAAM,SAAS,SAAS;IACxB,UAAU,SAAS,OAAO,SAAS;IACnC,QAAQ,QAAQ,MAAM,SAAS;IAC/B,YAAY;GACb,CAAC;GACD;EACD;EACA,IAAI,OAAO,WAAW,MAAM,QAC3B,IAAI,KAAK,iBAAiB,QAAQ,MAAM,QAAQ,GAAG,KAAK,UAAU,UAAU,OAAO,QAAQ,MAAM,MAAM,CAAC;EAEzG,UAAU,OAAO,MAAM,MAAM,MAAM,GAAG,KAAK,QAAQ,QAAQ,QAAQ,MAAM,QAAQ,GAAG;CACrF;AACD;;;;;;;;;;AAWA,SAAS,WACR,UACA,QACsD;CACtD,MAAM,UAAU,UAAuD;EACtE,MAAM,yBAAS,IAAI,IAAoB;EACvC,KAAK,MAAM,QAAQ,OAAO;GACzB,IAAI,KAAK,cAAc,MAAM;GAC7B,OAAO,IAAI,KAAK,YAAY,OAAO,IAAI,KAAK,SAAS,KAAK,KAAK,CAAC;EACjE;EACA,MAAM,sBAAM,IAAI,IAA2B;EAC3C,KAAK,MAAM,QAAQ,OAClB,IAAI,KAAK,cAAc,QAAQ,OAAO,IAAI,KAAK,SAAS,MAAM,GAAG,IAAI,IAAI,KAAK,WAAW,IAAI;EAE9F,OAAO;CACR;CAEA,MAAM,SAAS,OAAO,MAAM;CAC5B,MAAM,0BAAU,IAAI,IAAmB;CACvC,MAAM,QAA6D,CAAC;CAGpE,IAAI,SAAS;CACb,MAAM,sBAA4C;EACjD,OAAO,SAAS,OAAO,QAAQ;GAC9B,MAAM,YAAY,OAAO;GACzB,IAAI,aAAa,CAAC,QAAQ,IAAI,SAAS,GAAG,OAAO;EAClD;EACA,OAAO;CACR;CAEA,KAAK,MAAM,QAAQ,UAAU;EAC5B,MAAM,QAAQ,KAAK,cAAc,OAAO,KAAA,IAAY,OAAO,IAAI,KAAK,SAAS;EAC7E,IAAI,SAAS,CAAC,QAAQ,IAAI,KAAK,GAAG;GACjC,QAAQ,IAAI,KAAK;GACjB,MAAM,KAAK,CAAC,MAAM,KAAK,CAAC;GACxB;EACD;EACA,MAAM,aAAa,cAAc;EACjC,IAAI,YAAY,QAAQ,IAAI,UAAU;EACtC,MAAM,KAAK,CAAC,MAAM,UAAU,CAAC;CAC9B;CACA,KAAK,MAAM,QAAQ,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,IAAI,CAAC;CAC1E,OAAO;AACR;AAEA,SAAS,UACR,UACA,QACA,MACA,OACA,aACA,WACA,aACA,KACO;CACP,IAAI,aAAa,QAAQ;CACzB,MAAM,UAAU,UAA4B,UAAU,OAAO,SAAS,MAAM,QAAQ,KAAK,IAAI,UAAU,OAAO;CAC9G,IAAI,OAAO,QAAQ,MAAM,OAAO,MAAM,GAAG;EACxC,IAAI,KAAK,iBAAiB,aAAa,WAAW,aAAa,MAAM,OAAO,UAAU,MAAM,CAAC;EAC7F;CACD;CAEA,IAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,MAAM,GAAG;EACrD,MAAM,SAAS,KAAK,IAAI,SAAS,QAAQ,OAAO,MAAM;EACtD,KAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,SAAS;GAC5C,MAAM,SAAS,SAAS;GACxB,MAAM,QAAQ,OAAO;GACrB,IAAI,WAAW,KAAA,KAAa,UAAU,KAAA,GAAW;IAChD,IAAI,KAAK;KACR;KACA;KACA;KACA,MAAM,GAAG,KAAK,GAAG,MAAM;KACvB;KACA,MAAM,WAAW,KAAA,IAAY,UAAU;KACvC,UAAU,MAAM,MAAM;KACtB,QAAQ,MAAM,KAAK;KACnB,YAAY;IACb,CAAC;IACD;GACD;GACA,UAAU,QAAQ,OAAO,GAAG,KAAK,GAAG,MAAM,IAAI,OAAO,aAAa,WAAW,aAAa,GAAG;EAC9F;EACA;CACD;CAEA,IAAI,aAAa,QAAQ,OAAO,aAAa,YAAY,WAAW,QAAQ,OAAO,WAAW,UAAU;EACvG,MAAM,SAAS;EACf,MAAM,QAAQ;EACd,KAAK,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,GAAG;GAC3E,MAAM,SAAS,OAAO;GACtB,MAAM,QAAQ,MAAM;GACpB,IAAI,WAAW,KAAA,KAAa,UAAU,KAAA,GAAW;IAChD,IAAI,KAAK;KACR;KACA;KACA;KACA,MAAM,GAAG,KAAK,GAAG;KACjB,OAAO;KACP,MAAM,WAAW,KAAA,IAAY,UAAU;KACvC,UAAU,MAAM,MAAM;KACtB,QAAQ,MAAM,KAAK;KACnB,YAAY;IACb,CAAC;IACD;GACD;GACA,UAAU,QAAQ,OAAO,GAAG,KAAK,GAAG,OAAO,KAAK,aAAa,WAAW,aAAa,GAAG;EACzF;EACA;CACD;CAEA,IAAI,KAAK,iBAAiB,aAAa,WAAW,aAAa,MAAM,OAAO,UAAU,MAAM,CAAC;AAC9F;AAEA,SAAS,iBACR,aACA,WACA,aACA,MACA,OACA,UACA,QACe;CACf,OAAO;EACN;EACA;EACA;EACA;EACA;EACA,MAAM;EACN,UAAU,MAAM,QAAQ;EACxB,QAAQ,MAAM,MAAM;EACpB,YAAY;CACb;AACD;;AAGA,SAAS,cAAc,YAA0B,OAA4C;CAC5F,KAAK,MAAM,QAAQ,OAAO;EACzB,IAAI,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,WAAW,aAAa;EAK9E,IAAI,KAAK,UAAU,WAAA,SAA6B,KAAK,WAAW,gBAAgB,GAAG;EAEnF,IACC,KAAK,cAAc,QACnB,KAAK,cAAc,WAAW,aAC9B,CAAC,WAAW,YAAY,SAAS,KAAK,SAAS,GAE/C;EAED,MAAM,SAAS,WAAW,KAAK,SAAS;EACxC,IAAI,CAAC,QAAQ;EACb,IAAI,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,WAAW,KAAK,GAAG,OAAO;CACvE;CACA,OAAO;AACR;;;;;;;;AASA,SAAS,WAAW,WAAkD;CACrE,OAAO,YAAY,eAAe,UAAU,WAAA,SAA6B,IAAI,YAAY,UAAU,MAAA,CAA+B,KAAK,KAAA;AACxI;;;;;AAMA,SAAgB,qBAAqB,WAA4B;CAChE,OAAO,WAAW,SAAS,MAAM,KAAA;AAClC;AAEA,SAAS,MAAM,OAAoC;CAClD,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,MAAM,OAAO,KAAK,UAAU,KAAK;CACjC,OAAO,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AACrD"}
|