{"version":3,"sources":["../src/index.ts","../src/resilience.ts"],"sourcesContent":["export type { TranslationResilienceOptions } from './resilience';\nexport { installTranslationResilience } from './resilience';\n","/**\n * Makes React (and any other text-node-owning renderer) resilient to browser\n * page translation — Chrome / Google Translate and Edge, which merge and\n * replace Text nodes with `<font>` wrappers, and Firefox, which empties and\n * refills translated elements, reusing only some of their Text nodes. React\n * keeps references to the original, now detached, Text nodes, so without this\n * shim:\n *\n *  - unmounting translated conditional text throws NotFoundError (removeChild)\n *  - mounting content before translated text throws NotFoundError (insertBefore)\n *  - updating translated text writes to the detached node — the visible page\n *    silently never updates again (see facebook/react#11538)\n *\n * Strategy — \"re-adoption\", not error swallowing:\n *\n * 1. A document-wide MutationObserver watches mutations. Translation displaces\n *    text nodes in a recognizable pattern: adjacent Text nodes are merged\n *    (`normalize()`), then the merged run is replaced by wrapper elements\n *    inserted next to it in the same task. We track a DISPLACEMENT GROUP per\n *    replaced run: the ordered renderer-owned originals (with their\n *    pre-translation values) and the run of replacement nodes standing in for\n *    them. React's own commits never look like this: React processes\n *    deletions before placements, so a node it removes is never adjacent to a\n *    same-batch insertion at removal time, and React never merges text nodes.\n *\n * 2. Patched Node.prototype.removeChild / insertBefore / appendChild and the\n *    nodeValue / data setters detect operations on displaced Text nodes and\n *    first RESTORE the group — original nodes go back into the replacement\n *    run's position, replacements are removed — then let the native operation\n *    proceed. This repairs the renderer's ownership invariant: updates become\n *    visible, removals remove the right content, and the translator\n *    re-translates the freshly restored text via its own observer.\n *\n * 3. Translation can also delete text nodes outright and move inline elements\n *    (word-order changes — Chromium bug 872770). Deletions within a\n *    translation batch get an empty group with position hints so the node can\n *    come back if React updates it. Once translation activity has been\n *    detected, unrecoverable parent mismatches degrade to guarded best-effort\n *    operations instead of throwing.\n *\n * 4. Firefox applies a translation to an element by detaching every child and\n *    appending the translation back, reusing Text nodes by position; all but\n *    the first node of each run of text stay detached (see\n *    recognizeChildrenMerges). A lossy merge gets a WHOLE-PARENT group — the\n *    parent's original children and pre-translation text — restored before\n *    any renderer operation on one of them, attached or not. Firefox then\n *    re-translates the restored nodes one by one, in place.\n *\n * Arming, and why it cannot rely on the patches above: a browser's page\n * translator runs in the engine's own ISOLATED WORLD — it shares the DOM but\n * holds a separate copy of Node.prototype (Chromium runs the translate script\n * via ExecuteScriptInIsolatedWorld; see translate_agent.cc). None of the\n * patched methods here ever observe a translator's own mutations, so every\n * arming signal has to be one the shared DOM raises:\n *\n *  - Chrome's translator adds a `translated-*` class to <html> a few hundred\n *    ms before it touches text: an attribute sentinel catches that, and\n *    attributes are shared across worlds.\n *  - Firefox's translator sets <html lang> as it starts. Apps write that\n *    attribute too, so only a write from outside the page counts — told apart\n *    by wrappers on the <html> instance that the page's own writes go through\n *    and a translator's never do (see trackPageAttributeWrites).\n *  - Edge's translator and the Google Translate extension mark nothing. For\n *    those, a detection stylesheet (DETECTION_CSS) puts a CSS animation on the\n *    translator's signature <font>, and `animationstart` fires whichever world\n *    inserted it — at a fraction of the cost of observing the document.\n *  - Whatever still slips through lands on a patched method that is about to\n *    throw NotFoundError, where a document sweep (translationEvident) tells a\n *    translated page from a genuine renderer bug.\n *\n * Before any translation activity is detected, operations on untracked nodes\n * behave exactly as before — including throwing on genuine bugs.\n */\n\ninterface DisplacedOriginal {\n  node: Node;\n  /**\n   * A Text node's value before translation touched it (normalize and Firefox's\n   * merge both overwrite nodes they reuse); null for any other node.\n   */\n  value: string | null;\n}\n\ninterface DisplacementGroup {\n  parent: Node;\n  /** Renderer-owned nodes this group stands in for, in document order. */\n  originals: DisplacedOriginal[];\n  /** Nodes currently displaying the originals' content (empty if translation deleted the run). */\n  replacement: Node[];\n  /** Position hints captured at removal time, used when `replacement` is empty. */\n  previousSiblingHint: Node | null;\n  nextSiblingHint: Node | null;\n  /**\n   * The originals are ALL of the parent's children, text and elements, and\n   * restoring rebuilds the parent's child list (Firefox's merge — see\n   * recognizeChildrenMerges). Otherwise they are one displaced run of text\n   * that `replacement` stands in for (Chrome/Edge wrap-and-remove).\n   */\n  wholeParent: boolean;\n}\n\nconst displaced = new WeakMap<Node, DisplacementGroup>();\nconst groupByReplacementNode = new WeakMap<Node, DisplacementGroup>();\n/** Live merge targets (normalize) carrying content of already-detached originals. */\nconst pendingCarrierOriginals = new WeakMap<Text, DisplacedOriginal[]>();\n\nlet observer: MutationObserver | null = null;\nlet sentinelObserver: MutationObserver | null = null;\n/** True while installed but not yet observing — patched methods run a cheap synchronous signal check. */\nlet sentinelActive = false;\nlet translationDetected = false;\nconst noopEvent = (_message: string): void => undefined;\nlet emitEvent: (message: string) => void = noopEvent;\n\ninterface DomNatives {\n  insertBefore: typeof Node.prototype.insertBefore;\n  removeChild: typeof Node.prototype.removeChild;\n  appendChild: typeof Node.prototype.appendChild;\n  nodeValueDescriptor: PropertyDescriptor;\n  dataDescriptor: PropertyDescriptor;\n  setNodeValue(node: Node, value: string | null): void;\n  setData(node: CharacterData, value: string): void;\n}\n\nlet capturedNatives: DomNatives | null = null;\n\n/**\n * Native DOM entry points, captured once on first use rather than at module\n * load so that importing this module is safe in non-DOM environments (SSR);\n * only calling install requires a browser.\n */\nfunction domNatives(): DomNatives {\n  if (capturedNatives) return capturedNatives;\n  if (typeof Node === 'undefined' || typeof CharacterData === 'undefined') {\n    throw new Error(\n      'translation-resilience requires a DOM. Call installTranslationResilience() from client-side code only.'\n    );\n  }\n  const nodeValueDescriptor = Object.getOwnPropertyDescriptor(Node.prototype, 'nodeValue');\n  const dataDescriptor = Object.getOwnPropertyDescriptor(CharacterData.prototype, 'data');\n  const nodeValueSet = nodeValueDescriptor?.set;\n  const dataSet = dataDescriptor?.set;\n  if (!nodeValueDescriptor?.get || !nodeValueSet || !dataDescriptor?.get || !dataSet) {\n    throw new Error('translation-resilience: expected accessor descriptors for nodeValue and data');\n  }\n  capturedNatives = {\n    insertBefore: Node.prototype.insertBefore,\n    removeChild: Node.prototype.removeChild,\n    appendChild: Node.prototype.appendChild,\n    nodeValueDescriptor,\n    dataDescriptor,\n    setNodeValue: (node, value) => nodeValueSet.call(node, value),\n    setData: (node, value) => dataSet.call(node, value),\n  };\n  return capturedNatives;\n}\n\n/**\n * A fault in the shim itself must never make things worse than stock\n * behavior: every non-native code path runs through this guard, and on an\n * internal error the caller falls back to the native operation.\n */\nfunction describeError(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}\n\nfunction guarded<T>(operation: string, run: () => T, fallback: T): T {\n  try {\n    return run();\n  } catch (error) {\n    emitEvent(`internal error in ${operation}: ${describeError(error)}`);\n    return fallback;\n  }\n}\n\nfunction markTranslationDetected(): void {\n  if (translationDetected) return;\n  translationDetected = true;\n  emitEvent('translation activity detected');\n}\n\nfunction registerGroup(group: DisplacementGroup): void {\n  markTranslationDetected();\n  for (const original of group.originals) displaced.set(original.node, group);\n  for (const node of group.replacement) groupByReplacementNode.set(node, group);\n}\n\nfunction unregisterGroup(group: DisplacementGroup): void {\n  for (const original of group.originals) displaced.delete(original.node);\n  for (const node of group.replacement) groupByReplacementNode.delete(node);\n}\n\n/**\n * Correlation state must survive batch boundaries: the record stream can be\n * split at arbitrary points — the shim's own synchronous drains inside\n * patched DOM methods split a translator's mutation sequence across several\n * processRecords calls, and translators themselves spread work across tasks.\n * Entries are consumed on use and expire after a short wall-clock window so\n * that old insertions are never attributed to unrelated removals later.\n */\nconst CORRELATION_WINDOW_MS = 100;\n\ninterface TimedRun {\n  at: number;\n  nodes: Node[];\n}\ninterface TimedValue {\n  at: number;\n  value: string;\n}\ninterface PendingOrphan {\n  at: number;\n  parent: Node;\n  removed: Text;\n  previousSibling: Node | null;\n  nextSibling: Node | null;\n}\n\n/**\n * Every correlation store below is kept in ascending-`at` order: new entries\n * are appended, and any refresh of an existing entry's timestamp must\n * delete-then-set so the entry moves to the end. purgeExpired relies on this\n * to drop only the expired prefix and stop at the first fresh entry —\n * processRecords runs on every synchronous drain (i.e. inside patched DOM\n * calls), so a full scan of the stores per drain is quadratic under heavy\n * synchronous DOM churn.\n */\n\n/** Nodes recently inserted, indexed by their at-insertion-time nextSibling. */\nconst recentInsertedBefore = new Map<Node, TimedRun>();\n/** First recently-seen characterData oldValue per node = value before the mutation sequence. */\nconst recentOldValues = new Map<Node, TimedValue>();\n/** Accumulated merged-away content per normalize target, for validation. */\nconst recentCarrierAccumulated = new Map<Text, TimedValue>();\n/** Text removals with no replacement — become deletion groups once translator activity is confirmed. */\nlet pendingOrphans: PendingOrphan[] = [];\n\nfunction purgeExpired(now: number): void {\n  for (const [key, entry] of recentInsertedBefore) {\n    if (now - entry.at <= CORRELATION_WINDOW_MS) break;\n    recentInsertedBefore.delete(key);\n  }\n  for (const [key, entry] of recentOldValues) {\n    if (now - entry.at <= CORRELATION_WINDOW_MS) break;\n    recentOldValues.delete(key);\n  }\n  for (const [key, entry] of recentCarrierAccumulated) {\n    if (now - entry.at <= CORRELATION_WINDOW_MS) break;\n    recentCarrierAccumulated.delete(key);\n  }\n  const firstFresh = pendingOrphans.findIndex((orphan) => now - orphan.at <= CORRELATION_WINDOW_MS);\n  if (firstFresh === -1) {\n    if (pendingOrphans.length > 0) pendingOrphans = [];\n  } else if (firstFresh > 0) {\n    pendingOrphans = pendingOrphans.slice(firstFresh);\n  }\n}\n\nfunction clearCorrelationState(): void {\n  recentInsertedBefore.clear();\n  recentOldValues.clear();\n  recentCarrierAccumulated.clear();\n  pendingOrphans = [];\n  forgetPageMoves();\n}\n\n/** Replacement nodes a translator produces: <font> wrappers or plain text (revert). */\nfunction looksLikeTranslatorReplacement(node: Node): boolean {\n  return node instanceof Text || node.nodeName === 'FONT';\n}\n\n/**\n * Recognises the <font> wrapper a page translator specifically emits — not a\n * <font> an app happens to render itself. <font> is deprecated but apps can\n * still produce one (JSX, dangerouslySetInnerHTML, rendered HTML/markdown), so\n * the tag alone is not enough; we match the translator's signature:\n *\n *  - Chrome's Google Translate (built-in and the browser extension) wraps text\n *    in `<font style=\"vertical-align: inherit;\">` (doubly nested).\n *  - Microsoft Edge's built-in translator wraps in `<font>` carrying\n *    `_msttexthash` / `_msthash` / `_mstmutation` attributes and no style.\n *\n * Matching the signature keeps an app's own <font> from arming the observer,\n * while still covering translators that never mark <html>.\n */\nfunction isTranslatorFontWrapper(node: Node): boolean {\n  if (node.nodeName !== 'FONT' || !(node instanceof HTMLElement)) return false;\n  return (\n    node.style.verticalAlign === 'inherit' ||\n    node.hasAttribute('_msttexthash') ||\n    node.hasAttribute('_msthash') ||\n    node.hasAttribute('_mstmutation')\n  );\n}\n\n/**\n * The CSS spelling of the same signature isTranslatorFontWrapper matches.\n * Kept deliberately adjacent to it: both must describe the same wrappers.\n */\nconst TRANSLATOR_FONT_SELECTOR = 'font[_msttexthash],font[_msthash],font[_mstmutation],font[style*=\"vertical-align\"]';\n\nconst DETECTION_ANIMATION_NAME = 'translation-resilience-detect';\n\n/**\n * A browser's page translator runs in the engine's own isolated world: it\n * shares the DOM but has a separate copy of Node.prototype, so it never calls\n * the patched methods in this module. Any signal that depends on those\n * patches firing (see noticeTranslatorFont) can therefore only ever be raised\n * by a same-realm translator such as the bundled simulator — never by Chrome,\n * Edge or Firefox. Arming has to come from the shared DOM itself.\n *\n * A MutationObserver would see it, but observing childList across the whole\n * document costs about what the full observer costs (+7.2% vs +9.5% on a\n * 500x4 grid churn benchmark, headless Chrome, medians of 9 interleaved\n * trials) — precisely the cost lazy activation exists to avoid. A CSS\n * animation keyed to the translator's signature <font> costs the style engine\n * one more selector on elements it is already matching, and raises\n * `animationstart` when a matching element enters the tree from any world:\n * +1.1% on the same benchmark.\n *\n * `!important` and the attribute-qualified selector keep a global\n * `* { animation: none !important }` reset from silencing the hook.\n */\nconst DETECTION_CSS =\n  `@keyframes ${DETECTION_ANIMATION_NAME}{from{opacity:1}to{opacity:1}}` +\n  `${TRANSLATOR_FONT_SELECTOR}{animation-duration:1ms!important;animation-name:${DETECTION_ANIMATION_NAME}!important}`;\n\n/**\n * Constructable stylesheets first: a `style-src 'self'` Content-Security-Policy\n * blocks an injected <style> element outright (verified in Chrome), while\n * adoptedStyleSheets is CSSOM and unaffected by it. The <style> fallback\n * covers engines without constructable stylesheet support.\n */\nfunction installDetectionStylesheet(doc: Document): () => void {\n  const view = doc.defaultView;\n  try {\n    if (view && typeof view.CSSStyleSheet === 'function' && Array.isArray(doc.adoptedStyleSheets)) {\n      const sheet = new view.CSSStyleSheet();\n      sheet.replaceSync(DETECTION_CSS);\n      doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];\n      return () => {\n        doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((candidate) => candidate !== sheet);\n      };\n    }\n  } catch (error) {\n    emitEvent(`detection stylesheet: adoptedStyleSheets unusable (${describeError(error)})`);\n  }\n  try {\n    const style = doc.createElement('style');\n    style.textContent = DETECTION_CSS;\n    (doc.head ?? doc.documentElement).appendChild(style);\n    return () => style.remove();\n  } catch (error) {\n    // No detection stylesheet: the repair-path sweep still prevents the crash.\n    emitEvent(`detection stylesheet: not installed (${describeError(error)})`);\n    return () => undefined;\n  }\n}\n\n/**\n * Whether the document currently holds a translator's signature <font>. Only\n * ever called from a path that is otherwise about to throw, so a\n * document-wide query is affordable there; it never runs on a healthy path.\n */\nfunction documentShowsTranslation(doc: Document): boolean {\n  try {\n    return doc.querySelector(TRANSLATOR_FONT_SELECTOR) !== null;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * The run of nodes that took a removed node's place. A replaceChild-style\n * swap queues a single record carrying both sides — correlate those directly.\n * Translation instead inserts the wrapper(s) directly before the original and\n * then removes it as separate operations, so each wrapper's insertion record\n * has the original as its at-insertion-time nextSibling. Sibling pointers are\n * NOT walked at processing time — later mutations may already have\n * invalidated them.\n */\nfunction replacementRunFor(removed: Node, record: MutationRecord): Node[] {\n  if (record.removedNodes.length === 1 && record.addedNodes.length === 1) {\n    const added = record.addedNodes[0];\n    return added ? [added] : [];\n  }\n  const entry = recentInsertedBefore.get(removed);\n  if (!entry) return [];\n  recentInsertedBefore.delete(removed);\n  return entry.nodes.filter(looksLikeTranslatorReplacement);\n}\n\n/**\n * Detects a normalize() merge: the removed text's content was appended onto\n * the preceding Text sibling. The carrier must have a recent characterData\n * record (a renderer removing a node never mutates its neighbor) and its\n * content must be consistent with concatenation. Pre-mutation values are\n * used throughout — the caller (e.g. React) may already have written a new\n * value into a node before these records were processed.\n */\nfunction mergeCarrierFor(removed: Text, record: MutationRecord, now: number): Text | null {\n  const carrier = record.previousSibling;\n  if (!carrier || !(carrier instanceof Text)) return null;\n  const carrierOriginalValue = recentOldValues.get(carrier)?.value;\n  if (carrierOriginalValue === undefined) return null;\n  const accumulated = (recentCarrierAccumulated.get(carrier)?.value ?? '') + snapshotValue(removed);\n  if (!(carrier.nodeValue ?? '').startsWith(carrierOriginalValue + accumulated)) return null;\n  // delete-then-set keeps the store in ascending-`at` order (see purgeExpired)\n  recentCarrierAccumulated.delete(carrier);\n  recentCarrierAccumulated.set(carrier, { at: now, value: accumulated });\n  return carrier;\n}\n\nfunction snapshotValue(node: Text): string {\n  return recentOldValues.get(node)?.value ?? node.nodeValue ?? '';\n}\n\n/** Returns true if a displacement group was registered. */\nfunction handleDisplacedText(removed: Text, record: MutationRecord, now: number): boolean {\n  const run = replacementRunFor(removed, record);\n  if (run.length > 0) {\n    const group: DisplacementGroup = {\n      parent: record.target,\n      originals: [{ node: removed, value: snapshotValue(removed) }, ...(pendingCarrierOriginals.get(removed) ?? [])],\n      replacement: run,\n      previousSiblingHint: record.previousSibling,\n      nextSiblingHint: record.nextSibling,\n      wholeParent: false,\n    };\n    pendingCarrierOriginals.delete(removed);\n    registerGroup(group);\n    return true;\n  }\n\n  const carrier = mergeCarrierFor(removed, record, now);\n  if (carrier) {\n    const carried = pendingCarrierOriginals.get(carrier) ?? [];\n    carried.push({ node: removed, value: snapshotValue(removed) }, ...(pendingCarrierOriginals.get(removed) ?? []));\n    pendingCarrierOriginals.delete(removed);\n    pendingCarrierOriginals.set(carrier, carried);\n    return false;\n  }\n\n  pendingOrphans.push({\n    at: now,\n    parent: record.target,\n    removed,\n    previousSibling: record.previousSibling,\n    nextSibling: record.nextSibling,\n  });\n  return false;\n}\n\nfunction handleReplacementRemoved(group: DisplacementGroup, removed: Node, record: MutationRecord): void {\n  groupByReplacementNode.delete(removed);\n  const index = group.replacement.indexOf(removed);\n  const run = replacementRunFor(removed, record).filter((node) => {\n    // The translator may revert by re-inserting an original itself; an\n    // original never doubles as its own group's replacement.\n    return !group.originals.some((original) => original.node === node);\n  });\n  if (index >= 0) {\n    group.replacement.splice(index, 1, ...run);\n  } else {\n    group.replacement.push(...run);\n  }\n  for (const node of run) groupByReplacementNode.set(node, group);\n\n  // Full revert: every original is back in the document — the group is moot.\n  if (group.replacement.length === 0 && group.originals.every((original) => original.node.parentNode !== null)) {\n    unregisterGroup(group);\n    return;\n  }\n  if (group.replacement.length === 0) {\n    group.previousSiblingHint = record.previousSibling;\n    group.nextSiblingHint = record.nextSibling;\n  }\n}\n\n/**\n * Text removals with no replacement, seen around confirmed translator\n * activity, are translation deletions (word-order changes drop text nodes —\n * Chromium bug 872770). Track them so React can bring the text back.\n */\nfunction flushPendingOrphans(): void {\n  for (const orphan of pendingOrphans) {\n    if (displaced.has(orphan.removed)) continue;\n    const group: DisplacementGroup = {\n      parent: orphan.parent,\n      originals: [\n        { node: orphan.removed, value: snapshotValue(orphan.removed) },\n        ...(pendingCarrierOriginals.get(orphan.removed) ?? []),\n      ],\n      replacement: [],\n      previousSiblingHint: orphan.previousSibling,\n      nextSiblingHint: orphan.nextSibling,\n      wholeParent: false,\n    };\n    pendingCarrierOriginals.delete(orphan.removed);\n    registerGroup(group);\n  }\n  pendingOrphans = [];\n}\n\n/**\n * Firefox's full-page translator (`merge()` in translations-document.sys.mjs)\n * applies a translation to an element by detaching every child, first to\n * last, then appending the translated nodes in order: live Text nodes are\n * reused BY POSITION with their data overwritten, live elements by identity.\n * Its engine sees adjacent Text nodes as one run of text, so a run of several\n * renderer Text nodes comes back as one — the first node carries the whole\n * run's translation and the rest are never re-appended. They stay detached\n * while the renderer still holds them: the same silent freeze and\n * NotFoundError as Chrome's displacement, from a different mutation shape.\n *\n * The shape is recognised per parent within one batch: removals that each\n * take the first child (previousSibling null) until the parent is empty, then\n * appends (nextSibling null), with at least one removed Text node appended\n * back. Page code can produce that sequence too — a keyed move of a text node\n * that has become an only child is a removal from the front plus an append —\n * so two more things must hold, each of which rules out what the other\n * cannot:\n *\n *  - every Text node appended back was overwritten (a characterData record):\n *    Firefox writes the translation into each node it reuses, while a plain\n *    move changes no text;\n *  - none of the nodes went through the patched DOM methods since records\n *    were last processed (movedByPage): Firefox never calls them, while a\n *    renderer's moves and removals always do — including one that rewrites a\n *    text node in the same commit that moves it.\n *\n * Firefox applies a translation synchronously, so one merge lands in one\n * batch — unless page code runs inside it (a custom element's\n * connectedCallback touching a detached text node drains records midway), in\n * which case the halves are judged separately and may be missed.\n */\ninterface ChildrenMerge {\n  parent: Node;\n  removed: Node[];\n  appended: Node[];\n  records: MutationRecord[];\n  emptied: boolean;\n}\n\n/** Returns the records that belong to recognised merges. */\nfunction recognizeChildrenMerges(records: MutationRecord[]): Set<MutationRecord> {\n  const consumed = new Set<MutationRecord>();\n  const open = new Map<Node, ChildrenMerge>();\n  /**\n   * A reused Text node's value before the merge overwrote it: its first\n   * characterData oldValue in the batch. Collected up front because where\n   * that record falls relative to the node's removal and re-append is not\n   * part of the shape (Firefox overwrites while the node is detached).\n   */\n  const valuesBefore = new Map<Node, string>();\n  for (const record of records) {\n    if (record.type === 'characterData' && record.oldValue !== null && !valuesBefore.has(record.target)) {\n      valuesBefore.set(record.target, record.oldValue);\n    }\n  }\n\n  const close = (merge: ChildrenMerge): void => {\n    open.delete(merge.parent);\n    const removed = new Set(merge.removed);\n    const reusedText = merge.appended.filter((node) => node instanceof Text && removed.has(node));\n    if (reusedText.length === 0 || !reusedText.every((node) => valuesBefore.has(node))) return;\n    if (merge.removed.some((node) => movedByPage.has(node)) || merge.appended.some((node) => movedByPage.has(node))) {\n      return;\n    }\n    for (const record of merge.records) consumed.add(record);\n    markTranslationDetected();\n    registerChildrenMerge(merge, valuesBefore);\n  };\n\n  for (const record of records) {\n    if (record.type !== 'childList') continue;\n    const removedOne =\n      record.addedNodes.length === 0 && record.removedNodes.length === 1 && record.previousSibling === null\n        ? record.removedNodes[0]\n        : undefined;\n    const appendedOne =\n      record.removedNodes.length === 0 && record.addedNodes.length === 1 && record.nextSibling === null\n        ? record.addedNodes[0]\n        : undefined;\n    const merge = open.get(record.target);\n    if (merge && !merge.emptied && removedOne) {\n      merge.removed.push(removedOne);\n      merge.records.push(record);\n      merge.emptied = record.nextSibling === null;\n      continue;\n    }\n    if (merge?.emptied && appendedOne) {\n      merge.appended.push(appendedOne);\n      merge.records.push(record);\n      continue;\n    }\n    if (merge) close(merge);\n    if (removedOne) {\n      open.set(record.target, {\n        parent: record.target,\n        removed: [removedOne],\n        appended: [],\n        records: [record],\n        emptied: record.nextSibling === null,\n      });\n    }\n  }\n  for (const merge of [...open.values()]) close(merge);\n  return consumed;\n}\n\n/**\n * A merge that put every original back and added nothing translated its text\n * in place: the renderer's nodes still stand for themselves, so there is\n * nothing to restore. Otherwise the parent gets a whole-parent group recording\n * its original children and their pre-translation text, restored before any\n * renderer operation on one of them.\n */\nfunction registerChildrenMerge(merge: ChildrenMerge, valuesBefore: Map<Node, string>): void {\n  // A parent merged again before being restored: the earlier group still holds\n  // the renderer's structure and pre-translation text, whereas this merge's\n  // \"before\" values are the earlier translation. Build on the earlier group.\n  let earlier: DisplacementGroup | undefined;\n  for (const node of merge.removed) {\n    const group = displaced.get(node) ?? groupByReplacementNode.get(node);\n    if (group?.wholeParent && group.parent === merge.parent) {\n      earlier = group;\n      break;\n    }\n  }\n  const originals: DisplacedOriginal[] = earlier ? [...earlier.originals] : [];\n  const known = new Set<Node>(originals.map((original) => original.node));\n  const earlierReplacement = new Set<Node>(earlier?.replacement ?? []);\n  for (const node of merge.removed) {\n    if (known.has(node) || earlierReplacement.has(node)) continue;\n    originals.push({ node, value: node instanceof Text ? (valuesBefore.get(node) ?? node.data) : null });\n    known.add(node);\n  }\n  if (earlier) unregisterGroup(earlier);\n\n  const appended = new Set(merge.appended);\n  const replacement = merge.appended.filter((node) => !known.has(node));\n  if (replacement.length === 0 && originals.every((original) => appended.has(original.node))) return;\n  registerGroup({\n    parent: merge.parent,\n    originals,\n    replacement,\n    previousSiblingHint: null,\n    nextSiblingHint: null,\n    wholeParent: true,\n  });\n}\n\n/**\n * Nodes the page moved or removed through the patched DOM methods since\n * records were last processed — never a translator's work (see\n * recognizeChildrenMerges). Noted only while the observer runs, always after\n * the native call has queued its records, and forgotten whenever records are\n * processed, which covers every record those calls queued. Weakly held:\n * mutations the observer never sees (a shadow root, a detached container)\n * leave notes that nothing would otherwise clear.\n */\nlet movedByPage = new WeakSet<Node>();\nlet pageMovesNoted = false;\n\nfunction notePageMove(node: Node): void {\n  if (!observer) return;\n  movedByPage.add(node);\n  pageMovesNoted = true;\n}\n\nfunction forgetPageMoves(): void {\n  if (!pageMovesNoted) return;\n  movedByPage = new WeakSet<Node>();\n  pageMovesNoted = false;\n}\n\n/**\n * Set once Firefox's signal — <html lang> written from outside the page —\n * has been seen. Only then are children merges recognised: nothing else\n * produces them, and page code that happens to empty an element and put some\n * of its text back (through APIs the shim does not patch) must never be read\n * as one on a page Firefox is not translating.\n */\nlet firefoxSignalSeen = false;\nconst NO_RECORDS: ReadonlySet<MutationRecord> = new Set();\n\n/**\n * Firefox's other mark: it tags the elements inside each block it sends to its\n * engine (so it can match them up again), before the translation comes back,\n * and removes the tags when it merges. Blocks of plain text carry none, and a\n * lazy shim is not observing yet when they appear — but it is how an eager\n * shim installed after Firefox's <html lang> write still recognises it.\n */\nconst FIREFOX_ID_ATTRIBUTE = 'data-moz-translations-id';\n\n/**\n * Tags stay on a block from when Firefox sends it until its translation is\n * merged — the whole engine round trip — so an observer starting late most\n * likely finds them already in place rather than seeing them appear.\n */\nfunction noticeFirefoxTags(doc: Document): void {\n  if (firefoxSignalSeen) return;\n  try {\n    if (!doc.querySelector(`[${FIREFOX_ID_ATTRIBUTE}]`)) return;\n  } catch {\n    return;\n  }\n  firefoxSignalSeen = true;\n  emitEvent('Firefox translation markers detected');\n}\n\nfunction processRecords(records: MutationRecord[]): void {\n  try {\n    processRecordBatch(records);\n  } finally {\n    forgetPageMoves();\n  }\n}\n\nfunction processRecordBatch(records: MutationRecord[]): void {\n  if (records.length === 0) return;\n  const now = performance.now();\n  purgeExpired(now);\n\n  if (\n    !firefoxSignalSeen &&\n    records.some((record) => record.type === 'attributes' && record.attributeName === FIREFOX_ID_ATTRIBUTE)\n  ) {\n    firefoxSignalSeen = true;\n    emitEvent('Firefox translation markers detected');\n  }\n  const merged = firefoxSignalSeen ? recognizeChildrenMerges(records) : NO_RECORDS;\n  let sawTranslatorActivity = false;\n  for (const record of records) {\n    if (merged.has(record)) continue;\n    if (record.type === 'childList') {\n      for (const added of record.addedNodes) {\n        if (added.nodeName === 'FONT') sawTranslatorActivity = true;\n        if (record.nextSibling) {\n          const entry = recentInsertedBefore.get(record.nextSibling) ?? { at: now, nodes: [] };\n          entry.at = now;\n          entry.nodes.push(added);\n          // delete-then-set keeps the store in ascending-`at` order (see purgeExpired)\n          recentInsertedBefore.delete(record.nextSibling);\n          recentInsertedBefore.set(record.nextSibling, entry);\n        }\n      }\n    } else if (record.type === 'characterData' && record.oldValue !== null && !recentOldValues.has(record.target)) {\n      recentOldValues.set(record.target, { at: now, value: record.oldValue });\n    }\n  }\n\n  for (const record of records) {\n    if (record.type !== 'childList' || merged.has(record)) continue;\n    for (const removed of record.removedNodes) {\n      const group = groupByReplacementNode.get(removed);\n      if (group) {\n        handleReplacementRemoved(group, removed, record);\n      } else if (removed instanceof Text && !displaced.has(removed)) {\n        if (handleDisplacedText(removed, record, now)) sawTranslatorActivity = true;\n      }\n    }\n  }\n\n  if (sawTranslatorActivity) flushPendingOrphans();\n}\n\n/** Synchronously fold in records the observer hasn't delivered yet. */\nfunction drainPendingRecords(): void {\n  if (observer) {\n    const records = observer.takeRecords();\n    guarded('record processing', () => processRecords(records), undefined);\n  }\n}\n\ntype RestoreResult = 'restored' | 'gone' | 'untracked';\n\nfunction setTextValue(node: Text, value: string): void {\n  domNatives().setData(node, value);\n}\n\n/**\n * Puts a displaced group's original nodes back into the position its\n * replacement run occupies (removing the replacements), so the caller's\n * native DOM operation can proceed on a consistent tree. A whole-parent group\n * rebuilds the parent's child list from its first child on: any node the\n * renderer appended since the merge stays after the originals.\n */\nfunction restoreGroup(group: DisplacementGroup, skipValueFor?: Node): RestoreResult {\n  const natives = domNatives();\n  unregisterGroup(group);\n  for (const original of group.originals) {\n    // Re-adoption makes the node's DOM state authoritative again; correlation\n    // entries recorded while it was displaced would poison future sequences.\n    recentOldValues.delete(original.node);\n    if (original.node instanceof Text) {\n      recentCarrierAccumulated.delete(original.node);\n      pendingCarrierOriginals.delete(original.node);\n    }\n  }\n\n  const attached = group.replacement.filter((node) => node.parentNode === group.parent);\n  let cursor: Node | null;\n  if (group.wholeParent) {\n    // Take the translator's own nodes out first: originals already in order\n    // then stay where they are rather than being moved in front of them —\n    // moving an element re-creates what it hosts (an iframe reloads, a\n    // focused input loses focus).\n    for (const node of attached) natives.removeChild.call(group.parent, node);\n    cursor = group.parent.firstChild;\n  } else if (attached.length > 0) {\n    cursor = attached[0] ?? null;\n  } else if (group.previousSiblingHint?.parentNode === group.parent) {\n    cursor = group.previousSiblingHint.nextSibling;\n  } else if (group.nextSiblingHint?.parentNode === group.parent) {\n    cursor = group.nextSiblingHint;\n  } else if (group.replacement.length === 0 && group.parent.isConnected) {\n    cursor = null; // deleted run with dead hints: append to the parent\n  } else {\n    return 'gone';\n  }\n\n  for (const original of group.originals) {\n    if (original.value !== null && original.node !== skipValueFor && original.node instanceof Text) {\n      setTextValue(original.node, original.value);\n    }\n    if (original.node === cursor) {\n      cursor = original.node.nextSibling;\n      continue;\n    }\n    if (original.node.parentNode !== null && original.node.parentNode !== group.parent) continue;\n    natives.insertBefore.call(group.parent, original.node, cursor);\n  }\n  for (const node of attached) {\n    if (node.parentNode === group.parent && !group.originals.some((original) => original.node === node)) {\n      natives.removeChild.call(group.parent, node);\n    }\n  }\n  return 'restored';\n}\n\nfunction restoreDisplaced(node: Node, skipValue = false): RestoreResult {\n  drainPendingRecords();\n  const group = displaced.get(node);\n  if (!group) return 'untracked';\n  const result = restoreGroup(group, skipValue ? node : undefined);\n  // The restore's own mutations are not translator activity, and read back\n  // they would be misattributed: a translator-created Text node removed after\n  // the originals were inserted before it looks like one the originals\n  // displaced.\n  observer?.takeRecords();\n  return result;\n}\n\n/**\n * Whether a detached node might belong to a displacement group. Text nodes\n * always drain pending records first (a displacement may not be folded in\n * yet). Other nodes only join groups through a Firefox merge, which marks\n * translation detected and is folded in before any renderer task runs — so\n * until then, inserting an element costs nothing extra.\n */\nfunction mayBeDisplaced(node: Node): boolean {\n  return node instanceof Text || (translationDetected && displaced.has(node));\n}\n\n/**\n * Firefox's merge leaves renderer nodes attached that no longer stand for\n * their own content: a reused Text node carries its whole run's translation\n * while the rest of the run is detached, and siblings may be reordered. Any\n * renderer operation on a member of such a group restores the parent first,\n * so the operation lands on the structure the renderer built.\n */\nfunction restoreAttachedMember(node: Node, skipValue = false): void {\n  if (displaced.get(node)?.wholeParent) restoreDisplaced(node, skipValue);\n}\n\nlet uninstallCurrent: (() => void) | null = null;\n\nexport interface TranslationResilienceOptions {\n  document?: Document;\n  /** Observability hook: called with a short message on every non-native path taken. */\n  onEvent?: (message: string) => void;\n  /**\n   * Install the document-wide observer immediately instead of waiting for a\n   * translation signal. The lazy default costs nothing until translation\n   * starts, and arms on Chrome's translated-* class, on Firefox's <html lang>\n   * write from outside the page, and on the translator's own <font> wrappers\n   * for translators that mark nothing (Edge's built-in translator, the Google\n   * Translate extension). eager remains as an escape hatch for a translator\n   * that marks nothing and inserts no recognizable <font> wrapper.\n   */\n  eager?: boolean;\n}\n\n/**\n * Chrome's translator marks the document before it displaces any text: it\n * adds a `translated-ltr`/`translated-rtl` class to <html>, measured\n * ~275-500ms ahead of the first text mutation in real Chrome. The class VALUE\n * is checked (not just \"class changed\") because extensions add unrelated\n * classes to <html> on ordinary page loads — as exact tokens, which are all\n * Google's script ever sets, so a page's own `untranslated-banner` is not\n * taken for Chrome.\n */\nconst TRANSLATED_CLASS = /(?:^|\\s)translated-(?:ltr|rtl)(?:\\s|$)/;\n\nfunction hasTranslatedClass(doc: Document): boolean {\n  // The attribute, not classList: it reads the same on an SVG root, and\n  // touches nothing on <html> (jsdom caches classList as a property).\n  return TRANSLATED_CLASS.test(doc.documentElement.getAttribute('class') ?? '');\n}\n\ntype PageWrite = <T>(write: () => T) => T;\n\n/**\n * Shared by every copy of this package (Symbol.for), on each function it\n * installs on <html>: whether that copy is still tracking, and how to put\n * back what its wrapper replaced. See trackPageAttributeWrites.\n */\nconst WRAPPER_STATE = Symbol.for('translation-resilience.html-write-wrapper');\n\ninterface WrapperState {\n  readonly active: boolean;\n  unwrap(): void;\n}\n\n/**\n * If html[key] is a wrapper from a copy that has stopped tracking, returns\n * the function that removes it. Read defensively: the state may come from a\n * different version of this package.\n */\nfunction inertWrapperOn(html: Element, key: string): (() => void) | undefined {\n  const descriptor = Object.getOwnPropertyDescriptor(html, key);\n  const fn: unknown = descriptor?.value ?? descriptor?.set;\n  if (typeof fn !== 'function') return undefined;\n  const state: unknown = Reflect.get(fn, WRAPPER_STATE);\n  if (typeof state !== 'object' || state === null) return undefined;\n  if (!('active' in state) || state.active !== false || !('unwrap' in state)) return undefined;\n  const { unwrap } = state;\n  if (typeof unwrap !== 'function') return undefined;\n  return () => {\n    unwrap.call(state);\n  };\n}\n\n/**\n * Firefox's translator sets <html lang> to the target language as it starts,\n * well before it touches any text, and marks nothing else a page can see\n * cheaply. But applications write <html lang> too — i18n libraries sync it\n * when language detection resolves and on every switch (WCAG 3.1.1) — so the\n * attribute changing says nothing on its own. Where the write comes from\n * does: the page's own code reaches <html> through the page's JavaScript\n * objects, while a browser translator writes from its isolated world (Chrome,\n * Edge) or through Xray wrappers (Firefox), and neither ever sees a property\n * the page defines on an element.\n *\n * So <html> — that one instance, never Element.prototype, which would tax\n * every attribute write on the page — gets its own wrappers for each Element\n * API that writes attributes, and for the `lang` accessor. A write through a\n * wrapper is the page's own; a lang change that arrives any other way came\n * from outside the page. Writes through an Attr node, a NamedNodeMap, or a\n * prototype method called on <html> directly also count as outside. The only\n * cost of that misclassification is an observer armed early: an outside lang\n * write is never taken as evidence of translation (see translationEvident).\n *\n * A second copy of this package on the page (duplicated versions, micro\n * frontends) wraps the first copy's wrappers rather than skipping them, so\n * both see the page's writes as the page's. Every copy tags its wrappers with\n * WRAPPER_STATE, so whichever order copies go away in, the last one out\n * unwinds the others' inert wrappers too and leaves <html> as it was.\n *\n * Returns a function removing every wrapper.\n */\nfunction trackPageAttributeWrites(html: Element, asPageWrite: PageWrite): () => void {\n  let active = true;\n  const restorers: Array<() => void> = [];\n\n  /**\n   * Defines html[key] as `descriptor` (whose function is `fn`), remembering\n   * what was there — the prototype's, or another copy's wrapper, which ours\n   * calls through to. Removal puts that back, unless another copy has since\n   * wrapped ours: then ours stays, inert, until that copy unwinds it. Any\n   * failure (a non-extensible <html>) leaves the key unwrapped, which only\n   * means writes through it count as outside.\n   */\n  const replace = (key: string, descriptor: PropertyDescriptor, fn: object): void => {\n    guarded(\n      `<html> ${key} wrapper`,\n      () => {\n        const previous = Object.getOwnPropertyDescriptor(html, key);\n        if (previous && !previous.configurable) return;\n        const unwrap = (): void => {\n          if (previous) Object.defineProperty(html, key, previous);\n          else Reflect.deleteProperty(html, key);\n        };\n        const state: WrapperState = {\n          get active() {\n            return active;\n          },\n          unwrap,\n        };\n        Object.defineProperty(fn, WRAPPER_STATE, { value: state });\n        Object.defineProperty(html, key, { configurable: true, enumerable: false, ...descriptor });\n        restorers.push(() => {\n          const current = Object.getOwnPropertyDescriptor(html, key);\n          if (!current || (current.value ?? current.set) !== fn) return;\n          unwrap();\n          // Bounded: the wrappers beneath may come from another version of this package.\n          for (let depth = 0; depth < 16; depth++) {\n            const exposed = inertWrapperOn(html, key);\n            if (!exposed) break;\n            exposed();\n          }\n        });\n      },\n      undefined\n    );\n  };\n\n  const wrap = <A extends unknown[], R>(key: string, current: ((this: Element, ...args: A) => R) | undefined): void => {\n    if (typeof current !== 'function') return;\n    const wrapper = function (this: Element, ...args: A): R {\n      return active && this === html ? asPageWrite(() => current.call(this, ...args)) : current.call(this, ...args);\n    };\n    replace(key, { writable: true, value: wrapper }, wrapper);\n  };\n  wrap('setAttribute', html.setAttribute);\n  wrap('setAttributeNS', html.setAttributeNS);\n  wrap('removeAttribute', html.removeAttribute);\n  wrap('removeAttributeNS', html.removeAttributeNS);\n  wrap('toggleAttribute', html.toggleAttribute);\n  wrap('setAttributeNode', html.setAttributeNode);\n  wrap('setAttributeNodeNS', html.setAttributeNodeNS);\n  wrap('removeAttributeNode', html.removeAttributeNode);\n\n  const view = html.ownerDocument.defaultView;\n  const inherited =\n    view && html instanceof view.HTMLElement\n      ? Object.getOwnPropertyDescriptor(view.HTMLElement.prototype, 'lang')\n      : undefined;\n  const lang = Object.getOwnPropertyDescriptor(html, 'lang') ?? inherited;\n  const getLang = lang?.get;\n  const setLang = lang?.set;\n  if (getLang && setLang) {\n    const set = function (this: Element, value: string): void {\n      if (active && this === html) asPageWrite(() => setLang.call(this, value));\n      else setLang.call(this, value);\n    };\n    replace('lang', { get: getLang, set }, set);\n  }\n\n  return () => {\n    active = false;\n    for (const restore of restorers) guarded('<html> wrapper removal', restore, undefined);\n  };\n}\n\nexport function installTranslationResilience(options: TranslationResilienceOptions = {}): () => void {\n  if (uninstallCurrent) return uninstallCurrent;\n  const natives = domNatives();\n  const doc = options.document ?? document;\n  emitEvent = options.onEvent ?? noopEvent;\n\n  let teardownDetection: () => void = () => undefined;\n  let stopTrackingLang: () => void = () => undefined;\n  /**\n   * Chrome's translator rewrites a lang the page already has, from its\n   * isolated world — right after adding its class, and again after removing\n   * it on \"show original\". Once the class has been seen, a lang write from\n   * outside is Chrome's, never Firefox's signal.\n   */\n  let chromeMarkingSeen = hasTranslatedClass(doc);\n\n  const activateObserver = (): void => {\n    if (observer) return;\n    sentinelActive = false;\n    teardownDetection();\n    teardownDetection = () => undefined;\n    observer = new MutationObserver((records) => {\n      guarded('record processing', () => processRecords(records), undefined);\n    });\n    observer.observe(doc, {\n      childList: true,\n      subtree: true,\n      characterData: true,\n      characterDataOldValue: true,\n      attributes: true,\n      attributeFilter: [FIREFOX_ID_ATTRIBUTE],\n    });\n    emitEvent('translation signal detected, observing document');\n    noticeFirefoxTags(doc);\n  };\n\n  /**\n   * Same-realm translators (the bundled simulator, or anything else calling\n   * the patched DOM methods directly) can displace text in the same task that\n   * sets the signal — before the sentinel's microtask callback runs. Real\n   * Chrome translation runs in an isolated world with a large gap between\n   * signal and displacement, so this synchronous fallback is only load\n   * bearing for same-realm use: it reads one attribute while dormant and\n   * costs a boolean check once active.\n   */\n  const sentinelSyncCheck = (): void => {\n    if (sentinelActive && hasTranslatedClass(doc)) activateObserver();\n  };\n\n  /**\n   * `pageWrite` is true for records produced inside one of the page's own\n   * writes to <html>; a lang record anywhere else is a translator (Firefox)\n   * starting, which it does well before it changes any text. That is also the\n   * one thing that turns on recognition of Firefox's merges, so lang is\n   * watched until it happens — even once something else has armed the\n   * observer, and in eager mode.\n   */\n  const onSentinelRecords = (records: MutationRecord[], pageWrite: boolean): void => {\n    if (hasTranslatedClass(doc)) chromeMarkingSeen = true;\n    if (!pageWrite && !chromeMarkingSeen && records.some((record) => record.attributeName === 'lang')) {\n      emitEvent('<html lang> changed from outside the page');\n      firefoxSignalSeen = true;\n      stopTrackingLang();\n      activateObserver();\n      return;\n    }\n    if (hasTranslatedClass(doc)) activateObserver();\n  };\n\n  /**\n   * Brackets one of the page's own writes to <html>: records already queued\n   * are someone else's and are handled first; the records the write itself\n   * produces are taken synchronously, before the sentinel's callback could\n   * see them, and handled as the page's.\n   */\n  const asPageWrite: PageWrite = (write) => {\n    const before = sentinelObserver?.takeRecords() ?? [];\n    if (before.length > 0) guarded('sentinel processing', () => onSentinelRecords(before, false), undefined);\n    try {\n      return write();\n    } finally {\n      const own = sentinelObserver?.takeRecords() ?? [];\n      if (own.length > 0) guarded('sentinel processing', () => onSentinelRecords(own, true), undefined);\n    }\n  };\n\n  /**\n   * Not every translator marks <html> before it displaces text. Chrome's\n   * built-in Google Translate does (the translated-* class above), but\n   * Microsoft Edge's built-in translator and the Google Translate browser\n   * extension wrap text in <font> elements WITHOUT adding a translated-* class\n   * — so the attribute sentinel never fires and the shim would\n   * stay dormant while the page is actively being translated, letting the\n   * renderer crash exactly as it would with no shim (reported in production on\n   * Edge). A <font> carrying a translator's signature (isTranslatorFontWrapper)\n   * entering the tree is an unambiguous translation signal, so arm on it too.\n   * Called before the native insertion runs, so the observer is watching in\n   * time to record this very displacement; and translationDetected is set\n   * directly, so the crash-avoidance paths engage even for a translator whose\n   * mutation shape the observer does not recognise as a displacement group\n   * (Edge structures its wrapping differently from Chrome). The cost while\n   * dormant is a nodeName comparison per insert — far cheaper than running the\n   * full observer eagerly for the whole page lifetime.\n   */\n  const noticeTranslatorFont = (inserted: Node): void => {\n    if (translationDetected || !isTranslatorFontWrapper(inserted)) return;\n    activateObserver();\n    markTranslationDetected();\n  };\n\n  /**\n   * The signal that actually covers real browsers. The translator inserts its\n   * signature <font> from its own isolated world, which the patched methods\n   * above never see, but the shared DOM raises `animationstart` for it via\n   * DETECTION_CSS regardless of which world made the change.\n   */\n  const onDetectionAnimation = (event: AnimationEvent): void => {\n    if (event.animationName !== DETECTION_ANIMATION_NAME) return;\n    guarded(\n      'detection animation',\n      () => {\n        if (translationDetected) return;\n        emitEvent('translator font detected via detection stylesheet');\n        activateObserver();\n        markTranslationDetected();\n      },\n      undefined\n    );\n  };\n\n  /**\n   * Last line of defence, consulted only where the native call is about to\n   * throw NotFoundError. Two cases reach here even with the detection\n   * stylesheet installed: `animationstart` is delivered on the next style\n   * update, so a renderer commit in the same task as the displacement can\n   * still arrive first; and a translator that displaces text without emitting\n   * a recognisable <font> raises no animation at all. Sweeping the document\n   * for translator evidence at that point is what separates \"a translator\n   * moved this node\" from a genuine renderer bug — so the shim degrades\n   * gracefully on translated pages while still throwing on untranslated ones.\n   * A <html lang> change from outside the page is deliberately NOT evidence:\n   * it only arms the observer. Firefox's first merge marks translation\n   * detected, while a write merely misattributed to outside the page (see\n   * trackPageAttributeWrites) must not start masking genuine bugs.\n   */\n  const translationEvident = (): boolean => {\n    if (translationDetected) return true;\n    if (!documentShowsTranslation(doc)) return false;\n    emitEvent('translation evidence found on repair path');\n    activateObserver();\n    markTranslationDetected();\n    return true;\n  };\n\n  const sentinel = new MutationObserver((records) => {\n    guarded('sentinel processing', () => onSentinelRecords(records, false), undefined);\n  });\n  sentinelObserver = sentinel;\n  sentinel.observe(doc.documentElement, { attributes: true, attributeFilter: ['lang', 'class'] });\n  const stopTrackingPageWrites = trackPageAttributeWrites(doc.documentElement, asPageWrite);\n  stopTrackingLang = () => {\n    stopTrackingLang = () => undefined;\n    sentinel.disconnect();\n    if (sentinelObserver === sentinel) sentinelObserver = null;\n    stopTrackingPageWrites();\n  };\n\n  if (options.eager || hasTranslatedClass(doc)) {\n    activateObserver();\n  } else {\n    sentinelActive = true;\n    const removeStylesheet = installDetectionStylesheet(doc);\n    doc.addEventListener('animationstart', onDetectionAnimation, true);\n    teardownDetection = () => {\n      removeStylesheet();\n      doc.removeEventListener('animationstart', onDetectionAnimation, true);\n    };\n  }\n\n  Node.prototype.removeChild = function removeChild<T extends Node>(this: Node, child: T): T {\n    sentinelSyncCheck();\n    if (child.parentNode !== this) {\n      const outcome = guarded(\n        'removeChild repair',\n        (): 'native' | 'handled' => {\n          const result = mayBeDisplaced(child) ? restoreDisplaced(child) : 'untracked';\n          if (result === 'gone') {\n            // The displaced content is already absent, which is what this removal wanted.\n            emitEvent('removeChild: displaced text already gone, removal skipped');\n            return 'handled';\n          }\n          if (result === 'restored' && child.parentNode === this) return 'native';\n          if (translationEvident()) {\n            // Either translation moved this node somewhere we could not track\n            // (e.g. a word-order change), or restoring it put it back under a\n            // different parent. Remove it from wherever it actually is.\n            emitEvent('removeChild: removing node from its actual parent');\n            if (child.parentNode) natives.removeChild.call(child.parentNode, child);\n            notePageMove(child);\n            return 'handled';\n          }\n          return 'native';\n        },\n        'native'\n      );\n      if (outcome === 'handled') return child;\n    } else if (translationDetected) {\n      guarded('removeChild member restore', () => restoreAttachedMember(child), undefined);\n    }\n    natives.removeChild.call(this, child);\n    notePageMove(child);\n    return child;\n  };\n\n  Node.prototype.insertBefore = function insertBefore<T extends Node>(this: Node, node: T, child: Node | null): T {\n    sentinelSyncCheck();\n    noticeTranslatorFont(node);\n    if (node.parentNode === null) {\n      if (mayBeDisplaced(node)) guarded('insertBefore node repair', () => restoreDisplaced(node), 'untracked');\n    } else if (translationDetected) {\n      guarded('insertBefore node restore', () => restoreAttachedMember(node), undefined);\n    }\n    if (child && child.parentNode !== this) {\n      const outcome = guarded(\n        'insertBefore reference repair',\n        (): 'native' | 'handled' => {\n          const result = mayBeDisplaced(child) ? restoreDisplaced(child) : 'untracked';\n          if (result === 'restored' && child.parentNode === this) return 'native';\n          if (translationEvident()) {\n            // The reference node is unrecoverable, or restoring it put it back\n            // under a different parent; appending keeps the new node in the\n            // right parent, which is the best position still guaranteed.\n            emitEvent('insertBefore: reference gone, appending instead');\n            natives.appendChild.call(this, node);\n            notePageMove(node);\n            return 'handled';\n          }\n          return 'native';\n        },\n        'native'\n      );\n      if (outcome === 'handled') return node;\n    } else if (child && translationDetected) {\n      guarded('insertBefore reference restore', () => restoreAttachedMember(child), undefined);\n    }\n    natives.insertBefore.call(this, node, child);\n    notePageMove(node);\n    return node;\n  };\n\n  Node.prototype.appendChild = function appendChild<T extends Node>(this: Node, node: T): T {\n    sentinelSyncCheck();\n    noticeTranslatorFont(node);\n    if (node.parentNode === null) {\n      if (mayBeDisplaced(node)) guarded('appendChild repair', () => restoreDisplaced(node), 'untracked');\n    } else if (translationDetected) {\n      guarded('appendChild node restore', () => restoreAttachedMember(node), undefined);\n    }\n    natives.appendChild.call(this, node);\n    notePageMove(node);\n    return node;\n  };\n\n  const restoreAfterWrite = (node: Node): void => {\n    if (!(node instanceof Text)) return;\n    if (node.parentNode === null) {\n      guarded('text write repair', () => restoreDisplaced(node, true), 'untracked');\n    } else if (translationDetected) {\n      guarded('text write restore', () => restoreAttachedMember(node, true), undefined);\n    }\n  };\n\n  Object.defineProperty(Node.prototype, 'nodeValue', {\n    configurable: true,\n    enumerable: natives.nodeValueDescriptor.enumerable,\n    get: natives.nodeValueDescriptor.get,\n    set(this: Node, value: string | null) {\n      sentinelSyncCheck();\n      natives.setNodeValue(this, value);\n      restoreAfterWrite(this);\n    },\n  });\n\n  Object.defineProperty(CharacterData.prototype, 'data', {\n    configurable: true,\n    enumerable: natives.dataDescriptor.enumerable,\n    get: natives.dataDescriptor.get,\n    set(this: CharacterData, value: string) {\n      sentinelSyncCheck();\n      natives.setData(this, value);\n      restoreAfterWrite(this);\n    },\n  });\n\n  uninstallCurrent = () => {\n    teardownDetection();\n    teardownDetection = () => undefined;\n    stopTrackingLang();\n    observer?.disconnect();\n    observer = null;\n    sentinelObserver?.disconnect();\n    sentinelObserver = null;\n    sentinelActive = false;\n    translationDetected = false;\n    firefoxSignalSeen = false;\n    emitEvent = noopEvent;\n    clearCorrelationState();\n    Node.prototype.removeChild = natives.removeChild;\n    Node.prototype.insertBefore = natives.insertBefore;\n    Node.prototype.appendChild = natives.appendChild;\n    Object.defineProperty(Node.prototype, 'nodeValue', natives.nodeValueDescriptor);\n    Object.defineProperty(CharacterData.prototype, 'data', natives.dataDescriptor);\n    uninstallCurrent = null;\n  };\n  return uninstallCurrent;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqGA,IAAM,YAAY,oBAAI,QAAiC;AACvD,IAAM,yBAAyB,oBAAI,QAAiC;AAEpE,IAAM,0BAA0B,oBAAI,QAAmC;AAEvE,IAAI,WAAoC;AACxC,IAAI,mBAA4C;AAEhD,IAAI,iBAAiB;AACrB,IAAI,sBAAsB;AAC1B,IAAM,YAAY,CAAC,aAA2B;AAC9C,IAAI,YAAuC;AAY3C,IAAI,kBAAqC;AAOzC,SAAS,aAAyB;AAChC,MAAI,gBAAiB,QAAO;AAC5B,MAAI,OAAO,SAAS,eAAe,OAAO,kBAAkB,aAAa;AACvE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,sBAAsB,OAAO,yBAAyB,KAAK,WAAW,WAAW;AACvF,QAAM,iBAAiB,OAAO,yBAAyB,cAAc,WAAW,MAAM;AACtF,QAAM,eAAe,2DAAqB;AAC1C,QAAM,UAAU,iDAAgB;AAChC,MAAI,EAAC,2DAAqB,QAAO,CAAC,gBAAgB,EAAC,iDAAgB,QAAO,CAAC,SAAS;AAClF,UAAM,IAAI,MAAM,8EAA8E;AAAA,EAChG;AACA,oBAAkB;AAAA,IAChB,cAAc,KAAK,UAAU;AAAA,IAC7B,aAAa,KAAK,UAAU;AAAA,IAC5B,aAAa,KAAK,UAAU;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,cAAc,CAAC,MAAM,UAAU,aAAa,KAAK,MAAM,KAAK;AAAA,IAC5D,SAAS,CAAC,MAAM,UAAU,QAAQ,KAAK,MAAM,KAAK;AAAA,EACpD;AACA,SAAO;AACT;AAOA,SAAS,cAAc,OAAwB;AAC7C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,QAAW,WAAmB,KAAc,UAAgB;AACnE,MAAI;AACF,WAAO,IAAI;AAAA,EACb,SAAS,OAAO;AACd,cAAU,qBAAqB,SAAS,KAAK,cAAc,KAAK,CAAC,EAAE;AACnE,WAAO;AAAA,EACT;AACF;AAEA,SAAS,0BAAgC;AACvC,MAAI,oBAAqB;AACzB,wBAAsB;AACtB,YAAU,+BAA+B;AAC3C;AAEA,SAAS,cAAc,OAAgC;AACrD,0BAAwB;AACxB,aAAW,YAAY,MAAM,UAAW,WAAU,IAAI,SAAS,MAAM,KAAK;AAC1E,aAAW,QAAQ,MAAM,YAAa,wBAAuB,IAAI,MAAM,KAAK;AAC9E;AAEA,SAAS,gBAAgB,OAAgC;AACvD,aAAW,YAAY,MAAM,UAAW,WAAU,OAAO,SAAS,IAAI;AACtE,aAAW,QAAQ,MAAM,YAAa,wBAAuB,OAAO,IAAI;AAC1E;AAUA,IAAM,wBAAwB;AA6B9B,IAAM,uBAAuB,oBAAI,IAAoB;AAErD,IAAM,kBAAkB,oBAAI,IAAsB;AAElD,IAAM,2BAA2B,oBAAI,IAAsB;AAE3D,IAAI,iBAAkC,CAAC;AAEvC,SAAS,aAAa,KAAmB;AACvC,aAAW,CAAC,KAAK,KAAK,KAAK,sBAAsB;AAC/C,QAAI,MAAM,MAAM,MAAM,sBAAuB;AAC7C,yBAAqB,OAAO,GAAG;AAAA,EACjC;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,iBAAiB;AAC1C,QAAI,MAAM,MAAM,MAAM,sBAAuB;AAC7C,oBAAgB,OAAO,GAAG;AAAA,EAC5B;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,0BAA0B;AACnD,QAAI,MAAM,MAAM,MAAM,sBAAuB;AAC7C,6BAAyB,OAAO,GAAG;AAAA,EACrC;AACA,QAAM,aAAa,eAAe,UAAU,CAAC,WAAW,MAAM,OAAO,MAAM,qBAAqB;AAChG,MAAI,eAAe,IAAI;AACrB,QAAI,eAAe,SAAS,EAAG,kBAAiB,CAAC;AAAA,EACnD,WAAW,aAAa,GAAG;AACzB,qBAAiB,eAAe,MAAM,UAAU;AAAA,EAClD;AACF;AAEA,SAAS,wBAA8B;AACrC,uBAAqB,MAAM;AAC3B,kBAAgB,MAAM;AACtB,2BAAyB,MAAM;AAC/B,mBAAiB,CAAC;AAClB,kBAAgB;AAClB;AAGA,SAAS,+BAA+B,MAAqB;AAC3D,SAAO,gBAAgB,QAAQ,KAAK,aAAa;AACnD;AAgBA,SAAS,wBAAwB,MAAqB;AACpD,MAAI,KAAK,aAAa,UAAU,EAAE,gBAAgB,aAAc,QAAO;AACvE,SACE,KAAK,MAAM,kBAAkB,aAC7B,KAAK,aAAa,cAAc,KAChC,KAAK,aAAa,UAAU,KAC5B,KAAK,aAAa,cAAc;AAEpC;AAMA,IAAM,2BAA2B;AAEjC,IAAM,2BAA2B;AAsBjC,IAAM,gBACJ,cAAc,wBAAwB,iCACnC,wBAAwB,oDAAoD,wBAAwB;AAQzG,SAAS,2BAA2B,KAA2B;AA7U/D;AA8UE,QAAM,OAAO,IAAI;AACjB,MAAI;AACF,QAAI,QAAQ,OAAO,KAAK,kBAAkB,cAAc,MAAM,QAAQ,IAAI,kBAAkB,GAAG;AAC7F,YAAM,QAAQ,IAAI,KAAK,cAAc;AACrC,YAAM,YAAY,aAAa;AAC/B,UAAI,qBAAqB,CAAC,GAAG,IAAI,oBAAoB,KAAK;AAC1D,aAAO,MAAM;AACX,YAAI,qBAAqB,IAAI,mBAAmB,OAAO,CAAC,cAAc,cAAc,KAAK;AAAA,MAC3F;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,cAAU,sDAAsD,cAAc,KAAK,CAAC,GAAG;AAAA,EACzF;AACA,MAAI;AACF,UAAM,QAAQ,IAAI,cAAc,OAAO;AACvC,UAAM,cAAc;AACpB,MAAC,SAAI,SAAJ,YAAY,IAAI,iBAAiB,YAAY,KAAK;AACnD,WAAO,MAAM,MAAM,OAAO;AAAA,EAC5B,SAAS,OAAO;AAEd,cAAU,wCAAwC,cAAc,KAAK,CAAC,GAAG;AACzE,WAAO,MAAM;AAAA,EACf;AACF;AAOA,SAAS,yBAAyB,KAAwB;AACxD,MAAI;AACF,WAAO,IAAI,cAAc,wBAAwB,MAAM;AAAA,EACzD,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,SAAS,kBAAkB,SAAe,QAAgC;AACxE,MAAI,OAAO,aAAa,WAAW,KAAK,OAAO,WAAW,WAAW,GAAG;AACtE,UAAM,QAAQ,OAAO,WAAW,CAAC;AACjC,WAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;AAAA,EAC5B;AACA,QAAM,QAAQ,qBAAqB,IAAI,OAAO;AAC9C,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,uBAAqB,OAAO,OAAO;AACnC,SAAO,MAAM,MAAM,OAAO,8BAA8B;AAC1D;AAUA,SAAS,gBAAgB,SAAe,QAAwB,KAA0B;AAhZ1F;AAiZE,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,WAAW,EAAE,mBAAmB,MAAO,QAAO;AACnD,QAAM,wBAAuB,qBAAgB,IAAI,OAAO,MAA3B,mBAA8B;AAC3D,MAAI,yBAAyB,OAAW,QAAO;AAC/C,QAAM,gBAAe,oCAAyB,IAAI,OAAO,MAApC,mBAAuC,UAAvC,YAAgD,MAAM,cAAc,OAAO;AAChG,MAAI,GAAE,aAAQ,cAAR,YAAqB,IAAI,WAAW,uBAAuB,WAAW,EAAG,QAAO;AAEtF,2BAAyB,OAAO,OAAO;AACvC,2BAAyB,IAAI,SAAS,EAAE,IAAI,KAAK,OAAO,YAAY,CAAC;AACrE,SAAO;AACT;AAEA,SAAS,cAAc,MAAoB;AA7Z3C;AA8ZE,UAAO,iCAAgB,IAAI,IAAI,MAAxB,mBAA2B,UAA3B,YAAoC,KAAK,cAAzC,YAAsD;AAC/D;AAGA,SAAS,oBAAoB,SAAe,QAAwB,KAAsB;AAla1F;AAmaE,QAAM,MAAM,kBAAkB,SAAS,MAAM;AAC7C,MAAI,IAAI,SAAS,GAAG;AAClB,UAAM,QAA2B;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,WAAW,CAAC,EAAE,MAAM,SAAS,OAAO,cAAc,OAAO,EAAE,GAAG,IAAI,6BAAwB,IAAI,OAAO,MAAnC,YAAwC,CAAC,CAAE;AAAA,MAC7G,aAAa;AAAA,MACb,qBAAqB,OAAO;AAAA,MAC5B,iBAAiB,OAAO;AAAA,MACxB,aAAa;AAAA,IACf;AACA,4BAAwB,OAAO,OAAO;AACtC,kBAAc,KAAK;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,gBAAgB,SAAS,QAAQ,GAAG;AACpD,MAAI,SAAS;AACX,UAAM,WAAU,6BAAwB,IAAI,OAAO,MAAnC,YAAwC,CAAC;AACzD,YAAQ,KAAK,EAAE,MAAM,SAAS,OAAO,cAAc,OAAO,EAAE,GAAG,IAAI,6BAAwB,IAAI,OAAO,MAAnC,YAAwC,CAAC,CAAE;AAC9G,4BAAwB,OAAO,OAAO;AACtC,4BAAwB,IAAI,SAAS,OAAO;AAC5C,WAAO;AAAA,EACT;AAEA,iBAAe,KAAK;AAAA,IAClB,IAAI;AAAA,IACJ,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,iBAAiB,OAAO;AAAA,IACxB,aAAa,OAAO;AAAA,EACtB,CAAC;AACD,SAAO;AACT;AAEA,SAAS,yBAAyB,OAA0B,SAAe,QAA8B;AACvG,yBAAuB,OAAO,OAAO;AACrC,QAAM,QAAQ,MAAM,YAAY,QAAQ,OAAO;AAC/C,QAAM,MAAM,kBAAkB,SAAS,MAAM,EAAE,OAAO,CAAC,SAAS;AAG9D,WAAO,CAAC,MAAM,UAAU,KAAK,CAAC,aAAa,SAAS,SAAS,IAAI;AAAA,EACnE,CAAC;AACD,MAAI,SAAS,GAAG;AACd,UAAM,YAAY,OAAO,OAAO,GAAG,GAAG,GAAG;AAAA,EAC3C,OAAO;AACL,UAAM,YAAY,KAAK,GAAG,GAAG;AAAA,EAC/B;AACA,aAAW,QAAQ,IAAK,wBAAuB,IAAI,MAAM,KAAK;AAG9D,MAAI,MAAM,YAAY,WAAW,KAAK,MAAM,UAAU,MAAM,CAAC,aAAa,SAAS,KAAK,eAAe,IAAI,GAAG;AAC5G,oBAAgB,KAAK;AACrB;AAAA,EACF;AACA,MAAI,MAAM,YAAY,WAAW,GAAG;AAClC,UAAM,sBAAsB,OAAO;AACnC,UAAM,kBAAkB,OAAO;AAAA,EACjC;AACF;AAOA,SAAS,sBAA4B;AAperC;AAqeE,aAAW,UAAU,gBAAgB;AACnC,QAAI,UAAU,IAAI,OAAO,OAAO,EAAG;AACnC,UAAM,QAA2B;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,WAAW;AAAA,QACT,EAAE,MAAM,OAAO,SAAS,OAAO,cAAc,OAAO,OAAO,EAAE;AAAA,QAC7D,IAAI,6BAAwB,IAAI,OAAO,OAAO,MAA1C,YAA+C,CAAC;AAAA,MACtD;AAAA,MACA,aAAa,CAAC;AAAA,MACd,qBAAqB,OAAO;AAAA,MAC5B,iBAAiB,OAAO;AAAA,MACxB,aAAa;AAAA,IACf;AACA,4BAAwB,OAAO,OAAO,OAAO;AAC7C,kBAAc,KAAK;AAAA,EACrB;AACA,mBAAiB,CAAC;AACpB;AA2CA,SAAS,wBAAwB,SAAgD;AAC/E,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,OAAO,oBAAI,IAAyB;AAO1C,QAAM,eAAe,oBAAI,IAAkB;AAC3C,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS,mBAAmB,OAAO,aAAa,QAAQ,CAAC,aAAa,IAAI,OAAO,MAAM,GAAG;AACnG,mBAAa,IAAI,OAAO,QAAQ,OAAO,QAAQ;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC,UAA+B;AAC5C,SAAK,OAAO,MAAM,MAAM;AACxB,UAAM,UAAU,IAAI,IAAI,MAAM,OAAO;AACrC,UAAM,aAAa,MAAM,SAAS,OAAO,CAAC,SAAS,gBAAgB,QAAQ,QAAQ,IAAI,IAAI,CAAC;AAC5F,QAAI,WAAW,WAAW,KAAK,CAAC,WAAW,MAAM,CAAC,SAAS,aAAa,IAAI,IAAI,CAAC,EAAG;AACpF,QAAI,MAAM,QAAQ,KAAK,CAAC,SAAS,YAAY,IAAI,IAAI,CAAC,KAAK,MAAM,SAAS,KAAK,CAAC,SAAS,YAAY,IAAI,IAAI,CAAC,GAAG;AAC/G;AAAA,IACF;AACA,eAAW,UAAU,MAAM,QAAS,UAAS,IAAI,MAAM;AACvD,4BAAwB;AACxB,0BAAsB,OAAO,YAAY;AAAA,EAC3C;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS,YAAa;AACjC,UAAM,aACJ,OAAO,WAAW,WAAW,KAAK,OAAO,aAAa,WAAW,KAAK,OAAO,oBAAoB,OAC7F,OAAO,aAAa,CAAC,IACrB;AACN,UAAM,cACJ,OAAO,aAAa,WAAW,KAAK,OAAO,WAAW,WAAW,KAAK,OAAO,gBAAgB,OACzF,OAAO,WAAW,CAAC,IACnB;AACN,UAAM,QAAQ,KAAK,IAAI,OAAO,MAAM;AACpC,QAAI,SAAS,CAAC,MAAM,WAAW,YAAY;AACzC,YAAM,QAAQ,KAAK,UAAU;AAC7B,YAAM,QAAQ,KAAK,MAAM;AACzB,YAAM,UAAU,OAAO,gBAAgB;AACvC;AAAA,IACF;AACA,SAAI,+BAAO,YAAW,aAAa;AACjC,YAAM,SAAS,KAAK,WAAW;AAC/B,YAAM,QAAQ,KAAK,MAAM;AACzB;AAAA,IACF;AACA,QAAI,MAAO,OAAM,KAAK;AACtB,QAAI,YAAY;AACd,WAAK,IAAI,OAAO,QAAQ;AAAA,QACtB,QAAQ,OAAO;AAAA,QACf,SAAS,CAAC,UAAU;AAAA,QACpB,UAAU,CAAC;AAAA,QACX,SAAS,CAAC,MAAM;AAAA,QAChB,SAAS,OAAO,gBAAgB;AAAA,MAClC,CAAC;AAAA,IACH;AAAA,EACF;AACA,aAAW,SAAS,CAAC,GAAG,KAAK,OAAO,CAAC,EAAG,OAAM,KAAK;AACnD,SAAO;AACT;AASA,SAAS,sBAAsB,OAAsB,cAAuC;AA1mB5F;AA8mBE,MAAI;AACJ,aAAW,QAAQ,MAAM,SAAS;AAChC,UAAM,SAAQ,eAAU,IAAI,IAAI,MAAlB,YAAuB,uBAAuB,IAAI,IAAI;AACpE,SAAI,+BAAO,gBAAe,MAAM,WAAW,MAAM,QAAQ;AACvD,gBAAU;AACV;AAAA,IACF;AAAA,EACF;AACA,QAAM,YAAiC,UAAU,CAAC,GAAG,QAAQ,SAAS,IAAI,CAAC;AAC3E,QAAM,QAAQ,IAAI,IAAU,UAAU,IAAI,CAAC,aAAa,SAAS,IAAI,CAAC;AACtE,QAAM,qBAAqB,IAAI,KAAU,wCAAS,gBAAT,YAAwB,CAAC,CAAC;AACnE,aAAW,QAAQ,MAAM,SAAS;AAChC,QAAI,MAAM,IAAI,IAAI,KAAK,mBAAmB,IAAI,IAAI,EAAG;AACrD,cAAU,KAAK,EAAE,MAAM,OAAO,gBAAgB,QAAQ,kBAAa,IAAI,IAAI,MAArB,YAA0B,KAAK,OAAQ,KAAK,CAAC;AACnG,UAAM,IAAI,IAAI;AAAA,EAChB;AACA,MAAI,QAAS,iBAAgB,OAAO;AAEpC,QAAM,WAAW,IAAI,IAAI,MAAM,QAAQ;AACvC,QAAM,cAAc,MAAM,SAAS,OAAO,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC;AACpE,MAAI,YAAY,WAAW,KAAK,UAAU,MAAM,CAAC,aAAa,SAAS,IAAI,SAAS,IAAI,CAAC,EAAG;AAC5F,gBAAc;AAAA,IACZ,QAAQ,MAAM;AAAA,IACd;AAAA,IACA;AAAA,IACA,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,aAAa;AAAA,EACf,CAAC;AACH;AAWA,IAAI,cAAc,oBAAI,QAAc;AACpC,IAAI,iBAAiB;AAErB,SAAS,aAAa,MAAkB;AACtC,MAAI,CAAC,SAAU;AACf,cAAY,IAAI,IAAI;AACpB,mBAAiB;AACnB;AAEA,SAAS,kBAAwB;AAC/B,MAAI,CAAC,eAAgB;AACrB,gBAAc,oBAAI,QAAc;AAChC,mBAAiB;AACnB;AASA,IAAI,oBAAoB;AACxB,IAAM,aAA0C,oBAAI,IAAI;AASxD,IAAM,uBAAuB;AAO7B,SAAS,kBAAkB,KAAqB;AAC9C,MAAI,kBAAmB;AACvB,MAAI;AACF,QAAI,CAAC,IAAI,cAAc,IAAI,oBAAoB,GAAG,EAAG;AAAA,EACvD,SAAQ;AACN;AAAA,EACF;AACA,sBAAoB;AACpB,YAAU,sCAAsC;AAClD;AAEA,SAAS,eAAe,SAAiC;AACvD,MAAI;AACF,uBAAmB,OAAO;AAAA,EAC5B,UAAE;AACA,oBAAgB;AAAA,EAClB;AACF;AAEA,SAAS,mBAAmB,SAAiC;AAhtB7D;AAitBE,MAAI,QAAQ,WAAW,EAAG;AAC1B,QAAM,MAAM,YAAY,IAAI;AAC5B,eAAa,GAAG;AAEhB,MACE,CAAC,qBACD,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,gBAAgB,OAAO,kBAAkB,oBAAoB,GACtG;AACA,wBAAoB;AACpB,cAAU,sCAAsC;AAAA,EAClD;AACA,QAAM,SAAS,oBAAoB,wBAAwB,OAAO,IAAI;AACtE,MAAI,wBAAwB;AAC5B,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,IAAI,MAAM,EAAG;AACxB,QAAI,OAAO,SAAS,aAAa;AAC/B,iBAAW,SAAS,OAAO,YAAY;AACrC,YAAI,MAAM,aAAa,OAAQ,yBAAwB;AACvD,YAAI,OAAO,aAAa;AACtB,gBAAM,SAAQ,0BAAqB,IAAI,OAAO,WAAW,MAA3C,YAAgD,EAAE,IAAI,KAAK,OAAO,CAAC,EAAE;AACnF,gBAAM,KAAK;AACX,gBAAM,MAAM,KAAK,KAAK;AAEtB,+BAAqB,OAAO,OAAO,WAAW;AAC9C,+BAAqB,IAAI,OAAO,aAAa,KAAK;AAAA,QACpD;AAAA,MACF;AAAA,IACF,WAAW,OAAO,SAAS,mBAAmB,OAAO,aAAa,QAAQ,CAAC,gBAAgB,IAAI,OAAO,MAAM,GAAG;AAC7G,sBAAgB,IAAI,OAAO,QAAQ,EAAE,IAAI,KAAK,OAAO,OAAO,SAAS,CAAC;AAAA,IACxE;AAAA,EACF;AAEA,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS,eAAe,OAAO,IAAI,MAAM,EAAG;AACvD,eAAW,WAAW,OAAO,cAAc;AACzC,YAAM,QAAQ,uBAAuB,IAAI,OAAO;AAChD,UAAI,OAAO;AACT,iCAAyB,OAAO,SAAS,MAAM;AAAA,MACjD,WAAW,mBAAmB,QAAQ,CAAC,UAAU,IAAI,OAAO,GAAG;AAC7D,YAAI,oBAAoB,SAAS,QAAQ,GAAG,EAAG,yBAAwB;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,sBAAuB,qBAAoB;AACjD;AAGA,SAAS,sBAA4B;AACnC,MAAI,UAAU;AACZ,UAAM,UAAU,SAAS,YAAY;AACrC,YAAQ,qBAAqB,MAAM,eAAe,OAAO,GAAG,MAAS;AAAA,EACvE;AACF;AAIA,SAAS,aAAa,MAAY,OAAqB;AACrD,aAAW,EAAE,QAAQ,MAAM,KAAK;AAClC;AASA,SAAS,aAAa,OAA0B,cAAoC;AArxBpF;AAsxBE,QAAM,UAAU,WAAW;AAC3B,kBAAgB,KAAK;AACrB,aAAW,YAAY,MAAM,WAAW;AAGtC,oBAAgB,OAAO,SAAS,IAAI;AACpC,QAAI,SAAS,gBAAgB,MAAM;AACjC,+BAAyB,OAAO,SAAS,IAAI;AAC7C,8BAAwB,OAAO,SAAS,IAAI;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,YAAY,OAAO,CAAC,SAAS,KAAK,eAAe,MAAM,MAAM;AACpF,MAAI;AACJ,MAAI,MAAM,aAAa;AAKrB,eAAW,QAAQ,SAAU,SAAQ,YAAY,KAAK,MAAM,QAAQ,IAAI;AACxE,aAAS,MAAM,OAAO;AAAA,EACxB,WAAW,SAAS,SAAS,GAAG;AAC9B,cAAS,cAAS,CAAC,MAAV,YAAe;AAAA,EAC1B,aAAW,WAAM,wBAAN,mBAA2B,gBAAe,MAAM,QAAQ;AACjE,aAAS,MAAM,oBAAoB;AAAA,EACrC,aAAW,WAAM,oBAAN,mBAAuB,gBAAe,MAAM,QAAQ;AAC7D,aAAS,MAAM;AAAA,EACjB,WAAW,MAAM,YAAY,WAAW,KAAK,MAAM,OAAO,aAAa;AACrE,aAAS;AAAA,EACX,OAAO;AACL,WAAO;AAAA,EACT;AAEA,aAAW,YAAY,MAAM,WAAW;AACtC,QAAI,SAAS,UAAU,QAAQ,SAAS,SAAS,gBAAgB,SAAS,gBAAgB,MAAM;AAC9F,mBAAa,SAAS,MAAM,SAAS,KAAK;AAAA,IAC5C;AACA,QAAI,SAAS,SAAS,QAAQ;AAC5B,eAAS,SAAS,KAAK;AACvB;AAAA,IACF;AACA,QAAI,SAAS,KAAK,eAAe,QAAQ,SAAS,KAAK,eAAe,MAAM,OAAQ;AACpF,YAAQ,aAAa,KAAK,MAAM,QAAQ,SAAS,MAAM,MAAM;AAAA,EAC/D;AACA,aAAW,QAAQ,UAAU;AAC3B,QAAI,KAAK,eAAe,MAAM,UAAU,CAAC,MAAM,UAAU,KAAK,CAAC,aAAa,SAAS,SAAS,IAAI,GAAG;AACnG,cAAQ,YAAY,KAAK,MAAM,QAAQ,IAAI;AAAA,IAC7C;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAY,YAAY,OAAsB;AACtE,sBAAoB;AACpB,QAAM,QAAQ,UAAU,IAAI,IAAI;AAChC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,aAAa,OAAO,YAAY,OAAO,MAAS;AAK/D,uCAAU;AACV,SAAO;AACT;AASA,SAAS,eAAe,MAAqB;AAC3C,SAAO,gBAAgB,QAAS,uBAAuB,UAAU,IAAI,IAAI;AAC3E;AASA,SAAS,sBAAsB,MAAY,YAAY,OAAa;AAz2BpE;AA02BE,OAAI,eAAU,IAAI,IAAI,MAAlB,mBAAqB,YAAa,kBAAiB,MAAM,SAAS;AACxE;AAEA,IAAI,mBAAwC;AA2B5C,IAAM,mBAAmB;AAEzB,SAAS,mBAAmB,KAAwB;AA14BpD;AA64BE,SAAO,iBAAiB,MAAK,SAAI,gBAAgB,aAAa,OAAO,MAAxC,YAA6C,EAAE;AAC9E;AASA,IAAM,gBAAgB,uBAAO,IAAI,2CAA2C;AAY5E,SAAS,eAAe,MAAe,KAAuC;AAn6B9E;AAo6BE,QAAM,aAAa,OAAO,yBAAyB,MAAM,GAAG;AAC5D,QAAM,MAAc,8CAAY,UAAZ,YAAqB,yCAAY;AACrD,MAAI,OAAO,OAAO,WAAY,QAAO;AACrC,QAAM,QAAiB,QAAQ,IAAI,IAAI,aAAa;AACpD,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI,EAAE,YAAY,UAAU,MAAM,WAAW,SAAS,EAAE,YAAY,OAAQ,QAAO;AACnF,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,OAAO,WAAW,WAAY,QAAO;AACzC,SAAO,MAAM;AACX,WAAO,KAAK,KAAK;AAAA,EACnB;AACF;AA8BA,SAAS,yBAAyB,MAAe,aAAoC;AA78BrF;AA88BE,MAAI,SAAS;AACb,QAAM,YAA+B,CAAC;AAUtC,QAAM,UAAU,CAAC,KAAa,YAAgC,OAAqB;AACjF;AAAA,MACE,UAAU,GAAG;AAAA,MACb,MAAM;AACJ,cAAM,WAAW,OAAO,yBAAyB,MAAM,GAAG;AAC1D,YAAI,YAAY,CAAC,SAAS,aAAc;AACxC,cAAM,SAAS,MAAY;AACzB,cAAI,SAAU,QAAO,eAAe,MAAM,KAAK,QAAQ;AAAA,cAClD,SAAQ,eAAe,MAAM,GAAG;AAAA,QACvC;AACA,cAAM,QAAsB;AAAA,UAC1B,IAAI,SAAS;AACX,mBAAO;AAAA,UACT;AAAA,UACA;AAAA,QACF;AACA,eAAO,eAAe,IAAI,eAAe,EAAE,OAAO,MAAM,CAAC;AACzD,eAAO,eAAe,MAAM,KAAK,EAAE,cAAc,MAAM,YAAY,OAAO,GAAG,WAAW,CAAC;AACzF,kBAAU,KAAK,MAAM;AA3+B7B,cAAAA;AA4+BU,gBAAM,UAAU,OAAO,yBAAyB,MAAM,GAAG;AACzD,cAAI,CAAC,aAAYA,MAAA,QAAQ,UAAR,OAAAA,MAAiB,QAAQ,SAAS,GAAI;AACvD,iBAAO;AAEP,mBAAS,QAAQ,GAAG,QAAQ,IAAI,SAAS;AACvC,kBAAM,UAAU,eAAe,MAAM,GAAG;AACxC,gBAAI,CAAC,QAAS;AACd,oBAAQ;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,CAAyB,KAAa,YAAkE;AACnH,QAAI,OAAO,YAAY,WAAY;AACnC,UAAM,UAAU,YAA4B,MAAY;AACtD,aAAO,UAAU,SAAS,OAAO,YAAY,MAAM,QAAQ,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,QAAQ,KAAK,MAAM,GAAG,IAAI;AAAA,IAC9G;AACA,YAAQ,KAAK,EAAE,UAAU,MAAM,OAAO,QAAQ,GAAG,OAAO;AAAA,EAC1D;AACA,OAAK,gBAAgB,KAAK,YAAY;AACtC,OAAK,kBAAkB,KAAK,cAAc;AAC1C,OAAK,mBAAmB,KAAK,eAAe;AAC5C,OAAK,qBAAqB,KAAK,iBAAiB;AAChD,OAAK,mBAAmB,KAAK,eAAe;AAC5C,OAAK,oBAAoB,KAAK,gBAAgB;AAC9C,OAAK,sBAAsB,KAAK,kBAAkB;AAClD,OAAK,uBAAuB,KAAK,mBAAmB;AAEpD,QAAM,OAAO,KAAK,cAAc;AAChC,QAAM,YACJ,QAAQ,gBAAgB,KAAK,cACzB,OAAO,yBAAyB,KAAK,YAAY,WAAW,MAAM,IAClE;AACN,QAAM,QAAO,YAAO,yBAAyB,MAAM,MAAM,MAA5C,YAAiD;AAC9D,QAAM,UAAU,6BAAM;AACtB,QAAM,UAAU,6BAAM;AACtB,MAAI,WAAW,SAAS;AACtB,UAAM,MAAM,SAAyB,OAAqB;AACxD,UAAI,UAAU,SAAS,KAAM,aAAY,MAAM,QAAQ,KAAK,MAAM,KAAK,CAAC;AAAA,UACnE,SAAQ,KAAK,MAAM,KAAK;AAAA,IAC/B;AACA,YAAQ,QAAQ,EAAE,KAAK,SAAS,IAAI,GAAG,GAAG;AAAA,EAC5C;AAEA,SAAO,MAAM;AACX,aAAS;AACT,eAAW,WAAW,UAAW,SAAQ,0BAA0B,SAAS,MAAS;AAAA,EACvF;AACF;AAEO,SAAS,6BAA6B,UAAwC,CAAC,GAAe;AAjiCrG;AAkiCE,MAAI,iBAAkB,QAAO;AAC7B,QAAM,UAAU,WAAW;AAC3B,QAAM,OAAM,aAAQ,aAAR,YAAoB;AAChC,eAAY,aAAQ,YAAR,YAAmB;AAE/B,MAAI,oBAAgC,MAAM;AAC1C,MAAI,mBAA+B,MAAM;AAOzC,MAAI,oBAAoB,mBAAmB,GAAG;AAE9C,QAAM,mBAAmB,MAAY;AACnC,QAAI,SAAU;AACd,qBAAiB;AACjB,sBAAkB;AAClB,wBAAoB,MAAM;AAC1B,eAAW,IAAI,iBAAiB,CAAC,YAAY;AAC3C,cAAQ,qBAAqB,MAAM,eAAe,OAAO,GAAG,MAAS;AAAA,IACvE,CAAC;AACD,aAAS,QAAQ,KAAK;AAAA,MACpB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,eAAe;AAAA,MACf,uBAAuB;AAAA,MACvB,YAAY;AAAA,MACZ,iBAAiB,CAAC,oBAAoB;AAAA,IACxC,CAAC;AACD,cAAU,iDAAiD;AAC3D,sBAAkB,GAAG;AAAA,EACvB;AAWA,QAAM,oBAAoB,MAAY;AACpC,QAAI,kBAAkB,mBAAmB,GAAG,EAAG,kBAAiB;AAAA,EAClE;AAUA,QAAM,oBAAoB,CAAC,SAA2B,cAA6B;AACjF,QAAI,mBAAmB,GAAG,EAAG,qBAAoB;AACjD,QAAI,CAAC,aAAa,CAAC,qBAAqB,QAAQ,KAAK,CAAC,WAAW,OAAO,kBAAkB,MAAM,GAAG;AACjG,gBAAU,2CAA2C;AACrD,0BAAoB;AACpB,uBAAiB;AACjB,uBAAiB;AACjB;AAAA,IACF;AACA,QAAI,mBAAmB,GAAG,EAAG,kBAAiB;AAAA,EAChD;AAQA,QAAM,cAAyB,CAAC,UAAU;AA5mC5C,QAAAA,KAAAC;AA6mCI,UAAM,UAASD,MAAA,qDAAkB,kBAAlB,OAAAA,MAAmC,CAAC;AACnD,QAAI,OAAO,SAAS,EAAG,SAAQ,uBAAuB,MAAM,kBAAkB,QAAQ,KAAK,GAAG,MAAS;AACvG,QAAI;AACF,aAAO,MAAM;AAAA,IACf,UAAE;AACA,YAAM,OAAMC,MAAA,qDAAkB,kBAAlB,OAAAA,MAAmC,CAAC;AAChD,UAAI,IAAI,SAAS,EAAG,SAAQ,uBAAuB,MAAM,kBAAkB,KAAK,IAAI,GAAG,MAAS;AAAA,IAClG;AAAA,EACF;AAoBA,QAAM,uBAAuB,CAAC,aAAyB;AACrD,QAAI,uBAAuB,CAAC,wBAAwB,QAAQ,EAAG;AAC/D,qBAAiB;AACjB,4BAAwB;AAAA,EAC1B;AAQA,QAAM,uBAAuB,CAAC,UAAgC;AAC5D,QAAI,MAAM,kBAAkB,yBAA0B;AACtD;AAAA,MACE;AAAA,MACA,MAAM;AACJ,YAAI,oBAAqB;AACzB,kBAAU,mDAAmD;AAC7D,yBAAiB;AACjB,gCAAwB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAiBA,QAAM,qBAAqB,MAAe;AACxC,QAAI,oBAAqB,QAAO;AAChC,QAAI,CAAC,yBAAyB,GAAG,EAAG,QAAO;AAC3C,cAAU,2CAA2C;AACrD,qBAAiB;AACjB,4BAAwB;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,IAAI,iBAAiB,CAAC,YAAY;AACjD,YAAQ,uBAAuB,MAAM,kBAAkB,SAAS,KAAK,GAAG,MAAS;AAAA,EACnF,CAAC;AACD,qBAAmB;AACnB,WAAS,QAAQ,IAAI,iBAAiB,EAAE,YAAY,MAAM,iBAAiB,CAAC,QAAQ,OAAO,EAAE,CAAC;AAC9F,QAAM,yBAAyB,yBAAyB,IAAI,iBAAiB,WAAW;AACxF,qBAAmB,MAAM;AACvB,uBAAmB,MAAM;AACzB,aAAS,WAAW;AACpB,QAAI,qBAAqB,SAAU,oBAAmB;AACtD,2BAAuB;AAAA,EACzB;AAEA,MAAI,QAAQ,SAAS,mBAAmB,GAAG,GAAG;AAC5C,qBAAiB;AAAA,EACnB,OAAO;AACL,qBAAiB;AACjB,UAAM,mBAAmB,2BAA2B,GAAG;AACvD,QAAI,iBAAiB,kBAAkB,sBAAsB,IAAI;AACjE,wBAAoB,MAAM;AACxB,uBAAiB;AACjB,UAAI,oBAAoB,kBAAkB,sBAAsB,IAAI;AAAA,IACtE;AAAA,EACF;AAEA,OAAK,UAAU,cAAc,SAAS,YAAwC,OAAa;AACzF,sBAAkB;AAClB,QAAI,MAAM,eAAe,MAAM;AAC7B,YAAM,UAAU;AAAA,QACd;AAAA,QACA,MAA4B;AAC1B,gBAAM,SAAS,eAAe,KAAK,IAAI,iBAAiB,KAAK,IAAI;AACjE,cAAI,WAAW,QAAQ;AAErB,sBAAU,2DAA2D;AACrE,mBAAO;AAAA,UACT;AACA,cAAI,WAAW,cAAc,MAAM,eAAe,KAAM,QAAO;AAC/D,cAAI,mBAAmB,GAAG;AAIxB,sBAAU,mDAAmD;AAC7D,gBAAI,MAAM,WAAY,SAAQ,YAAY,KAAK,MAAM,YAAY,KAAK;AACtE,yBAAa,KAAK;AAClB,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA,UAAI,YAAY,UAAW,QAAO;AAAA,IACpC,WAAW,qBAAqB;AAC9B,cAAQ,8BAA8B,MAAM,sBAAsB,KAAK,GAAG,MAAS;AAAA,IACrF;AACA,YAAQ,YAAY,KAAK,MAAM,KAAK;AACpC,iBAAa,KAAK;AAClB,WAAO;AAAA,EACT;AAEA,OAAK,UAAU,eAAe,SAAS,aAAyC,MAAS,OAAuB;AAC9G,sBAAkB;AAClB,yBAAqB,IAAI;AACzB,QAAI,KAAK,eAAe,MAAM;AAC5B,UAAI,eAAe,IAAI,EAAG,SAAQ,4BAA4B,MAAM,iBAAiB,IAAI,GAAG,WAAW;AAAA,IACzG,WAAW,qBAAqB;AAC9B,cAAQ,6BAA6B,MAAM,sBAAsB,IAAI,GAAG,MAAS;AAAA,IACnF;AACA,QAAI,SAAS,MAAM,eAAe,MAAM;AACtC,YAAM,UAAU;AAAA,QACd;AAAA,QACA,MAA4B;AAC1B,gBAAM,SAAS,eAAe,KAAK,IAAI,iBAAiB,KAAK,IAAI;AACjE,cAAI,WAAW,cAAc,MAAM,eAAe,KAAM,QAAO;AAC/D,cAAI,mBAAmB,GAAG;AAIxB,sBAAU,iDAAiD;AAC3D,oBAAQ,YAAY,KAAK,MAAM,IAAI;AACnC,yBAAa,IAAI;AACjB,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA,UAAI,YAAY,UAAW,QAAO;AAAA,IACpC,WAAW,SAAS,qBAAqB;AACvC,cAAQ,kCAAkC,MAAM,sBAAsB,KAAK,GAAG,MAAS;AAAA,IACzF;AACA,YAAQ,aAAa,KAAK,MAAM,MAAM,KAAK;AAC3C,iBAAa,IAAI;AACjB,WAAO;AAAA,EACT;AAEA,OAAK,UAAU,cAAc,SAAS,YAAwC,MAAY;AACxF,sBAAkB;AAClB,yBAAqB,IAAI;AACzB,QAAI,KAAK,eAAe,MAAM;AAC5B,UAAI,eAAe,IAAI,EAAG,SAAQ,sBAAsB,MAAM,iBAAiB,IAAI,GAAG,WAAW;AAAA,IACnG,WAAW,qBAAqB;AAC9B,cAAQ,4BAA4B,MAAM,sBAAsB,IAAI,GAAG,MAAS;AAAA,IAClF;AACA,YAAQ,YAAY,KAAK,MAAM,IAAI;AACnC,iBAAa,IAAI;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,oBAAoB,CAAC,SAAqB;AAC9C,QAAI,EAAE,gBAAgB,MAAO;AAC7B,QAAI,KAAK,eAAe,MAAM;AAC5B,cAAQ,qBAAqB,MAAM,iBAAiB,MAAM,IAAI,GAAG,WAAW;AAAA,IAC9E,WAAW,qBAAqB;AAC9B,cAAQ,sBAAsB,MAAM,sBAAsB,MAAM,IAAI,GAAG,MAAS;AAAA,IAClF;AAAA,EACF;AAEA,SAAO,eAAe,KAAK,WAAW,aAAa;AAAA,IACjD,cAAc;AAAA,IACd,YAAY,QAAQ,oBAAoB;AAAA,IACxC,KAAK,QAAQ,oBAAoB;AAAA,IACjC,IAAgB,OAAsB;AACpC,wBAAkB;AAClB,cAAQ,aAAa,MAAM,KAAK;AAChC,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,CAAC;AAED,SAAO,eAAe,cAAc,WAAW,QAAQ;AAAA,IACrD,cAAc;AAAA,IACd,YAAY,QAAQ,eAAe;AAAA,IACnC,KAAK,QAAQ,eAAe;AAAA,IAC5B,IAAyB,OAAe;AACtC,wBAAkB;AAClB,cAAQ,QAAQ,MAAM,KAAK;AAC3B,wBAAkB,IAAI;AAAA,IACxB;AAAA,EACF,CAAC;AAED,qBAAmB,MAAM;AACvB,sBAAkB;AAClB,wBAAoB,MAAM;AAC1B,qBAAiB;AACjB,yCAAU;AACV,eAAW;AACX,yDAAkB;AAClB,uBAAmB;AACnB,qBAAiB;AACjB,0BAAsB;AACtB,wBAAoB;AACpB,gBAAY;AACZ,0BAAsB;AACtB,SAAK,UAAU,cAAc,QAAQ;AACrC,SAAK,UAAU,eAAe,QAAQ;AACtC,SAAK,UAAU,cAAc,QAAQ;AACrC,WAAO,eAAe,KAAK,WAAW,aAAa,QAAQ,mBAAmB;AAC9E,WAAO,eAAe,cAAc,WAAW,QAAQ,QAAQ,cAAc;AAC7E,uBAAmB;AAAA,EACrB;AACA,SAAO;AACT;","names":["_a","_b"]}