{"version":3,"file":"useFlipTransition.mjs","names":[],"sources":["../../../src/Image/viewer/useFlipTransition.ts"],"sourcesContent":["import type { MotionValue } from 'motion/react';\nimport { animate, motionValue } from 'motion/react';\nimport { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport type { Rect } from './geometry';\n\nexport const OPEN_SPRING = { bounce: 0.15, type: 'spring' as const, visualDuration: 0.3 };\n// bounce: 0 — a full-viewport push with overshoot would visibly slide past\n// the resting position and snap back.\nconst PUSH_SPRING = { bounce: 0, type: 'spring' as const, visualDuration: 0.3 };\nconst FADE = { duration: 0.15, ease: 'easeOut' as const };\nconst CHROME_FADE = { delay: 0.15, duration: 0.2, ease: 'easeOut' as const };\nconst FADE_SCALE = 0.92;\nconst SWITCH_FADE_SCALE = 0.96;\nconst SETTLE_FALLBACK_MS = 1000;\n\ninterface Animation {\n  stop: () => void;\n}\n\nexport interface FlipTransformValues {\n  flipX: MotionValue<boolean>;\n  flipY: MotionValue<boolean>;\n  rotate: MotionValue<number>;\n  scale: MotionValue<number>;\n  x: MotionValue<number>;\n  y: MotionValue<number>;\n}\n\nexport interface UseFlipTransitionOptions {\n  animated: boolean;\n  getCloseSource: () => HTMLImageElement;\n  getFitRect: () => Rect;\n  getInitialScale: () => number;\n  getViewportWidth: () => number;\n  onClosed: () => void;\n  source: HTMLImageElement;\n  transform: FlipTransformValues;\n}\n\nexport interface CloseTransitionOptions {\n  fade?: boolean;\n}\n\nexport interface UseFlipTransitionResult {\n  backdropRef: (node: HTMLElement | null) => void;\n  chromeRef: (node: HTMLElement | null) => void;\n  close: (options?: CloseTransitionOptions) => void;\n  imageRef: (node: HTMLImageElement | null) => void;\n  isClosing: () => boolean;\n  isTransitioning: () => boolean;\n  switchTo: (apply: () => void, direction?: 1 | -1) => void;\n}\n\nconst measureSource = (element: HTMLImageElement): DOMRect | null => {\n  if (!element.isConnected) return null;\n  const rect = element.getBoundingClientRect();\n  if (rect.width <= 0 || rect.height <= 0) return null;\n  if (rect.bottom <= 0 || rect.right <= 0) return null;\n  if (rect.top >= window.innerHeight || rect.left >= window.innerWidth) return null;\n  return rect;\n};\n\nconst sourceTransform = (rect: DOMRect, fit: Rect) => ({\n  scale:\n    fit.width > 0 && fit.height > 0\n      ? Math.max(rect.width / fit.width, rect.height / fit.height)\n      : 1,\n  x: rect.left + rect.width / 2 - (fit.x + fit.width / 2),\n  y: rect.top + rect.height / 2 - (fit.y + fit.height / 2),\n});\n\nconst readTransform = (transform: FlipTransformValues) =>\n  [\n    `translate3d(${transform.x.get()}px, ${transform.y.get()}px, 0)`,\n    `scale(${transform.scale.get()})`,\n    `rotate(${transform.rotate.get()}deg)`,\n    `scaleX(${transform.flipX.get() ? -1 : 1})`,\n    `scaleY(${transform.flipY.get() ? -1 : 1})`,\n  ].join(' ');\n\nconst useBoundNode = <T extends HTMLElement>(apply: (node: T) => void) => {\n  const nodeRef = useRef<T | null>(null);\n  const applyRef = useRef(apply);\n  applyRef.current = apply;\n\n  const setNode = useCallback((node: T | null) => {\n    nodeRef.current = node;\n    if (node) applyRef.current(node);\n  }, []);\n\n  const refresh = useCallback(() => {\n    const node = nodeRef.current;\n    if (node) applyRef.current(node);\n  }, []);\n\n  const getNode = useCallback(() => nodeRef.current, []);\n\n  return useMemo(() => ({ getNode, refresh, setNode }), [getNode, refresh, setNode]);\n};\n\nexport const useFlipTransition = ({\n  animated,\n  getCloseSource,\n  getFitRect,\n  getInitialScale,\n  getViewportWidth,\n  onClosed,\n  source,\n  transform,\n}: UseFlipTransitionOptions): UseFlipTransitionResult => {\n  const [opacity] = useState(() => ({\n    backdrop: motionValue(0),\n    chrome: motionValue(0),\n    image: motionValue(animated ? 1 : 0),\n  }));\n\n  const image = useBoundNode<HTMLImageElement>(\n    useCallback(\n      (node) => {\n        node.style.transform = readTransform(transform);\n        node.style.opacity = String(opacity.image.get());\n      },\n      [opacity, transform],\n    ),\n  );\n\n  const backdrop = useBoundNode<HTMLElement>(\n    useCallback(\n      (node) => {\n        node.style.opacity = String(opacity.backdrop.get());\n      },\n      [opacity],\n    ),\n  );\n\n  const chrome = useBoundNode<HTMLElement>(\n    useCallback(\n      (node) => {\n        node.style.opacity = String(opacity.chrome.get());\n      },\n      [opacity],\n    ),\n  );\n\n  const runningRef = useRef<Animation[]>([]);\n  const closingRef = useRef(false);\n  const transitioningRef = useRef(true);\n\n  const onClosedRef = useRef(onClosed);\n  onClosedRef.current = onClosed;\n\n  const getFitRectRef = useRef(getFitRect);\n  getFitRectRef.current = getFitRect;\n\n  const getCloseSourceRef = useRef(getCloseSource);\n  getCloseSourceRef.current = getCloseSource;\n\n  const getInitialScaleRef = useRef(getInitialScale);\n  getInitialScaleRef.current = getInitialScale;\n\n  const getViewportWidthRef = useRef(getViewportWidth);\n  getViewportWidthRef.current = getViewportWidth;\n\n  const ghostRef = useRef<HTMLImageElement | null>(null);\n  const removeGhost = useCallback(() => {\n    ghostRef.current?.remove();\n    ghostRef.current = null;\n  }, []);\n\n  const run = useCallback((animations: Animation[]) => {\n    runningRef.current = [...runningRef.current, ...animations];\n  }, []);\n\n  const stopAll = useCallback(() => {\n    for (const animation of runningRef.current) animation.stop();\n    runningRef.current = [];\n  }, []);\n\n  const isTransitioning = useCallback(() => transitioningRef.current, []);\n  const isClosing = useCallback(() => closingRef.current, []);\n\n  // stopAll() only stops tracked Animation objects; a bare window.setTimeout\n  // has no way to be cancelled by it. Track a fallback timer the same way, so\n  // a later stopAll() (a new open/close/switch superseding an interrupted one)\n  // clears the old timer along with the animations it was backing — otherwise\n  // it can fire mid-way through the new phase and flip transitioningRef false\n  // while something else is legitimately still in flight.\n  const trackTimeout = useCallback(\n    (callback: () => void, ms: number) => {\n      const id = window.setTimeout(callback, ms);\n      run([{ stop: () => window.clearTimeout(id) }]);\n    },\n    [run],\n  );\n\n  // A future animate() call on one of these shared motion values (e.g. a refit\n  // triggered by a natural-size change) silently cancels whichever animation is\n  // already running on it — motion's animate() stops the prior one without ever\n  // firing its onComplete. Track completion by count for the common case, but\n  // always back it with a fallback timer so onSettled fires exactly once no\n  // matter what: a cancelled axis can never leave this permanently unfired.\n  const animateSettling = useCallback(\n    (axes: [MotionValue<number>, number][], onSettled: () => void) => {\n      let pending = axes.length;\n      let settled = false;\n      const finish = () => {\n        if (settled) return;\n        settled = true;\n        onSettled();\n      };\n      const onAxisComplete = () => {\n        pending -= 1;\n        if (pending === 0) finish();\n      };\n      run(\n        axes.map(([value, target]) =>\n          animate(value, target, { ...OPEN_SPRING, onComplete: onAxisComplete }),\n        ),\n      );\n      trackTimeout(finish, SETTLE_FALLBACK_MS);\n    },\n    [run, trackTimeout],\n  );\n\n  useLayoutEffect(() => {\n    const unsubscribes = [\n      ...[\n        transform.flipX,\n        transform.flipY,\n        transform.rotate,\n        transform.scale,\n        transform.x,\n        transform.y,\n        opacity.image,\n      ].map((value) => value.on('change', image.refresh)),\n      opacity.backdrop.on('change', backdrop.refresh),\n      opacity.chrome.on('change', chrome.refresh),\n    ];\n\n    return () => {\n      for (const unsubscribe of unsubscribes) unsubscribe();\n    };\n  }, [backdrop, chrome, image, opacity, transform]);\n\n  useLayoutEffect(() => {\n    const rect = animated ? measureSource(source) : null;\n    transitioningRef.current = true;\n    const markSettled = () => {\n      transitioningRef.current = false;\n    };\n\n    // Resting scale is whatever defaultZoom resolved to, not necessarily fit.\n    const resting = getInitialScaleRef.current();\n\n    if (rect) {\n      const start = sourceTransform(rect, getFitRectRef.current());\n      transform.scale.set(start.scale);\n      transform.x.set(start.x);\n      transform.y.set(start.y);\n      opacity.image.set(1);\n      animateSettling(\n        [\n          [transform.scale, resting],\n          [transform.x, 0],\n          [transform.y, 0],\n        ],\n        markSettled,\n      );\n    } else {\n      opacity.image.set(0);\n      if (animated) transform.scale.set(resting * FADE_SCALE);\n      run([animate(opacity.image, 1, { ...FADE, onComplete: markSettled })]);\n      if (animated) run([animate(transform.scale, resting, FADE)]);\n      trackTimeout(markSettled, SETTLE_FALLBACK_MS);\n    }\n\n    run([animate(opacity.backdrop, 1, FADE), animate(opacity.chrome, 1, CHROME_FADE)]);\n\n    return () => {\n      stopAll();\n      removeGhost();\n    };\n  }, [\n    animateSettling,\n    animated,\n    opacity,\n    removeGhost,\n    run,\n    source,\n    stopAll,\n    trackTimeout,\n    transform,\n  ]);\n\n  const close = useCallback(\n    (options?: CloseTransitionOptions) => {\n      if (closingRef.current) return;\n      closingRef.current = true;\n      transitioningRef.current = true;\n      stopAll();\n      removeGhost();\n\n      let finished = false;\n      const finish = () => {\n        if (finished) return;\n        finished = true;\n        transitioningRef.current = false;\n        onClosedRef.current();\n      };\n      const rect = animated && !options?.fade ? measureSource(getCloseSourceRef.current()) : null;\n\n      run([animate(opacity.backdrop, 0, FADE), animate(opacity.chrome, 0, FADE)]);\n\n      if (rect) {\n        const target = sourceTransform(rect, getFitRectRef.current());\n        animateSettling(\n          [\n            [transform.x, target.x],\n            [transform.y, target.y],\n            [transform.scale, target.scale],\n          ],\n          finish,\n        );\n        return;\n      }\n\n      if (animated) run([animate(transform.scale, transform.scale.get() * FADE_SCALE, FADE)]);\n      run([animate(opacity.image, 0, { ...FADE, onComplete: finish })]);\n      trackTimeout(finish, SETTLE_FALLBACK_MS);\n    },\n    [animateSettling, animated, opacity, run, stopAll, trackTimeout, transform],\n  );\n\n  const switchTo = useCallback(\n    (apply: () => void, direction?: 1 | -1) => {\n      if (closingRef.current) return;\n      stopAll();\n      removeGhost();\n      transitioningRef.current = true;\n\n      const markSettled = () => {\n        transitioningRef.current = false;\n      };\n\n      const node = image.getNode();\n      const width = getViewportWidthRef.current();\n\n      if (animated && direction && node && width > 0) {\n        // The clone snapshots the outgoing visual state wholesale — src,\n        // fitRect positioning and the current zoom/rotate/flip transform —\n        // so the live <img> stays the single element every other system\n        // (gestures, FLIP close, refit) keeps operating on.\n        const ghost = node.cloneNode() as HTMLImageElement;\n        ghost.dataset.ghost = 'true';\n        ghost.setAttribute('aria-hidden', 'true');\n        ghost.style.pointerEvents = 'none';\n        const base = ghost.style.transform;\n        node.parentElement?.insertBefore(ghost, node);\n        ghostRef.current = ghost;\n\n        const progress = motionValue(0);\n        const unsubscribe = progress.on('change', (p) => {\n          ghost.style.transform = `translateX(${-direction * width * p}px) ${base}`;\n        });\n        const finishGhost = () => {\n          unsubscribe();\n          if (ghostRef.current === ghost) removeGhost();\n          else ghost.remove();\n        };\n\n        apply();\n        transform.x.jump(direction * width);\n\n        run([\n          animate(progress, 1, { ...PUSH_SPRING, onComplete: finishGhost }),\n          animate(transform.x, 0, { ...PUSH_SPRING, onComplete: markSettled }),\n          { stop: finishGhost },\n        ]);\n        trackTimeout(() => {\n          finishGhost();\n          markSettled();\n        }, SETTLE_FALLBACK_MS);\n        return;\n      }\n\n      const tasks: Animation[] = [];\n      if (animated) tasks.push(animate(transform.scale, SWITCH_FADE_SCALE, FADE));\n      tasks.push(\n        animate(opacity.image, 0, {\n          ...FADE,\n          onComplete: () => {\n            apply();\n            run([animate(opacity.image, 1, { ...FADE, onComplete: markSettled })]);\n          },\n        }),\n      );\n      run(tasks);\n      trackTimeout(markSettled, SETTLE_FALLBACK_MS);\n    },\n    [animated, image, opacity, removeGhost, run, stopAll, trackTimeout, transform],\n  );\n\n  return {\n    backdropRef: backdrop.setNode,\n    chromeRef: chrome.setNode,\n    close,\n    imageRef: image.setNode,\n    isClosing,\n    isTransitioning,\n    switchTo,\n  };\n};\n"],"mappings":";;;AAMA,MAAa,cAAc;CAAE,QAAQ;CAAM,MAAM;CAAmB,gBAAgB;AAAI;AAGxF,MAAM,cAAc;CAAE,QAAQ;CAAG,MAAM;CAAmB,gBAAgB;AAAI;AAC9E,MAAM,OAAO;CAAE,UAAU;CAAM,MAAM;AAAmB;AACxD,MAAM,cAAc;CAAE,OAAO;CAAM,UAAU;CAAK,MAAM;AAAmB;AAC3E,MAAM,aAAa;AACnB,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAwC3B,MAAM,iBAAiB,YAA8C;CACnE,IAAI,CAAC,QAAQ,aAAa,OAAO;CACjC,MAAM,OAAO,QAAQ,sBAAsB;CAC3C,IAAI,KAAK,SAAS,KAAK,KAAK,UAAU,GAAG,OAAO;CAChD,IAAI,KAAK,UAAU,KAAK,KAAK,SAAS,GAAG,OAAO;CAChD,IAAI,KAAK,OAAO,OAAO,eAAe,KAAK,QAAQ,OAAO,YAAY,OAAO;CAC7E,OAAO;AACT;AAEA,MAAM,mBAAmB,MAAe,SAAe;CACrD,OACE,IAAI,QAAQ,KAAK,IAAI,SAAS,IAC1B,KAAK,IAAI,KAAK,QAAQ,IAAI,OAAO,KAAK,SAAS,IAAI,MAAM,IACzD;CACN,GAAG,KAAK,OAAO,KAAK,QAAQ,KAAK,IAAI,IAAI,IAAI,QAAQ;CACrD,GAAG,KAAK,MAAM,KAAK,SAAS,KAAK,IAAI,IAAI,IAAI,SAAS;AACxD;AAEA,MAAM,iBAAiB,cACrB;CACE,eAAe,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,EAAE,IAAI,EAAE;CACzD,SAAS,UAAU,MAAM,IAAI,EAAE;CAC/B,UAAU,UAAU,OAAO,IAAI,EAAE;CACjC,UAAU,UAAU,MAAM,IAAI,IAAI,KAAK,EAAE;CACzC,UAAU,UAAU,MAAM,IAAI,IAAI,KAAK,EAAE;AAC3C,CAAC,CAAC,KAAK,GAAG;AAEZ,MAAM,gBAAuC,UAA6B;CACxE,MAAM,UAAU,OAAiB,IAAI;CACrC,MAAM,WAAW,OAAO,KAAK;CAC7B,SAAS,UAAU;CAEnB,MAAM,UAAU,aAAa,SAAmB;EAC9C,QAAQ,UAAU;EAClB,IAAI,MAAM,SAAS,QAAQ,IAAI;CACjC,GAAG,CAAC,CAAC;CAEL,MAAM,UAAU,kBAAkB;EAChC,MAAM,OAAO,QAAQ;EACrB,IAAI,MAAM,SAAS,QAAQ,IAAI;CACjC,GAAG,CAAC,CAAC;CAEL,MAAM,UAAU,kBAAkB,QAAQ,SAAS,CAAC,CAAC;CAErD,OAAO,eAAe;EAAE;EAAS;EAAS;CAAQ,IAAI;EAAC;EAAS;EAAS;CAAO,CAAC;AACnF;AAEA,MAAa,qBAAqB,EAChC,UACA,gBACA,YACA,iBACA,kBACA,UACA,QACA,gBACuD;CACvD,MAAM,CAAC,WAAW,gBAAgB;EAChC,UAAU,YAAY,CAAC;EACvB,QAAQ,YAAY,CAAC;EACrB,OAAO,YAAY,WAAW,IAAI,CAAC;CACrC,EAAE;CAEF,MAAM,QAAQ,aACZ,aACG,SAAS;EACR,KAAK,MAAM,YAAY,cAAc,SAAS;EAC9C,KAAK,MAAM,UAAU,OAAO,QAAQ,MAAM,IAAI,CAAC;CACjD,GACA,CAAC,SAAS,SAAS,CACrB,CACF;CAEA,MAAM,WAAW,aACf,aACG,SAAS;EACR,KAAK,MAAM,UAAU,OAAO,QAAQ,SAAS,IAAI,CAAC;CACpD,GACA,CAAC,OAAO,CACV,CACF;CAEA,MAAM,SAAS,aACb,aACG,SAAS;EACR,KAAK,MAAM,UAAU,OAAO,QAAQ,OAAO,IAAI,CAAC;CAClD,GACA,CAAC,OAAO,CACV,CACF;CAEA,MAAM,aAAa,OAAoB,CAAC,CAAC;CACzC,MAAM,aAAa,OAAO,KAAK;CAC/B,MAAM,mBAAmB,OAAO,IAAI;CAEpC,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CAEtB,MAAM,gBAAgB,OAAO,UAAU;CACvC,cAAc,UAAU;CAExB,MAAM,oBAAoB,OAAO,cAAc;CAC/C,kBAAkB,UAAU;CAE5B,MAAM,qBAAqB,OAAO,eAAe;CACjD,mBAAmB,UAAU;CAE7B,MAAM,sBAAsB,OAAO,gBAAgB;CACnD,oBAAoB,UAAU;CAE9B,MAAM,WAAW,OAAgC,IAAI;CACrD,MAAM,cAAc,kBAAkB;EACpC,SAAS,SAAS,OAAO;EACzB,SAAS,UAAU;CACrB,GAAG,CAAC,CAAC;CAEL,MAAM,MAAM,aAAa,eAA4B;EACnD,WAAW,UAAU,CAAC,GAAG,WAAW,SAAS,GAAG,UAAU;CAC5D,GAAG,CAAC,CAAC;CAEL,MAAM,UAAU,kBAAkB;EAChC,KAAK,MAAM,aAAa,WAAW,SAAS,UAAU,KAAK;EAC3D,WAAW,UAAU,CAAC;CACxB,GAAG,CAAC,CAAC;CAEL,MAAM,kBAAkB,kBAAkB,iBAAiB,SAAS,CAAC,CAAC;CACtE,MAAM,YAAY,kBAAkB,WAAW,SAAS,CAAC,CAAC;CAQ1D,MAAM,eAAe,aAClB,UAAsB,OAAe;EACpC,MAAM,KAAK,OAAO,WAAW,UAAU,EAAE;EACzC,IAAI,CAAC,EAAE,YAAY,OAAO,aAAa,EAAE,EAAE,CAAC,CAAC;CAC/C,GACA,CAAC,GAAG,CACN;CAQA,MAAM,kBAAkB,aACrB,MAAuC,cAA0B;EAChE,IAAI,UAAU,KAAK;EACnB,IAAI,UAAU;EACd,MAAM,eAAe;GACnB,IAAI,SAAS;GACb,UAAU;GACV,UAAU;EACZ;EACA,MAAM,uBAAuB;GAC3B,WAAW;GACX,IAAI,YAAY,GAAG,OAAO;EAC5B;EACA,IACE,KAAK,KAAK,CAAC,OAAO,YAChB,QAAQ,OAAO,QAAQ;GAAE,GAAG;GAAa,YAAY;EAAe,CAAC,CACvE,CACF;EACA,aAAa,QAAQ,kBAAkB;CACzC,GACA,CAAC,KAAK,YAAY,CACpB;CAEA,sBAAsB;EACpB,MAAM,eAAe;GACnB,GAAG;IACD,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,QAAQ;GACV,CAAC,CAAC,KAAK,UAAU,MAAM,GAAG,UAAU,MAAM,OAAO,CAAC;GAClD,QAAQ,SAAS,GAAG,UAAU,SAAS,OAAO;GAC9C,QAAQ,OAAO,GAAG,UAAU,OAAO,OAAO;EAC5C;EAEA,aAAa;GACX,KAAK,MAAM,eAAe,cAAc,YAAY;EACtD;CACF,GAAG;EAAC;EAAU;EAAQ;EAAO;EAAS;CAAS,CAAC;CAEhD,sBAAsB;EACpB,MAAM,OAAO,WAAW,cAAc,MAAM,IAAI;EAChD,iBAAiB,UAAU;EAC3B,MAAM,oBAAoB;GACxB,iBAAiB,UAAU;EAC7B;EAGA,MAAM,UAAU,mBAAmB,QAAQ;EAE3C,IAAI,MAAM;GACR,MAAM,QAAQ,gBAAgB,MAAM,cAAc,QAAQ,CAAC;GAC3D,UAAU,MAAM,IAAI,MAAM,KAAK;GAC/B,UAAU,EAAE,IAAI,MAAM,CAAC;GACvB,UAAU,EAAE,IAAI,MAAM,CAAC;GACvB,QAAQ,MAAM,IAAI,CAAC;GACnB,gBACE;IACE,CAAC,UAAU,OAAO,OAAO;IACzB,CAAC,UAAU,GAAG,CAAC;IACf,CAAC,UAAU,GAAG,CAAC;GACjB,GACA,WACF;EACF,OAAO;GACL,QAAQ,MAAM,IAAI,CAAC;GACnB,IAAI,UAAU,UAAU,MAAM,IAAI,UAAU,UAAU;GACtD,IAAI,CAAC,QAAQ,QAAQ,OAAO,GAAG;IAAE,GAAG;IAAM,YAAY;GAAY,CAAC,CAAC,CAAC;GACrE,IAAI,UAAU,IAAI,CAAC,QAAQ,UAAU,OAAO,SAAS,IAAI,CAAC,CAAC;GAC3D,aAAa,aAAa,kBAAkB;EAC9C;EAEA,IAAI,CAAC,QAAQ,QAAQ,UAAU,GAAG,IAAI,GAAG,QAAQ,QAAQ,QAAQ,GAAG,WAAW,CAAC,CAAC;EAEjF,aAAa;GACX,QAAQ;GACR,YAAY;EACd;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,QAAQ,aACX,YAAqC;EACpC,IAAI,WAAW,SAAS;EACxB,WAAW,UAAU;EACrB,iBAAiB,UAAU;EAC3B,QAAQ;EACR,YAAY;EAEZ,IAAI,WAAW;EACf,MAAM,eAAe;GACnB,IAAI,UAAU;GACd,WAAW;GACX,iBAAiB,UAAU;GAC3B,YAAY,QAAQ;EACtB;EACA,MAAM,OAAO,YAAY,CAAC,SAAS,OAAO,cAAc,kBAAkB,QAAQ,CAAC,IAAI;EAEvF,IAAI,CAAC,QAAQ,QAAQ,UAAU,GAAG,IAAI,GAAG,QAAQ,QAAQ,QAAQ,GAAG,IAAI,CAAC,CAAC;EAE1E,IAAI,MAAM;GACR,MAAM,SAAS,gBAAgB,MAAM,cAAc,QAAQ,CAAC;GAC5D,gBACE;IACE,CAAC,UAAU,GAAG,OAAO,CAAC;IACtB,CAAC,UAAU,GAAG,OAAO,CAAC;IACtB,CAAC,UAAU,OAAO,OAAO,KAAK;GAChC,GACA,MACF;GACA;EACF;EAEA,IAAI,UAAU,IAAI,CAAC,QAAQ,UAAU,OAAO,UAAU,MAAM,IAAI,IAAI,YAAY,IAAI,CAAC,CAAC;EACtF,IAAI,CAAC,QAAQ,QAAQ,OAAO,GAAG;GAAE,GAAG;GAAM,YAAY;EAAO,CAAC,CAAC,CAAC;EAChE,aAAa,QAAQ,kBAAkB;CACzC,GACA;EAAC;EAAiB;EAAU;EAAS;EAAK;EAAS;EAAc;CAAS,CAC5E;CAEA,MAAM,WAAW,aACd,OAAmB,cAAuB;EACzC,IAAI,WAAW,SAAS;EACxB,QAAQ;EACR,YAAY;EACZ,iBAAiB,UAAU;EAE3B,MAAM,oBAAoB;GACxB,iBAAiB,UAAU;EAC7B;EAEA,MAAM,OAAO,MAAM,QAAQ;EAC3B,MAAM,QAAQ,oBAAoB,QAAQ;EAE1C,IAAI,YAAY,aAAa,QAAQ,QAAQ,GAAG;GAK9C,MAAM,QAAQ,KAAK,UAAU;GAC7B,MAAM,QAAQ,QAAQ;GACtB,MAAM,aAAa,eAAe,MAAM;GACxC,MAAM,MAAM,gBAAgB;GAC5B,MAAM,OAAO,MAAM,MAAM;GACzB,KAAK,eAAe,aAAa,OAAO,IAAI;GAC5C,SAAS,UAAU;GAEnB,MAAM,WAAW,YAAY,CAAC;GAC9B,MAAM,cAAc,SAAS,GAAG,WAAW,MAAM;IAC/C,MAAM,MAAM,YAAY,cAAc,CAAC,YAAY,QAAQ,EAAE,MAAM;GACrE,CAAC;GACD,MAAM,oBAAoB;IACxB,YAAY;IACZ,IAAI,SAAS,YAAY,OAAO,YAAY;SACvC,MAAM,OAAO;GACpB;GAEA,MAAM;GACN,UAAU,EAAE,KAAK,YAAY,KAAK;GAElC,IAAI;IACF,QAAQ,UAAU,GAAG;KAAE,GAAG;KAAa,YAAY;IAAY,CAAC;IAChE,QAAQ,UAAU,GAAG,GAAG;KAAE,GAAG;KAAa,YAAY;IAAY,CAAC;IACnE,EAAE,MAAM,YAAY;GACtB,CAAC;GACD,mBAAmB;IACjB,YAAY;IACZ,YAAY;GACd,GAAG,kBAAkB;GACrB;EACF;EAEA,MAAM,QAAqB,CAAC;EAC5B,IAAI,UAAU,MAAM,KAAK,QAAQ,UAAU,OAAO,mBAAmB,IAAI,CAAC;EAC1E,MAAM,KACJ,QAAQ,QAAQ,OAAO,GAAG;GACxB,GAAG;GACH,kBAAkB;IAChB,MAAM;IACN,IAAI,CAAC,QAAQ,QAAQ,OAAO,GAAG;KAAE,GAAG;KAAM,YAAY;IAAY,CAAC,CAAC,CAAC;GACvE;EACF,CAAC,CACH;EACA,IAAI,KAAK;EACT,aAAa,aAAa,kBAAkB;CAC9C,GACA;EAAC;EAAU;EAAO;EAAS;EAAa;EAAK;EAAS;EAAc;CAAS,CAC/E;CAEA,OAAO;EACL,aAAa,SAAS;EACtB,WAAW,OAAO;EAClB;EACA,UAAU,MAAM;EAChB;EACA;EACA;CACF;AACF"}