{"version":3,"file":"videowatch-CukABKao.mjs","sources":["../../../node_modules/.pnpm/react-bootstrap@2.10.10_@types+react@19.1.8_react-dom@19.1.0_react@19.1.0/node_modules/react-bootstrap/esm/InputGroupText.js","../../../node_modules/.pnpm/react-bootstrap@2.10.10_@types+react@19.1.8_react-dom@19.1.0_react@19.1.0/node_modules/react-bootstrap/esm/InputGroup.js","../../../node_modules/.pnpm/react-bootstrap@2.10.10_@types+react@19.1.8_react-dom@19.1.0_react@19.1.0/node_modules/react-bootstrap/esm/createUtilityClasses.js","../../../node_modules/.pnpm/react-bootstrap@2.10.10_@types+react@19.1.8_react-dom@19.1.0_react@19.1.0/node_modules/react-bootstrap/esm/Stack.js","../src/components/favoritebutton.tsx","../../../node_modules/.pnpm/ms@2.0.0/node_modules/ms/index.js","../../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/debug.js","../../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/browser.js","../../../node_modules/.pnpm/jsonp@0.2.1/node_modules/jsonp/index.js","../../../node_modules/.pnpm/react-share@5.2.2_react@19.1.0/node_modules/react-share/dist/index.js","../src/components/ShareDropdown.tsx","../src/components/GiftModal.tsx","../src/components/DonationCommentDisplay.tsx","../src/pages/videowatch/videoplayercontainer.tsx","../src/components/ConfirmModal.tsx","../src/pages/videowatch/reportmodal.tsx","../src/pages/videowatch/videoinfo.tsx","../src/pages/videowatch/videowatchmain.tsx","../src/pages/videowatch/comment/commentform.tsx","../src/pages/videowatch/comment/commenteditform.tsx","../src/pages/videowatch/comment/commentitem.tsx","../src/pages/videowatch/videocomments.tsx","../src/pages/videowatch/yuanhuiVideoNavigation.ts","../src/pages/videowatch/relatedvideos.tsx","../src/pages/videowatch/index.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { useBootstrapPrefix } from './ThemeProvider';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst InputGroupText = /*#__PURE__*/React.forwardRef(({\n  className,\n  bsPrefix,\n  as: Component = 'span',\n  ...props\n}, ref) => {\n  bsPrefix = useBootstrapPrefix(bsPrefix, 'input-group-text');\n  return /*#__PURE__*/_jsx(Component, {\n    ref: ref,\n    className: classNames(className, bsPrefix),\n    ...props\n  });\n});\nInputGroupText.displayName = 'InputGroupText';\nexport default InputGroupText;","\"use client\";\n\nimport classNames from 'classnames';\nimport * as React from 'react';\nimport { useMemo } from 'react';\nimport { useBootstrapPrefix } from './ThemeProvider';\nimport FormCheckInput from './FormCheckInput';\nimport InputGroupContext from './InputGroupContext';\nimport InputGroupText from './InputGroupText';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst InputGroupCheckbox = props => /*#__PURE__*/_jsx(InputGroupText, {\n  children: /*#__PURE__*/_jsx(FormCheckInput, {\n    type: \"checkbox\",\n    ...props\n  })\n});\nconst InputGroupRadio = props => /*#__PURE__*/_jsx(InputGroupText, {\n  children: /*#__PURE__*/_jsx(FormCheckInput, {\n    type: \"radio\",\n    ...props\n  })\n});\nconst InputGroup = /*#__PURE__*/React.forwardRef(({\n  bsPrefix,\n  size,\n  hasValidation,\n  className,\n  // Need to define the default \"as\" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595\n  as: Component = 'div',\n  ...props\n}, ref) => {\n  bsPrefix = useBootstrapPrefix(bsPrefix, 'input-group');\n\n  // Intentionally an empty object. Used in detecting if a dropdown\n  // exists under an input group.\n  const contextValue = useMemo(() => ({}), []);\n  return /*#__PURE__*/_jsx(InputGroupContext.Provider, {\n    value: contextValue,\n    children: /*#__PURE__*/_jsx(Component, {\n      ref: ref,\n      ...props,\n      className: classNames(className, bsPrefix, size && `${bsPrefix}-${size}`, hasValidation && 'has-validation')\n    })\n  });\n});\nInputGroup.displayName = 'InputGroup';\nexport default Object.assign(InputGroup, {\n  Text: InputGroupText,\n  Radio: InputGroupRadio,\n  Checkbox: InputGroupCheckbox\n});","import PropTypes from 'prop-types';\nimport { DEFAULT_BREAKPOINTS, DEFAULT_MIN_BREAKPOINT } from './ThemeProvider';\nexport function responsivePropType(propType) {\n  return PropTypes.oneOfType([propType, PropTypes.shape({\n    xs: propType,\n    sm: propType,\n    md: propType,\n    lg: propType,\n    xl: propType,\n    xxl: propType\n  })]);\n}\nexport default function createUtilityClassName(utilityValues, breakpoints = DEFAULT_BREAKPOINTS, minBreakpoint = DEFAULT_MIN_BREAKPOINT) {\n  const classes = [];\n  Object.entries(utilityValues).forEach(([utilName, utilValue]) => {\n    if (utilValue != null) {\n      if (typeof utilValue === 'object') {\n        breakpoints.forEach(brkPoint => {\n          const bpValue = utilValue[brkPoint];\n          if (bpValue != null) {\n            const infix = brkPoint !== minBreakpoint ? `-${brkPoint}` : '';\n            classes.push(`${utilName}${infix}-${bpValue}`);\n          }\n        });\n      } else {\n        classes.push(`${utilName}-${utilValue}`);\n      }\n    }\n  });\n  return classes;\n}","\"use client\";\n\nimport classNames from 'classnames';\nimport * as React from 'react';\nimport { useBootstrapPrefix, useBootstrapBreakpoints, useBootstrapMinBreakpoint } from './ThemeProvider';\nimport createUtilityClassName, { responsivePropType } from './createUtilityClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst Stack = /*#__PURE__*/React.forwardRef(({\n  as: Component = 'div',\n  bsPrefix,\n  className,\n  direction,\n  gap,\n  ...props\n}, ref) => {\n  bsPrefix = useBootstrapPrefix(bsPrefix, direction === 'horizontal' ? 'hstack' : 'vstack');\n  const breakpoints = useBootstrapBreakpoints();\n  const minBreakpoint = useBootstrapMinBreakpoint();\n  return /*#__PURE__*/_jsx(Component, {\n    ...props,\n    ref: ref,\n    className: classNames(className, bsPrefix, ...createUtilityClassName({\n      gap\n    }, breakpoints, minBreakpoint))\n  });\n});\nStack.displayName = 'Stack';\nexport default Stack;","import { useState, useEffect } from 'react';\nimport { Button } from 'react-bootstrap';\nimport { api, consumeNativeAuthResume, getErrorMessage } from '../libs';\nimport { trackFavorite } from '../libs/analytics';\nimport { showError } from '../libs/toast';\nimport { useTranslation } from '../libs/i18n';\nimport { redirectToLogin } from '../utils/redirect';\n\ninterface FavoriteButtonProps {\n    videoId: string;\n    currentUserId?: number;\n    className?: string;\n}\n\ninterface FavoriteResponse {\n    success: boolean;\n    isFavorited: boolean;\n    message: string;\n    favoritedAt?: string;\n}\n\ninterface FavoriteStatus {\n    isFavorited: boolean;\n    favoritedAt?: string;\n}\n\nexport function FavoriteButton({\n    videoId,\n    currentUserId,\n    className = '',\n}: FavoriteButtonProps) {\n    const { t } = useTranslation();\n    const [isFavorited, setIsFavorited] = useState(false);\n    const [loading, setLoading] = useState(false);\n    const [favoriteStatusKnown, setFavoriteStatusKnown] = useState(false);\n    const [favoriteStatusResolved, setFavoriteStatusResolved] = useState(false);\n\n    // Load initial favorite status\n    useEffect(() => {\n        if (currentUserId) {\n            loadFavoriteStatus();\n        }\n    }, [videoId, currentUserId]);\n\n    const loadFavoriteStatus = async () => {\n        try {\n            const response = await api.get<FavoriteStatus>(\n                `/api/videos/${videoId}/favorite`\n            );\n            setIsFavorited(response.data.isFavorited);\n            setFavoriteStatusKnown(true);\n        } catch (err) {\n            // Ignore errors for favorite status - not critical\n            console.warn(\n                'Failed to load favorite status:',\n                getErrorMessage(err)\n            );\n        } finally {\n            setFavoriteStatusResolved(true);\n        }\n    };\n\n    const handleToggleFavorite = async () => {\n        if (loading) return;\n\n        // If user is not logged in, redirect to login\n        if (!currentUserId) {\n            redirectToLogin({ action: 'favorite', targetId: videoId });\n            return;\n        }\n\n        // Save original state for rollback\n        const originalFavoriteStatus = isFavorited;\n\n        // Optimistically update UI immediately\n        setIsFavorited(!isFavorited);\n\n        try {\n            setLoading(true);\n            const response = await api.post<FavoriteResponse>(\n                `/api/videos/${videoId}/favorite`\n            );\n\n            if (response.data.success) {\n                // Update to actual server response (should match optimistic update)\n                setIsFavorited(response.data.isFavorited);\n\n                // 追踪收藏事件\n                trackFavorite({\n                    action: response.data.isFavorited\n                        ? 'favorite'\n                        : 'unfavorite',\n                    video_id: videoId,\n                    success: true,\n                });\n            } else {\n                // Rollback on server rejection\n                setIsFavorited(originalFavoriteStatus);\n                const errorMsg = originalFavoriteStatus\n                    ? t('ui.error.unfavoriteFailed')\n                    : t('ui.error.favoriteFailed');\n                showError(errorMsg);\n\n                // 追踪失败事件\n                trackFavorite({\n                    action: originalFavoriteStatus ? 'unfavorite' : 'favorite',\n                    video_id: videoId,\n                    success: false,\n                    error: 'server_rejected',\n                });\n            }\n        } catch (err) {\n            // Rollback on error\n            setIsFavorited(originalFavoriteStatus);\n            const errorMessage = getErrorMessage(err);\n\n            // 追踪失败事件\n            trackFavorite({\n                action: originalFavoriteStatus ? 'unfavorite' : 'favorite',\n                video_id: videoId,\n                success: false,\n                error: errorMessage,\n            });\n\n            // Show appropriate error message\n            if (\n                errorMessage.includes('网络') ||\n                errorMessage.includes('Network') ||\n                errorMessage.includes('timeout') ||\n                errorMessage.includes('连接')\n            ) {\n                showError(t('ui.error.favoriteNetworkError'));\n            } else {\n                const errorMsg = originalFavoriteStatus\n                    ? t('ui.error.unfavoriteFailed')\n                    : t('ui.error.favoriteFailed');\n                showError(errorMsg);\n            }\n        } finally {\n            setLoading(false);\n        }\n    };\n\n    useEffect(() => {\n        if (\n            currentUserId &&\n            favoriteStatusResolved &&\n            consumeNativeAuthResume({ action: 'favorite', targetId: videoId })\n        ) {\n            if (favoriteStatusKnown && !isFavorited) {\n                void handleToggleFavorite();\n            }\n        }\n    }, [\n        currentUserId,\n        favoriteStatusKnown,\n        favoriteStatusResolved,\n        isFavorited,\n        videoId,\n    ]);\n\n    return (\n        <Button\n            variant=\"light\"\n            className={className}\n            onClick={handleToggleFavorite}\n            disabled={loading}\n            title={\n                isFavorited\n                    ? t('ui.button.unfavorite')\n                    : t('ui.button.favorite')\n            }\n        >\n            <i\n                className={`bi ${\n                    isFavorited ? 'bi-star-fill' : 'bi-star'\n                } me-1`}\n            ></i>\n            {isFavorited ? t('ui.button.unfavorite') : t('ui.button.favorite')}\n        </Button>\n    );\n}\n","/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n *  - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} [options]\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function(val, options) {\n  options = options || {};\n  var type = typeof val;\n  if (type === 'string' && val.length > 0) {\n    return parse(val);\n  } else if (type === 'number' && isNaN(val) === false) {\n    return options.long ? fmtLong(val) : fmtShort(val);\n  }\n  throw new Error(\n    'val is not a non-empty string or a valid number. val=' +\n      JSON.stringify(val)\n  );\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n  str = String(str);\n  if (str.length > 100) {\n    return;\n  }\n  var match = /^((?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(\n    str\n  );\n  if (!match) {\n    return;\n  }\n  var n = parseFloat(match[1]);\n  var type = (match[2] || 'ms').toLowerCase();\n  switch (type) {\n    case 'years':\n    case 'year':\n    case 'yrs':\n    case 'yr':\n    case 'y':\n      return n * y;\n    case 'days':\n    case 'day':\n    case 'd':\n      return n * d;\n    case 'hours':\n    case 'hour':\n    case 'hrs':\n    case 'hr':\n    case 'h':\n      return n * h;\n    case 'minutes':\n    case 'minute':\n    case 'mins':\n    case 'min':\n    case 'm':\n      return n * m;\n    case 'seconds':\n    case 'second':\n    case 'secs':\n    case 'sec':\n    case 's':\n      return n * s;\n    case 'milliseconds':\n    case 'millisecond':\n    case 'msecs':\n    case 'msec':\n    case 'ms':\n      return n;\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n  if (ms >= d) {\n    return Math.round(ms / d) + 'd';\n  }\n  if (ms >= h) {\n    return Math.round(ms / h) + 'h';\n  }\n  if (ms >= m) {\n    return Math.round(ms / m) + 'm';\n  }\n  if (ms >= s) {\n    return Math.round(ms / s) + 's';\n  }\n  return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n  return plural(ms, d, 'day') ||\n    plural(ms, h, 'hour') ||\n    plural(ms, m, 'minute') ||\n    plural(ms, s, 'second') ||\n    ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, n, name) {\n  if (ms < n) {\n    return;\n  }\n  if (ms < n * 1.5) {\n    return Math.floor(ms / n) + ' ' + name;\n  }\n  return Math.ceil(ms / n) + ' ' + name + 's';\n}\n","\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = createDebug.debug = createDebug['default'] = createDebug;\nexports.coerce = coerce;\nexports.disable = disable;\nexports.enable = enable;\nexports.enabled = enabled;\nexports.humanize = require('ms');\n\n/**\n * The currently active debug mode names, and names to skip.\n */\n\nexports.names = [];\nexports.skips = [];\n\n/**\n * Map of special \"%n\" handling functions, for the debug \"format\" argument.\n *\n * Valid key names are a single, lower or upper-case letter, i.e. \"n\" and \"N\".\n */\n\nexports.formatters = {};\n\n/**\n * Previous log timestamp.\n */\n\nvar prevTime;\n\n/**\n * Select a color.\n * @param {String} namespace\n * @return {Number}\n * @api private\n */\n\nfunction selectColor(namespace) {\n  var hash = 0, i;\n\n  for (i in namespace) {\n    hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);\n    hash |= 0; // Convert to 32bit integer\n  }\n\n  return exports.colors[Math.abs(hash) % exports.colors.length];\n}\n\n/**\n * Create a debugger with the given `namespace`.\n *\n * @param {String} namespace\n * @return {Function}\n * @api public\n */\n\nfunction createDebug(namespace) {\n\n  function debug() {\n    // disabled?\n    if (!debug.enabled) return;\n\n    var self = debug;\n\n    // set `diff` timestamp\n    var curr = +new Date();\n    var ms = curr - (prevTime || curr);\n    self.diff = ms;\n    self.prev = prevTime;\n    self.curr = curr;\n    prevTime = curr;\n\n    // turn the `arguments` into a proper Array\n    var args = new Array(arguments.length);\n    for (var i = 0; i < args.length; i++) {\n      args[i] = arguments[i];\n    }\n\n    args[0] = exports.coerce(args[0]);\n\n    if ('string' !== typeof args[0]) {\n      // anything else let's inspect with %O\n      args.unshift('%O');\n    }\n\n    // apply any `formatters` transformations\n    var index = 0;\n    args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {\n      // if we encounter an escaped % then don't increase the array index\n      if (match === '%%') return match;\n      index++;\n      var formatter = exports.formatters[format];\n      if ('function' === typeof formatter) {\n        var val = args[index];\n        match = formatter.call(self, val);\n\n        // now we need to remove `args[index]` since it's inlined in the `format`\n        args.splice(index, 1);\n        index--;\n      }\n      return match;\n    });\n\n    // apply env-specific formatting (colors, etc.)\n    exports.formatArgs.call(self, args);\n\n    var logFn = debug.log || exports.log || console.log.bind(console);\n    logFn.apply(self, args);\n  }\n\n  debug.namespace = namespace;\n  debug.enabled = exports.enabled(namespace);\n  debug.useColors = exports.useColors();\n  debug.color = selectColor(namespace);\n\n  // env-specific initialization logic for debug instances\n  if ('function' === typeof exports.init) {\n    exports.init(debug);\n  }\n\n  return debug;\n}\n\n/**\n * Enables a debug mode by namespaces. This can include modes\n * separated by a colon and wildcards.\n *\n * @param {String} namespaces\n * @api public\n */\n\nfunction enable(namespaces) {\n  exports.save(namespaces);\n\n  exports.names = [];\n  exports.skips = [];\n\n  var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\\s,]+/);\n  var len = split.length;\n\n  for (var i = 0; i < len; i++) {\n    if (!split[i]) continue; // ignore empty strings\n    namespaces = split[i].replace(/\\*/g, '.*?');\n    if (namespaces[0] === '-') {\n      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\n    } else {\n      exports.names.push(new RegExp('^' + namespaces + '$'));\n    }\n  }\n}\n\n/**\n * Disable debug output.\n *\n * @api public\n */\n\nfunction disable() {\n  exports.enable('');\n}\n\n/**\n * Returns true if the given mode name is enabled, false otherwise.\n *\n * @param {String} name\n * @return {Boolean}\n * @api public\n */\n\nfunction enabled(name) {\n  var i, len;\n  for (i = 0, len = exports.skips.length; i < len; i++) {\n    if (exports.skips[i].test(name)) {\n      return false;\n    }\n  }\n  for (i = 0, len = exports.names.length; i < len; i++) {\n    if (exports.names[i].test(name)) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * Coerce `val`.\n *\n * @param {Mixed} val\n * @return {Mixed}\n * @api private\n */\n\nfunction coerce(val) {\n  if (val instanceof Error) return val.stack || val.message;\n  return val;\n}\n","/**\n * This is the web browser implementation of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = require('./debug');\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = 'undefined' != typeof chrome\n               && 'undefined' != typeof chrome.storage\n                  ? chrome.storage.local\n                  : localstorage();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n  'lightseagreen',\n  'forestgreen',\n  'goldenrod',\n  'dodgerblue',\n  'darkorchid',\n  'crimson'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\nfunction useColors() {\n  // NB: In an Electron preload script, document will be defined but not fully\n  // initialized. Since we know we're in Chrome, we'll just detect this case\n  // explicitly\n  if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {\n    return true;\n  }\n\n  // is webkit? http://stackoverflow.com/a/16459606/376773\n  // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n  return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||\n    // is firebug? http://stackoverflow.com/a/398120/376773\n    (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||\n    // is firefox >= v31?\n    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||\n    // double check webkit in userAgent just in case we are in a worker\n    (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/));\n}\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nexports.formatters.j = function(v) {\n  try {\n    return JSON.stringify(v);\n  } catch (err) {\n    return '[UnexpectedJSONParseError]: ' + err.message;\n  }\n};\n\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs(args) {\n  var useColors = this.useColors;\n\n  args[0] = (useColors ? '%c' : '')\n    + this.namespace\n    + (useColors ? ' %c' : ' ')\n    + args[0]\n    + (useColors ? '%c ' : ' ')\n    + '+' + exports.humanize(this.diff);\n\n  if (!useColors) return;\n\n  var c = 'color: ' + this.color;\n  args.splice(1, 0, c, 'color: inherit')\n\n  // the final \"%c\" is somewhat tricky, because there could be other\n  // arguments passed either before or after the %c, so we need to\n  // figure out the correct index to insert the CSS into\n  var index = 0;\n  var lastC = 0;\n  args[0].replace(/%[a-zA-Z%]/g, function(match) {\n    if ('%%' === match) return;\n    index++;\n    if ('%c' === match) {\n      // we only are interested in the *last* %c\n      // (the user may have provided their own)\n      lastC = index;\n    }\n  });\n\n  args.splice(lastC, 0, c);\n}\n\n/**\n * Invokes `console.log()` when available.\n * No-op when `console.log` is not a \"function\".\n *\n * @api public\n */\n\nfunction log() {\n  // this hackery is required for IE8/9, where\n  // the `console.log` function doesn't have 'apply'\n  return 'object' === typeof console\n    && console.log\n    && Function.prototype.apply.call(console.log, console, arguments);\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\n\nfunction save(namespaces) {\n  try {\n    if (null == namespaces) {\n      exports.storage.removeItem('debug');\n    } else {\n      exports.storage.debug = namespaces;\n    }\n  } catch(e) {}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n  var r;\n  try {\n    r = exports.storage.debug;\n  } catch(e) {}\n\n  // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n  if (!r && typeof process !== 'undefined' && 'env' in process) {\n    r = process.env.DEBUG;\n  }\n\n  return r;\n}\n\n/**\n * Enable namespaces listed in `localStorage.debug` initially.\n */\n\nexports.enable(load());\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage() {\n  try {\n    return window.localStorage;\n  } catch (e) {}\n}\n","/**\n * Module dependencies\n */\n\nvar debug = require('debug')('jsonp');\n\n/**\n * Module exports.\n */\n\nmodule.exports = jsonp;\n\n/**\n * Callback index.\n */\n\nvar count = 0;\n\n/**\n * Noop function.\n */\n\nfunction noop(){}\n\n/**\n * JSONP handler\n *\n * Options:\n *  - param {String} qs parameter (`callback`)\n *  - prefix {String} qs parameter (`__jp`)\n *  - name {String} qs parameter (`prefix` + incr)\n *  - timeout {Number} how long after a timeout error is emitted (`60000`)\n *\n * @param {String} url\n * @param {Object|Function} optional options / callback\n * @param {Function} optional callback\n */\n\nfunction jsonp(url, opts, fn){\n  if ('function' == typeof opts) {\n    fn = opts;\n    opts = {};\n  }\n  if (!opts) opts = {};\n\n  var prefix = opts.prefix || '__jp';\n\n  // use the callback name that was passed if one was provided.\n  // otherwise generate a unique name by incrementing our counter.\n  var id = opts.name || (prefix + (count++));\n\n  var param = opts.param || 'callback';\n  var timeout = null != opts.timeout ? opts.timeout : 60000;\n  var enc = encodeURIComponent;\n  var target = document.getElementsByTagName('script')[0] || document.head;\n  var script;\n  var timer;\n\n\n  if (timeout) {\n    timer = setTimeout(function(){\n      cleanup();\n      if (fn) fn(new Error('Timeout'));\n    }, timeout);\n  }\n\n  function cleanup(){\n    if (script.parentNode) script.parentNode.removeChild(script);\n    window[id] = noop;\n    if (timer) clearTimeout(timer);\n  }\n\n  function cancel(){\n    if (window[id]) {\n      cleanup();\n    }\n  }\n\n  window[id] = function(data){\n    debug('jsonp got', data);\n    cleanup();\n    if (fn) fn(null, data);\n  };\n\n  // add qs component\n  url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id);\n  url = url.replace('?&', '?');\n\n  debug('jsonp req \"%s\"', url);\n\n  // create script\n  script = document.createElement('script');\n  script.src = url;\n  target.parentNode.insertBefore(script, target);\n\n  return cancel;\n}\n","var __defProp = Object.defineProperty;\nvar __defProps = Object.defineProperties;\nvar __getOwnPropDescs = Object.getOwnPropertyDescriptors;\nvar __getOwnPropSymbols = Object.getOwnPropertySymbols;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __propIsEnum = Object.prototype.propertyIsEnumerable;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __spreadValues = (a, b) => {\n  for (var prop in b || (b = {}))\n    if (__hasOwnProp.call(b, prop))\n      __defNormalProp(a, prop, b[prop]);\n  if (__getOwnPropSymbols)\n    for (var prop of __getOwnPropSymbols(b)) {\n      if (__propIsEnum.call(b, prop))\n        __defNormalProp(a, prop, b[prop]);\n    }\n  return a;\n};\nvar __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));\nvar __objRest = (source, exclude) => {\n  var target = {};\n  for (var prop in source)\n    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)\n      target[prop] = source[prop];\n  if (source != null && __getOwnPropSymbols)\n    for (var prop of __getOwnPropSymbols(source)) {\n      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))\n        target[prop] = source[prop];\n    }\n  return target;\n};\nimport { jsxs, jsx } from \"react/jsx-runtime\";\nimport { forwardRef, useRef, useEffect, useCallback, useState } from \"react\";\nimport cx from \"classnames\";\nimport jsonp from \"jsonp\";\nfunction createIcon(iconConfig) {\n  const Icon = (_a) => {\n    var _b = _a, {\n      bgStyle = {},\n      borderRadius = 0,\n      iconFillColor = \"white\",\n      round = false,\n      size = 64\n    } = _b, rest = __objRest(_b, [\n      \"bgStyle\",\n      \"borderRadius\",\n      \"iconFillColor\",\n      \"round\",\n      \"size\"\n    ]);\n    return /* @__PURE__ */ jsxs(\"svg\", __spreadProps(__spreadValues({ viewBox: \"0 0 64 64\", width: size, height: size }, rest), { children: [\n      round ? /* @__PURE__ */ jsx(\"circle\", { cx: \"32\", cy: \"32\", r: \"32\", fill: iconConfig.color, style: bgStyle }) : /* @__PURE__ */ jsx(\n        \"rect\",\n        {\n          width: \"64\",\n          height: \"64\",\n          rx: borderRadius,\n          ry: borderRadius,\n          fill: iconConfig.color,\n          style: bgStyle\n        }\n      ),\n      /* @__PURE__ */ jsx(\"path\", { d: iconConfig.path, fill: iconFillColor })\n    ] }));\n  };\n  return Icon;\n}\nconst BlueskyIcon = createIcon({\n  color: \"#1185FE\",\n  path: \"M21.945 18.886C26.015 21.941 30.393 28.137 32 31.461 33.607 28.137 37.985 21.941 42.055 18.886 44.992 16.681 49.75 14.975 49.75 20.403 49.75 21.487 49.128 29.51 48.764 30.813 47.497 35.341 42.879 36.496 38.772 35.797 45.951 37.019 47.778 41.067 43.833 45.114 36.342 52.801 33.066 43.186 32.227 40.722 32.073 40.27 32.001 40.059 32 40.238 31.999 40.059 31.927 40.27 31.773 40.722 30.934 43.186 27.658 52.801 20.167 45.114 16.222 41.067 18.049 37.019 25.228 35.797 21.121 36.496 16.503 35.341 15.236 30.813 14.872 29.51 14.25 21.487 14.25 20.403 14.25 14.975 19.008 16.681 21.945 18.886Z\"\n});\nclass AssertionError extends Error {\n  constructor(message) {\n    super(message);\n    this.name = \"AssertionError\";\n  }\n}\nfunction assert(value, message) {\n  if (!value) {\n    throw new AssertionError(message);\n  }\n}\nfunction objectToGetParams(object) {\n  const params = Object.entries(object).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n  return params.length > 0 ? `?${params.join(\"&\")}` : \"\";\n}\nconst isPromise = (obj) => !!obj && (typeof obj === \"object\" || typeof obj === \"function\") && \"then\" in obj && typeof obj.then === \"function\";\nconst getBoxPositionOnWindowCenter = (width, height) => ({\n  left: window.outerWidth / 2 + (window.screenX || window.screenLeft || 0) - width / 2,\n  top: window.outerHeight / 2 + (window.screenY || window.screenTop || 0) - height / 2\n});\nconst getBoxPositionOnScreenCenter = (width, height) => ({\n  top: (window.screen.height - height) / 2,\n  left: (window.screen.width - width) / 2\n});\nfunction windowOpen(url, _a, onClose) {\n  var _b = _a, { height, width } = _b, configRest = __objRest(_b, [\"height\", \"width\"]);\n  const config = __spreadValues({\n    height,\n    width,\n    location: \"no\",\n    toolbar: \"no\",\n    status: \"no\",\n    directories: \"no\",\n    menubar: \"no\",\n    scrollbars: \"yes\",\n    resizable: \"no\",\n    centerscreen: \"yes\",\n    chrome: \"yes\"\n  }, configRest);\n  const shareDialog = window.open(\n    url,\n    \"\",\n    Object.keys(config).map((key) => `${key}=${config[key]}`).join(\", \")\n  );\n  if (onClose) {\n    const interval = window.setInterval(() => {\n      try {\n        if (shareDialog === null || shareDialog.closed) {\n          window.clearInterval(interval);\n          onClose(shareDialog);\n        }\n      } catch (e) {\n        console.error(e);\n      }\n    }, 1e3);\n  }\n  return shareDialog;\n}\nfunction ShareButton(_c) {\n  var _d = _c, {\n    beforeOnClick,\n    children,\n    className,\n    disabled,\n    disabledStyle = { opacity: 0.6 },\n    forwardedRef,\n    htmlTitle,\n    networkLink,\n    networkName: networkName,\n    onClick: onClick,\n    onShareWindowClose,\n    openShareDialogOnClick = true,\n    opts,\n    resetButtonStyle = true,\n    style,\n    title: title,\n    url: url,\n    windowHeight = 400,\n    windowPosition = \"windowCenter\",\n    windowWidth = 550\n  } = _d, rest = __objRest(_d, [\n    \"beforeOnClick\",\n    \"children\",\n    \"className\",\n    \"disabled\",\n    \"disabledStyle\",\n    \"forwardedRef\",\n    \"htmlTitle\",\n    \"networkLink\",\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    \"networkName\",\n    // deconstructed from ...rest to prevent passing it to the button element\n    \"onClick\",\n    \"onShareWindowClose\",\n    \"openShareDialogOnClick\",\n    \"opts\",\n    \"resetButtonStyle\",\n    \"style\",\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    \"title\",\n    // deconstructed from ...rest to prevent passing it to the button element\n    \"url\",\n    \"windowHeight\",\n    \"windowPosition\",\n    \"windowWidth\"\n  ]);\n  const handleClick = async (event) => {\n    const link = networkLink(url, opts);\n    if (disabled) {\n      return;\n    }\n    event.preventDefault();\n    if (beforeOnClick) {\n      const returnVal = beforeOnClick();\n      if (isPromise(returnVal)) {\n        await returnVal;\n      }\n    }\n    if (openShareDialogOnClick) {\n      const windowConfig = __spreadValues({\n        height: windowHeight,\n        width: windowWidth\n      }, windowPosition === \"windowCenter\" ? getBoxPositionOnWindowCenter(windowWidth, windowHeight) : getBoxPositionOnScreenCenter(windowWidth, windowHeight));\n      windowOpen(link, windowConfig, onShareWindowClose);\n    }\n    if (onClick) {\n      onClick(event, link);\n    }\n  };\n  const newClassName = cx(\n    \"react-share__ShareButton\",\n    {\n      \"react-share__ShareButton--disabled\": !!disabled,\n      disabled: !!disabled\n    },\n    className\n  );\n  const newStyle = resetButtonStyle ? __spreadValues(__spreadValues({\n    backgroundColor: \"transparent\",\n    border: \"none\",\n    padding: 0,\n    font: \"inherit\",\n    color: \"inherit\",\n    cursor: \"pointer\"\n  }, style), disabled && disabledStyle) : __spreadValues(__spreadValues({}, style), disabled && disabledStyle);\n  return /* @__PURE__ */ jsx(\n    \"button\",\n    __spreadProps(__spreadValues({}, rest), {\n      className: newClassName,\n      onClick: handleClick,\n      ref: forwardedRef,\n      style: newStyle,\n      title: htmlTitle,\n      children\n    })\n  );\n}\nfunction createShareButton(networkName, link, optsMap, defaultProps) {\n  const CreatedButton = (props, ref) => {\n    const opts = optsMap(props);\n    const passedProps = __spreadValues({}, props);\n    const optsKeys = Object.keys(opts);\n    optsKeys.forEach((key) => {\n      delete passedProps[key];\n    });\n    return /* @__PURE__ */ jsx(\n      ShareButton,\n      __spreadProps(__spreadValues(__spreadValues({}, defaultProps), passedProps), {\n        forwardedRef: ref,\n        networkName,\n        networkLink: link,\n        opts\n      })\n    );\n  };\n  CreatedButton.displayName = `ShareButton-${networkName}`;\n  return forwardRef(CreatedButton);\n}\nfunction blueskyLink(url, { title, separator }) {\n  assert(url, \"bluesky.url\");\n  return \"https://bsky.app/intent/compose\" + objectToGetParams({\n    text: title ? title + separator + url : url\n  });\n}\nconst BlueskyShareButton = createShareButton(\n  \"bluesky\",\n  blueskyLink,\n  (props) => ({\n    title: props.title,\n    separator: props.separator || \" \"\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460,\n    windowPosition: \"windowCenter\"\n  }\n);\nconst EmailIcon = createIcon({\n  color: \"#7f7f7f\",\n  path: \"M17,22v20h30V22H17z M41.1,25L32,32.1L22.9,25H41.1z M20,39V26.6l12,9.3l12-9.3V39H20z\"\n});\nfunction emailLink(url, { subject, body, separator }) {\n  return \"mailto:\" + objectToGetParams({ subject, body: body ? body + separator + url : url });\n}\nconst EmailShareButton = createShareButton(\n  \"email\",\n  emailLink,\n  (props) => ({\n    subject: props.subject,\n    body: props.body,\n    separator: props.separator || \" \"\n  }),\n  {\n    openShareDialogOnClick: false,\n    onClick: (_, link) => {\n      window.location.href = link;\n    }\n  }\n);\nconst FacebookIcon = createIcon({\n  color: \"#0965FE\",\n  path: \"M34.1,47V33.3h4.6l0.7-5.3h-5.3v-3.4c0-1.5,0.4-2.6,2.6-2.6l2.8,0v-4.8c-0.5-0.1-2.2-0.2-4.1-0.2 c-4.1,0-6.9,2.5-6.9,7V28H24v5.3h4.6V47H34.1z\"\n});\nconst FacebookMessengerIcon = createIcon({\n  color: \"#0A7CFF\",\n  path: \"M 53.066406 21.871094 C 52.667969 21.339844 51.941406 21.179688 51.359375 21.496094 L 37.492188 29.058594 L 28.867188 21.660156 C 28.339844 21.207031 27.550781 21.238281 27.054688 21.730469 L 11.058594 37.726562 C 10.539062 38.25 10.542969 39.09375 11.0625 39.613281 C 11.480469 40.027344 12.121094 40.121094 12.640625 39.839844 L 26.503906 32.28125 L 35.136719 39.679688 C 35.667969 40.132812 36.457031 40.101562 36.949219 39.609375 L 52.949219 23.613281 C 53.414062 23.140625 53.464844 22.398438 53.066406 21.871094 Z M 53.066406 21.871094\"\n});\nfunction facebookMessengerLink(url, { appId, redirectUri, to }) {\n  return \"https://www.facebook.com/dialog/send\" + objectToGetParams({\n    link: url,\n    redirect_uri: redirectUri || url,\n    app_id: appId,\n    to\n  });\n}\nconst FacebookMessengerShareButton = createShareButton(\n  \"facebookmessenger\",\n  facebookMessengerLink,\n  (props) => ({\n    appId: props.appId,\n    redirectUri: props.redirectUri,\n    to: props.to\n  }),\n  {\n    windowWidth: 1e3,\n    windowHeight: 820\n  }\n);\nfunction facebookLink(url, { hashtag }) {\n  assert(url, \"facebook.url\");\n  return \"https://www.facebook.com/sharer/sharer.php\" + objectToGetParams({ u: url, hashtag });\n}\nconst FacebookShareButton = createShareButton(\n  \"facebook\",\n  facebookLink,\n  (props) => ({ hashtag: props.hashtag }),\n  {\n    windowWidth: 550,\n    windowHeight: 400\n  }\n);\nfunction useIsMounted() {\n  const isMounted = useRef(false);\n  useEffect(() => {\n    isMounted.current = true;\n    return () => {\n      isMounted.current = false;\n    };\n  }, []);\n  return useCallback(() => isMounted.current, []);\n}\nfunction SocialMediaShareCount(_e) {\n  var _f = _e, {\n    children = (shareCount) => shareCount,\n    className,\n    getCount,\n    url\n  } = _f, rest = __objRest(_f, [\n    \"children\",\n    \"className\",\n    \"getCount\",\n    \"url\"\n  ]);\n  const isMounted = useIsMounted();\n  const [count, setCount] = useState(void 0);\n  const [isLoading, setIsLoading] = useState(false);\n  useEffect(() => {\n    setIsLoading(true);\n    getCount(url, (count2) => {\n      if (isMounted()) {\n        setCount(count2);\n        setIsLoading(false);\n      }\n    });\n  }, [url]);\n  return /* @__PURE__ */ jsx(\"span\", __spreadProps(__spreadValues({ className: cx(\"react-share__ShareCount\", className) }, rest), { children: !isLoading && count !== void 0 && children(count) }));\n}\nfunction createShareCount(getCount) {\n  const ShareCount = (props) => /* @__PURE__ */ jsx(SocialMediaShareCount, __spreadValues({ getCount }, props));\n  ShareCount.displayName = `ShareCount(${getCount.name})`;\n  return ShareCount;\n}\nfunction getFacebookShareCount(shareUrl, callback) {\n  const endpoint = `https://graph.facebook.com/?id=${shareUrl}&fields=og_object{engagement}`;\n  jsonp(endpoint, (err, data) => {\n    callback(\n      !err && data && data.og_object && data.og_object.engagement ? data.og_object.engagement.count : void 0\n    );\n  });\n}\nconst FacebookShareCount = createShareCount(getFacebookShareCount);\nconst HatenaIcon = createIcon({\n  color: \"#009ad9\",\n  path: \"M 36.164062 33.554688 C 34.988281 32.234375 33.347656 31.5 31.253906 31.34375 C 33.125 30.835938 34.476562 30.09375 35.335938 29.09375 C 36.191406 28.09375 36.609375 26.78125 36.609375 25.101562 C 36.628906 23.875 36.332031 22.660156 35.75 21.578125 C 35.160156 20.558594 34.292969 19.71875 33.253906 19.160156 C 32.304688 18.640625 31.175781 18.265625 29.847656 18.042969 C 28.523438 17.824219 26.195312 17.730469 22.867188 17.730469 L 14.769531 17.730469 L 14.769531 47.269531 L 23.113281 47.269531 C 26.46875 47.269531 28.886719 47.15625 30.367188 46.929688 C 31.851562 46.695312 33.085938 46.304688 34.085938 45.773438 C 35.289062 45.148438 36.28125 44.179688 36.933594 42.992188 C 37.597656 41.796875 37.933594 40.402344 37.933594 38.816406 C 37.933594 36.621094 37.347656 34.867188 36.164062 33.554688 Z M 22.257812 24.269531 L 23.984375 24.269531 C 25.988281 24.269531 27.332031 24.496094 28.015625 24.945312 C 28.703125 25.402344 29.042969 26.183594 29.042969 27.285156 C 29.042969 28.390625 28.664062 29.105469 27.9375 29.550781 C 27.210938 29.992188 25.84375 30.199219 23.855469 30.199219 L 22.257812 30.199219 Z M 29.121094 41.210938 C 28.328125 41.691406 26.976562 41.925781 25.078125 41.925781 L 22.257812 41.925781 L 22.257812 35.488281 L 25.195312 35.488281 C 27.144531 35.488281 28.496094 35.738281 29.210938 36.230469 C 29.925781 36.726562 30.304688 37.582031 30.304688 38.832031 C 30.304688 40.078125 29.914062 40.742188 29.105469 41.222656 Z M 29.121094 41.210938 M 46.488281 39.792969 C 44.421875 39.792969 42.742188 41.46875 42.742188 43.535156 C 42.742188 45.605469 44.421875 47.28125 46.488281 47.28125 C 48.554688 47.28125 50.230469 45.605469 50.230469 43.535156 C 50.230469 41.46875 48.554688 39.792969 46.488281 39.792969 Z M 46.488281 39.792969 M 43.238281 17.730469 L 49.738281 17.730469 L 49.738281 37.429688 L 43.238281 37.429688 Z M 43.238281 17.730469 \"\n});\nfunction hatenaLink(url, { title }) {\n  assert(url, \"hatena.url\");\n  return `http://b.hatena.ne.jp/add?mode=confirm&url=${url}&title=${title}`;\n}\nconst HatenaShareButton = createShareButton(\n  \"hatena\",\n  hatenaLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460,\n    windowPosition: \"windowCenter\"\n  }\n);\nfunction getHatenaShareCount(shareUrl, callback) {\n  const url = \"https://bookmark.hatenaapis.com/count/entry\";\n  jsonp(\n    url + objectToGetParams({\n      url: shareUrl\n    }),\n    (err, data) => {\n      callback(data != null ? data : void 0);\n    }\n  );\n}\nconst HatenaShareCount = createShareCount(getHatenaShareCount);\nconst InstapaperIcon = createIcon({\n  color: \"#1F1F1F\",\n  path: \"M35.688 43.012c0 2.425.361 2.785 3.912 3.056V48H24.401v-1.932c3.555-.27 3.912-.63 3.912-3.056V20.944c0-2.379-.36-2.785-3.912-3.056V16H39.6v1.888c-3.55.27-3.912.675-3.912 3.056v22.068h.001z\"\n});\nfunction instapaperLink(url, { title, description }) {\n  assert(url, \"instapaper.url\");\n  return \"http://www.instapaper.com/hello2\" + objectToGetParams({\n    url,\n    title,\n    description\n  });\n}\nconst InstapaperShareButton = createShareButton(\n  \"instapaper\",\n  instapaperLink,\n  (props) => ({\n    title: props.title,\n    description: props.description\n  }),\n  {\n    windowWidth: 500,\n    windowHeight: 500,\n    windowPosition: \"windowCenter\"\n  }\n);\nconst LineIcon = createIcon({\n  color: \"#00b800\",\n  path: \"M52.62 30.138c0 3.693-1.432 7.019-4.42 10.296h.001c-4.326 4.979-14 11.044-16.201 11.972-2.2.927-1.876-.591-1.786-1.112l.294-1.765c.069-.527.142-1.343-.066-1.865-.232-.574-1.146-.872-1.817-1.016-9.909-1.31-17.245-8.238-17.245-16.51 0-9.226 9.251-16.733 20.62-16.733 11.37 0 20.62 7.507 20.62 16.733zM27.81 25.68h-1.446a.402.402 0 0 0-.402.401v8.985c0 .221.18.4.402.4h1.446a.401.401 0 0 0 .402-.4v-8.985a.402.402 0 0 0-.402-.401zm9.956 0H36.32a.402.402 0 0 0-.402.401v5.338L31.8 25.858a.39.39 0 0 0-.031-.04l-.002-.003-.024-.025-.008-.007a.313.313 0 0 0-.032-.026.255.255 0 0 1-.021-.014l-.012-.007-.021-.012-.013-.006-.023-.01-.013-.005-.024-.008-.014-.003-.023-.005-.017-.002-.021-.003-.021-.002h-1.46a.402.402 0 0 0-.402.401v8.985c0 .221.18.4.402.4h1.446a.401.401 0 0 0 .402-.4v-5.337l4.123 5.568c.028.04.063.072.101.099l.004.003a.236.236 0 0 0 .025.015l.012.006.019.01a.154.154 0 0 1 .019.008l.012.004.028.01.005.001a.442.442 0 0 0 .104.013h1.446a.4.4 0 0 0 .401-.4v-8.985a.402.402 0 0 0-.401-.401zm-13.442 7.537h-3.93v-7.136a.401.401 0 0 0-.401-.401h-1.447a.4.4 0 0 0-.401.401v8.984a.392.392 0 0 0 .123.29c.072.068.17.111.278.111h5.778a.4.4 0 0 0 .401-.401v-1.447a.401.401 0 0 0-.401-.401zm21.429-5.287c.222 0 .401-.18.401-.402v-1.446a.401.401 0 0 0-.401-.402h-5.778a.398.398 0 0 0-.279.113l-.005.004-.006.008a.397.397 0 0 0-.111.276v8.984c0 .108.043.206.112.278l.005.006a.401.401 0 0 0 .284.117h5.778a.4.4 0 0 0 .401-.401v-1.447a.401.401 0 0 0-.401-.401h-3.93v-1.519h3.93c.222 0 .401-.18.401-.402V29.85a.401.401 0 0 0-.401-.402h-3.93V27.93h3.93z\"\n});\nfunction lineLink(url, { title }) {\n  assert(url, \"line.url\");\n  return \"https://social-plugins.line.me/lineit/share\" + objectToGetParams({\n    url,\n    text: title\n  });\n}\nconst LineShareButton = createShareButton(\n  \"line\",\n  lineLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 500,\n    windowHeight: 500\n  }\n);\nconst LinkedinIcon = createIcon({\n  color: \"#0077B5\",\n  path: \"M20.4,44h5.4V26.6h-5.4V44z M23.1,18c-1.7,0-3.1,1.4-3.1,3.1c0,1.7,1.4,3.1,3.1,3.1 c1.7,0,3.1-1.4,3.1-3.1C26.2,19.4,24.8,18,23.1,18z M39.5,26.2c-2.6,0-4.4,1.4-5.1,2.8h-0.1v-2.4h-5.2V44h5.4v-8.6 c0-2.3,0.4-4.5,3.2-4.5c2.8,0,2.8,2.6,2.8,4.6V44H46v-9.5C46,29.8,45,26.2,39.5,26.2z\"\n});\nfunction linkedinLink(url, { title, summary, source }) {\n  assert(url, \"linkedin.url\");\n  return \"https://linkedin.com/shareArticle\" + objectToGetParams({ url, mini: \"true\", title, summary, source });\n}\nconst LinkedinShareButton = createShareButton(\n  \"linkedin\",\n  linkedinLink,\n  ({ title, summary, source }) => ({ title, summary, source }),\n  {\n    windowWidth: 750,\n    windowHeight: 600\n  }\n);\nconst LivejournalIcon = createIcon({\n  color: \"#21A5D8\",\n  path: \"M18.3407821,28.1764706 L21.9441341,31.789916 L33.0055865,42.882353 C33.0055865,42.882353 33.0893855,42.9663866 33.0893855,42.9663866 L46.6648046,47 C46.6648046,47 46.6648046,47 46.7486034,47 C46.8324022,47 46.8324022,47 46.9162012,46.9159664 C47,46.8319327 47,46.8319327 47,46.7478991 L42.9776536,33.1344537 C42.9776536,33.1344537 42.9776536,33.1344537 42.8938548,33.0504202 L31.1620111,21.3697479 L31.1620111,21.3697479 L28.1452514,18.2605042 C27.3072626,17.4201681 26.5530726,17 25.7150838,17 C24.2905028,17 23.0335195,18.3445378 21.5251397,19.8571429 C21.273743,20.1092437 20.9385475,20.4453781 20.6871508,20.697479 C20.3519553,21.0336134 20.1005586,21.2857143 19.849162,21.5378151 C18.3407821,22.9663866 17.0837989,24.2268908 17,25.7394958 C17.0837989,26.4957983 17.5027933,27.3361345 18.3407821,28.1764706 Z M39.9012319,39.6134454 C39.7336341,39.4453781 39.4822374,37.6806724 40.2364275,36.8403362 C40.9906174,36.0840337 41.6610084,36 42.1638017,36 C42.3313995,36 42.4989973,36 42.5827961,36 L44.8453659,43.5630253 L43.5883828,44.8235295 L36.0464833,42.5546218 C35.9626843,42.2184874 35.8788855,41.2100841 36.8844722,40.2016807 C37.2196676,39.8655463 37.8900587,39.6134454 38.5604498,39.6134454 C39.147042,39.6134454 39.5660364,39.7815126 39.5660364,39.7815126 C39.6498353,39.8655463 39.8174331,39.8655463 39.8174331,39.7815126 C39.9850307,39.7815126 39.9850307,39.697479 39.9012319,39.6134454 Z\"\n});\nfunction livejournalLink(url, { title, description }) {\n  assert(url, \"livejournal.url\");\n  return \"https://www.livejournal.com/update.bml\" + objectToGetParams({\n    subject: title,\n    event: description\n  });\n}\nconst LivejournalShareButton = createShareButton(\n  \"livejournal\",\n  livejournalLink,\n  (props) => ({\n    title: props.title,\n    description: props.description\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460\n  }\n);\nconst MailruIcon = createIcon({\n  color: \"#168DE2\",\n  path: \"M39.7107745,17 C41.6619755,17 43.3204965,18.732852 43.3204965,21.0072202 C43.3204965,23.2815885 41.7595357,25.0144404 39.7107745,25.0144404 C37.7595732,25.0144404 36.1010522,23.2815885 36.1010522,21.0072202 C36.1010522,18.732852 37.7595732,17 39.7107745,17 Z M24.3938451,17 C26.3450463,17 28.0035672,18.732852 28.0035672,21.0072202 C28.0035672,23.2815885 26.4426063,25.0144404 24.3938451,25.0144404 C22.4426439,25.0144404 20.7841229,23.2815885 20.7841229,21.0072202 C20.7841229,18.732852 22.4426439,17 24.3938451,17 Z M51.9057817,43.4259928 C51.7106617,44.0758123 51.4179815,44.6173285 50.9301812,44.9422383 C50.637501,45.1588448 50.2472607,45.267148 49.8570205,45.267148 C49.07654,45.267148 48.3936197,44.833935 48.0033795,44.0758123 L46.2472985,40.7184115 L45.759498,41.2599278 C42.5400162,44.9422383 37.466893,47 32.0035297,47 C26.5401664,47 21.5646034,44.9422383 18.2475614,41.2599278 L17.7597611,40.7184115 L16.00368,44.0758123 C15.6134398,44.833935 14.9305194,45.267148 14.1500389,45.267148 C13.7597986,45.267148 13.3695584,45.1588448 13.0768782,44.9422383 C12.0037176,44.2924187 11.7110374,42.7761733 12.2963978,41.5848375 L16.7841605,33.0288807 C17.1744007,32.270758 17.8573211,31.8375453 18.6378016,31.8375453 C19.0280418,31.8375453 19.4182821,31.9458485 19.7109623,32.1624548 C20.7841229,32.8122743 21.0768031,34.3285197 20.4914427,35.5198555 L20.1012025,36.2779783 L20.2963226,36.602888 C22.4426439,39.9602888 27.0279667,42.234657 31.9059697,42.234657 C36.7839727,42.234657 41.3692955,40.068592 43.5156167,36.602888 L43.7107367,36.2779783 L43.3204965,35.6281587 C43.0278165,35.0866425 42.9302562,34.436823 43.1253765,33.7870035 C43.3204965,33.137184 43.6131767,32.5956678 44.100977,32.270758 C44.3936572,32.0541515 44.7838975,31.9458485 45.1741377,31.9458485 C45.9546182,31.9458485 46.6375385,32.3790613 47.0277787,33.137184 L51.5155415,41.6931408 C52.003342,42.234657 52.100902,42.8844765 51.9057817,43.4259928 Z\"\n});\nfunction mailruLink(url, { title, description, imageUrl }) {\n  assert(url, \"mailru.url\");\n  return \"https://connect.mail.ru/share\" + objectToGetParams({\n    url,\n    title,\n    description,\n    image_url: imageUrl\n  });\n}\nconst MailruShareButton = createShareButton(\n  \"mailru\",\n  mailruLink,\n  (props) => ({\n    title: props.title,\n    description: props.description,\n    imageUrl: props.imageUrl\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460\n  }\n);\nconst OKIcon = createIcon({\n  color: \"#F97400\",\n  path: \"M39,30c-1,0-3,2-7,2s-6-2-7-2c-1.1,0-2,0.9-2,2c0,1,0.6,1.5,1,1.7c1.2,0.7,5,2.3,5,2.3l-4.3,5.4   c0,0-0.8,0.9-0.8,1.6c0,1.1,0.9,2,2,2c1,0,1.5-0.7,1.5-0.7S32,39,32,39c0,0,4.5,5.3,4.5,5.3S37,45,38,45c1.1,0,2-0.9,2-2   c0-0.6-0.8-1.6-0.8-1.6L35,36c0,0,3.8-1.6,5-2.3c0.4-0.3,1-0.7,1-1.7C41,30.9,40.1,30,39,30z M32,15c-3.9,0-7,3.1-7,7s3.1,7,7,7c3.9,0,7-3.1,7-7S35.9,15,32,15z M32,25.5   c-1.9,0-3.5-1.6-3.5-3.5c0-1.9,1.6-3.5,3.5-3.5c1.9,0,3.5,1.6,3.5,3.5C35.5,23.9,33.9,22.5,35,22.5z \"\n});\nfunction okLink(url, { title, description, image }) {\n  assert(url, \"ok.url\");\n  return \"https://connect.ok.ru/offer\" + objectToGetParams({\n    url,\n    title,\n    description,\n    imageUrl: image\n  });\n}\nconst OKShareButton = createShareButton(\n  \"ok\",\n  okLink,\n  (props) => ({\n    title: props.title,\n    description: props.description,\n    image: props.image\n  }),\n  {\n    windowWidth: 588,\n    windowHeight: 480,\n    windowPosition: \"screenCenter\"\n  }\n);\nfunction getOKShareCount(shareUrl, callback) {\n  if (!window.OK) {\n    window.OK = {\n      Share: {\n        count: function count(index2, _count) {\n          var _a, _b;\n          (_b = (_a = window.OK.callbacks)[index2]) == null ? void 0 : _b.call(_a, _count);\n        }\n      },\n      callbacks: []\n    };\n  }\n  const url = \"https://connect.ok.ru/dk\";\n  const index = window.OK.callbacks.length;\n  window.ODKL = {\n    updateCount(index2, count) {\n      var _a, _b;\n      const callbackIndex = index2 === \"\" ? 0 : parseInt(index2.replace(\"react-share-\", \"\"), 10);\n      (_b = (_a = window.OK.callbacks)[callbackIndex]) == null ? void 0 : _b.call(_a, count === \"\" ? void 0 : parseInt(count, 10));\n    }\n  };\n  window.OK.callbacks.push(callback);\n  return jsonp(\n    url + objectToGetParams({\n      \"st.cmd\": \"extLike\",\n      uid: `react-share-${index}`,\n      ref: shareUrl\n    })\n  );\n}\nconst OKShareCount = createShareCount(getOKShareCount);\nconst PinterestIcon = createIcon({\n  color: \"#E60023\",\n  path: \"M32,16c-8.8,0-16,7.2-16,16c0,6.6,3.9,12.2,9.6,14.7c0-1.1,0-2.5,0.3-3.7 c0.3-1.3,2.1-8.7,2.1-8.7s-0.5-1-0.5-2.5c0-2.4,1.4-4.1,3.1-4.1c1.5,0,2.2,1.1,2.2,2.4c0,1.5-0.9,3.7-1.4,5.7 c-0.4,1.7,0.9,3.1,2.5,3.1c3,0,5.1-3.9,5.1-8.5c0-3.5-2.4-6.1-6.7-6.1c-4.9,0-7.9,3.6-7.9,7.7c0,1.4,0.4,2.4,1.1,3.1 c0.3,0.3,0.3,0.5,0.2,0.9c-0.1,0.3-0.3,1-0.3,1.3c-0.1,0.4-0.4,0.6-0.8,0.4c-2.2-0.9-3.3-3.4-3.3-6.1c0-4.5,3.8-10,11.4-10 c6.1,0,10.1,4.4,10.1,9.2c0,6.3-3.5,11-8.6,11c-1.7,0-3.4-0.9-3.9-2c0,0-0.9,3.7-1.1,4.4c-0.3,1.2-1,2.5-1.6,3.4 c1.4,0.4,3,0.7,4.5,0.7c8.8,0,16-7.2,16-16C48,23.2,40.8,16,32,16z\"\n});\nfunction pinterestLink(url, { media, description, pinId }) {\n  if (pinId) {\n    return `https://pinterest.com/pin/${pinId}/repin/x/`;\n  }\n  assert(url, \"pinterest.url\");\n  assert(media, \"pinterest.media\");\n  return \"https://pinterest.com/pin/create/button/\" + objectToGetParams({\n    url,\n    media,\n    description\n  });\n}\nconst PinterestShareButton = createShareButton(\n  \"pinterest\",\n  pinterestLink,\n  (props) => ({\n    media: props.media,\n    description: props.description,\n    pinId: props.pinId\n  }),\n  {\n    windowWidth: 1e3,\n    windowHeight: 730\n  }\n);\nfunction getPinterestShareCount(shareUrl, callback) {\n  const url = \"https://api.pinterest.com/v1/urls/count.json\";\n  jsonp(\n    url + objectToGetParams({\n      url: shareUrl\n    }),\n    (err, data) => {\n      callback(data ? data.count : void 0);\n    }\n  );\n}\nconst PinterestShareCount = createShareCount(getPinterestShareCount);\nconst PocketIcon = createIcon({\n  color: \"#EF3F56\",\n  path: \"M41.084 29.065l-7.528 7.882a2.104 2.104 0 0 1-1.521.666 2.106 2.106 0 0 1-1.522-.666l-7.528-7.882c-.876-.914-.902-2.43-.065-3.384.84-.955 2.228-.987 3.1-.072l6.015 6.286 6.022-6.286c.88-.918 2.263-.883 3.102.071.841.938.82 2.465-.06 3.383l-.015.002zm6.777-10.976C47.463 16.84 46.361 16 45.14 16H18.905c-1.2 0-2.289.82-2.716 2.044-.125.363-.189.743-.189 1.125v10.539l.112 2.096c.464 4.766 2.73 8.933 6.243 11.838.06.053.125.102.19.153l.04.033c1.882 1.499 3.986 2.514 6.259 3.014a14.662 14.662 0 0 0 6.13.052c.118-.042.235-.065.353-.087.03 0 .065-.022.098-.042a15.395 15.395 0 0 0 6.011-2.945l.039-.045.18-.153c3.502-2.902 5.765-7.072 6.248-11.852L48 29.674v-10.52c0-.366-.041-.728-.161-1.08l.022.015z\"\n});\nfunction pocketLink(url, { title }) {\n  assert(url, \"pocket.url\");\n  return \"https://getpocket.com/save\" + objectToGetParams({\n    url,\n    title\n  });\n}\nconst PocketShareButton = createShareButton(\n  \"pocket\",\n  pocketLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 500,\n    windowHeight: 500\n  }\n);\nconst RedditIcon = createIcon({\n  color: \"#FF5700\",\n  path: \"M 53.34375 32 C 53.277344 30.160156 52.136719 28.53125 50.429688 27.839844 C 48.722656 27.148438 46.769531 27.523438 45.441406 28.800781 C 41.800781 26.324219 37.519531 24.957031 33.121094 24.863281 L 35.199219 14.878906 L 42.046875 16.320312 C 42.214844 17.882812 43.496094 19.09375 45.066406 19.171875 C 46.636719 19.253906 48.03125 18.183594 48.359375 16.644531 C 48.6875 15.105469 47.847656 13.558594 46.382812 12.992188 C 44.914062 12.425781 43.253906 13.007812 42.464844 14.367188 L 34.625 12.800781 C 34.363281 12.742188 34.09375 12.792969 33.871094 12.9375 C 33.648438 13.082031 33.492188 13.308594 33.441406 13.566406 L 31.070312 24.671875 C 26.617188 24.738281 22.277344 26.105469 18.59375 28.609375 C 17.242188 27.339844 15.273438 26.988281 13.570312 27.707031 C 11.863281 28.429688 10.746094 30.089844 10.71875 31.941406 C 10.691406 33.789062 11.757812 35.484375 13.441406 36.257812 C 13.402344 36.726562 13.402344 37.195312 13.441406 37.664062 C 13.441406 44.832031 21.792969 50.65625 32.097656 50.65625 C 42.398438 50.65625 50.753906 44.832031 50.753906 37.664062 C 50.789062 37.195312 50.789062 36.726562 50.753906 36.257812 C 52.363281 35.453125 53.371094 33.800781 53.34375 32 Z M 21.34375 35.199219 C 21.34375 33.433594 22.777344 32 24.542969 32 C 26.3125 32 27.742188 33.433594 27.742188 35.199219 C 27.742188 36.96875 26.3125 38.398438 24.542969 38.398438 C 22.777344 38.398438 21.34375 36.96875 21.34375 35.199219 Z M 39.9375 44 C 37.664062 45.710938 34.871094 46.582031 32.03125 46.464844 C 29.191406 46.582031 26.398438 45.710938 24.128906 44 C 23.847656 43.65625 23.871094 43.15625 24.183594 42.839844 C 24.5 42.527344 25 42.503906 25.34375 42.785156 C 27.269531 44.195312 29.617188 44.90625 32 44.800781 C 34.386719 44.929688 36.746094 44.242188 38.6875 42.847656 C 39.042969 42.503906 39.605469 42.511719 39.953125 42.863281 C 40.296875 43.21875 40.289062 43.785156 39.9375 44.128906 Z M 39.359375 38.527344 C 37.59375 38.527344 36.160156 37.09375 36.160156 35.328125 C 36.160156 33.5625 37.59375 32.128906 39.359375 32.128906 C 41.128906 32.128906 42.558594 33.5625 42.558594 35.328125 C 42.59375 36.203125 42.269531 37.054688 41.65625 37.6875 C 41.046875 38.316406 40.203125 38.664062 39.328125 38.65625 Z M 39.359375 38.527344\"\n});\nfunction redditLink(url, { title }) {\n  assert(url, \"reddit.url\");\n  return \"https://www.reddit.com/web/submit\" + objectToGetParams({\n    url,\n    title\n  });\n}\nconst RedditShareButton = createShareButton(\n  \"reddit\",\n  redditLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460,\n    windowPosition: \"windowCenter\"\n  }\n);\nfunction gabLink(url, { title }) {\n  assert(url, \"gab.url\");\n  return \"https://gab.com/compose\" + objectToGetParams({\n    url,\n    text: title\n  });\n}\nconst GabShareButton = createShareButton(\n  \"gab\",\n  gabLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 640,\n    windowPosition: \"windowCenter\"\n  }\n);\nconst GabIcon = createIcon({\n  color: \"#00d178\",\n  path: \"m17.0506,23.97457l5.18518,0l0,14.23933c0,6.82699 -3.72695,10.09328 -9.33471,10.09328c-2.55969,0 -4.82842,-0.87286 -6.22084,-2.0713l2.07477,-3.88283c1.19844,0.81051 2.33108,1.29543 3.85511,1.29543c2.75366,0 4.44049,-1.97432 4.44049,-4.82149l0,-0.87286c-1.16728,1.39242 -2.81947,2.0713 -4.63446,2.0713c-4.44048,0 -7.81068,-3.68885 -7.81068,-8.28521c0,-4.59289 3.37019,-8.28174 7.81068,-8.28174c1.81499,0 3.46718,0.67888 4.63446,2.0713l0,-1.55521zm-3.62997,11.39217c1.97777,0 3.62997,-1.6522 3.62997,-3.62652c0,-1.97432 -1.6522,-3.62305 -3.62997,-3.62305c-1.97778,0 -3.62997,1.64873 -3.62997,3.62305c0,1.97432 1.65219,3.62652 3.62997,3.62652zm25.7077,4.13913l-5.18518,0l0,-1.29197c-1.00448,1.13264 -2.3969,1.81152 -4.21188,1.81152c-3.62997,0 -5.63893,-2.52504 -5.63893,-5.4034c0,-4.27076 5.251,-5.85715 9.78846,-4.49937c-0.09698,-1.39241 -0.9733,-2.39343 -2.78829,-2.39343c-1.26426,0 -2.72248,0.48492 -3.62997,1.00102l-1.5552,-3.72003c1.19844,-0.77587 3.40136,-1.55174 5.96452,-1.55174c3.78931,0 7.25648,2.13365 7.25648,7.95962l0,8.08777zm-5.18518,-6.14809c-2.42806,-0.77587 -4.66563,-0.3533 -4.66563,1.36124c0,1.00101 0.84168,1.6799 1.84616,1.6799c1.20191,0 2.56315,-0.96984 2.81947,-3.04115zm13.00626,-17.66495l0,9.83695c1.16727,-1.39242 2.81946,-2.0713 4.63445,-2.0713c4.44048,0 7.81068,3.68885 7.81068,8.28174c0,4.59636 -3.37019,8.28521 -7.81068,8.28521c-1.81499,0 -3.46718,-0.67888 -4.63445,-2.0713l0,1.55174l-5.18519,0l0,-23.81304l5.18519,0zm3.62997,19.67391c1.97777,0 3.62997,-1.6522 3.62997,-3.62652c0,-1.97432 -1.6522,-3.62305 -3.62997,-3.62305c-1.97778,0 -3.62997,1.64873 -3.62997,3.62305c0,1.97432 1.65219,3.62652 3.62997,3.62652zm0,0\"\n});\nfunction getRedditShareCount(shareUrl, callback) {\n  const endpoint = `https://www.reddit.com/api/info.json?limit=1&url=${shareUrl}`;\n  jsonp(endpoint, { param: \"jsonp\" }, (err, response) => {\n    callback(\n      !err && response && response.data && response.data.children.length > 0 && response.data.children[0].data.score ? response.data.children[0].data.score : void 0\n    );\n  });\n}\nconst RedditShareCount = createShareCount(getRedditShareCount);\nconst TelegramIcon = createIcon({\n  color: \"#25A3E3\",\n  path: \"m45.90873,15.44335c-0.6901,-0.0281 -1.37668,0.14048 -1.96142,0.41265c-0.84989,0.32661 -8.63939,3.33986 -16.5237,6.39174c-3.9685,1.53296 -7.93349,3.06593 -10.98537,4.24067c-3.05012,1.1765 -5.34694,2.05098 -5.4681,2.09312c-0.80775,0.28096 -1.89996,0.63566 -2.82712,1.72788c-0.23354,0.27218 -0.46884,0.62161 -0.58825,1.10275c-0.11941,0.48114 -0.06673,1.09222 0.16682,1.5716c0.46533,0.96052 1.25376,1.35737 2.18443,1.71383c3.09051,0.99037 6.28638,1.93508 8.93263,2.8236c0.97632,3.44171 1.91401,6.89571 2.84116,10.34268c0.30554,0.69185 0.97105,0.94823 1.65764,0.95525l-0.00351,0.03512c0,0 0.53908,0.05268 1.06412,-0.07375c0.52679,-0.12292 1.18879,-0.42846 1.79109,-0.99212c0.662,-0.62161 2.45836,-2.38812 3.47683,-3.38552l7.6736,5.66477l0.06146,0.03512c0,0 0.84989,0.59703 2.09312,0.68132c0.62161,0.04214 1.4399,-0.07726 2.14229,-0.59176c0.70766,-0.51626 1.1765,-1.34683 1.396,-2.29506c0.65673,-2.86224 5.00979,-23.57745 5.75257,-27.00686l-0.02107,0.08077c0.51977,-1.93157 0.32837,-3.70159 -0.87096,-4.74991c-0.60054,-0.52152 -1.2924,-0.7498 -1.98425,-0.77965l0,0.00176zm-0.2072,3.29069c0.04741,0.0439 0.0439,0.0439 0.00351,0.04741c-0.01229,-0.00351 0.14048,0.2072 -0.15804,1.32576l-0.01229,0.04214l-0.00878,0.03863c-0.75858,3.50668 -5.15554,24.40802 -5.74203,26.96472c-0.08077,0.34417 -0.11414,0.31959 -0.09482,0.29852c-0.1756,-0.02634 -0.50045,-0.16506 -0.52679,-0.1756l-13.13468,-9.70175c4.4988,-4.33199 9.09945,-8.25307 13.744,-12.43229c0.8218,-0.41265 0.68483,-1.68573 -0.29852,-1.70681c-1.04305,0.24584 -1.92279,0.99564 -2.8798,1.47502c-5.49971,3.2626 -11.11882,6.13186 -16.55882,9.49279c-2.792,-0.97105 -5.57873,-1.77704 -8.15298,-2.57601c2.2336,-0.89555 4.00889,-1.55579 5.75608,-2.23009c3.05188,-1.1765 7.01687,-2.7042 10.98537,-4.24067c7.94051,-3.06944 15.92667,-6.16346 16.62028,-6.43037l0.05619,-0.02283l0.05268,-0.02283c0.19316,-0.0878 0.30378,-0.09658 0.35471,-0.10009c0,0 -0.01756,-0.05795 -0.00351,-0.04566l-0.00176,0zm-20.91715,22.0638l2.16687,1.60145c-0.93418,0.91311 -1.81743,1.77353 -2.45485,2.38812l0.28798,-3.98957\"\n});\nfunction telegramLink(url, { title }) {\n  assert(url, \"telegram.url\");\n  return \"https://telegram.me/share/url\" + objectToGetParams({\n    url,\n    text: title\n  });\n}\nconst TelegramShareButton = createShareButton(\n  \"telegram\",\n  telegramLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 550,\n    windowHeight: 400\n  }\n);\nconst ThreadsIcon = createIcon({\n  color: \"#000000\",\n  path: \"M41.4569 31.0027C41.2867 30.9181 41.1138 30.8366 40.9386 30.7586C40.6336 24.9274 37.5624 21.5891 32.4055 21.5549C32.3821 21.5548 32.3589 21.5548 32.3355 21.5548C29.251 21.5548 26.6857 22.9207 25.1067 25.4063L27.9429 27.4247C29.1224 25.5681 30.9736 25.1723 32.3369 25.1723C32.3526 25.1723 32.3684 25.1723 32.384 25.1724C34.082 25.1837 35.3633 25.6958 36.1926 26.6947C36.7961 27.4218 37.1997 28.4267 37.3996 29.6949C35.8941 29.4294 34.266 29.3478 32.5255 29.4513C27.6225 29.7443 24.4705 32.711 24.6822 36.8332C24.7896 38.9242 25.7937 40.7231 27.5094 41.8982C28.96 42.8916 30.8282 43.3774 32.7699 43.2674C35.3341 43.1216 37.3456 42.1066 38.749 40.2507C39.8148 38.8413 40.4889 37.0149 40.7865 34.7136C42.0085 35.4787 42.9142 36.4855 43.4144 37.6959C44.2649 39.7534 44.3145 43.1344 41.6553 45.8908C39.3255 48.3055 36.525 49.3501 32.2926 49.3824C27.5977 49.3463 24.0471 47.7842 21.7385 44.7396C19.5768 41.8886 18.4595 37.7706 18.4179 32.5C18.4595 27.2293 19.5768 23.1113 21.7385 20.2604C24.0471 17.2157 27.5977 15.6537 32.2925 15.6175C37.0215 15.654 40.634 17.2235 43.0309 20.2829C44.2062 21.7831 45.0923 23.6698 45.6764 25.8696L49 24.9496C48.2919 22.2419 47.1778 19.9087 45.6616 17.9736C42.5888 14.0514 38.0947 12.0417 32.3041 12H32.2809C26.5022 12.0415 22.0584 14.0589 19.073 17.9961C16.4165 21.4997 15.0462 26.3747 15.0001 32.4856L15 32.5L15.0001 32.5144C15.0462 38.6252 16.4165 43.5004 19.073 47.004C22.0584 50.941 26.5022 52.9586 32.2809 53H32.3041C37.4418 52.9631 41.0632 51.5676 44.0465 48.4753C47.9496 44.4297 47.8321 39.3587 46.5457 36.2457C45.6227 34.0134 43.8631 32.2002 41.4569 31.0027ZM32.5863 39.6551C30.4374 39.7807 28.205 38.78 28.0949 36.6367C28.0133 35.0476 29.185 33.2743 32.7182 33.0631C33.1228 33.0389 33.5199 33.027 33.9099 33.027C35.1933 33.027 36.3939 33.1564 37.4854 33.4039C37.0783 38.6788 34.6902 39.5353 32.5863 39.6551Z\"\n});\nfunction threadsLink(url, { title }) {\n  assert(url, \"threads.url\");\n  return \"https://threads.net/intent/post\" + objectToGetParams({\n    url,\n    text: title\n  });\n}\nconst ThreadsShareButton = createShareButton(\n  \"threads\",\n  threadsLink,\n  (props) => ({\n    title: props.title\n  }),\n  {\n    windowWidth: 550,\n    windowHeight: 600\n  }\n);\nconst TumblrIcon = createIcon({\n  color: \"#34526f\",\n  path: \"M39.2,41c-0.6,0.3-1.6,0.5-2.4,0.5c-2.4,0.1-2.9-1.7-2.9-3v-9.3h6v-4.5h-6V17c0,0-4.3,0-4.4,0 c-0.1,0-0.2,0.1-0.2,0.2c-0.3,2.3-1.4,6.4-5.9,8.1v3.9h3V39c0,3.4,2.5,8.1,9,8c2.2,0,4.7-1,5.2-1.8L39.2,41z\"\n});\nfunction tumblrLink(url, {\n  title,\n  caption,\n  tags,\n  posttype\n}) {\n  assert(url, \"tumblr.url\");\n  return \"https://www.tumblr.com/widgets/share/tool\" + objectToGetParams({\n    canonicalUrl: url,\n    title,\n    caption,\n    tags,\n    posttype\n  });\n}\nconst TumblrShareButton = createShareButton(\n  \"tumblr\",\n  tumblrLink,\n  (props) => ({\n    title: props.title,\n    tags: (props.tags || []).join(\",\"),\n    caption: props.caption,\n    posttype: props.posttype || \"link\"\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460\n  }\n);\nfunction getTumblrShareCount(shareUrl, callback) {\n  const endpoint = \"https://api.tumblr.com/v2/share/stats\";\n  return jsonp(\n    endpoint + objectToGetParams({\n      url: shareUrl\n    }),\n    (err, data) => {\n      callback(!err && data && data.response ? data.response.note_count : void 0);\n    }\n  );\n}\nconst TumblrShareCount = createShareCount(getTumblrShareCount);\nconst TwitterIcon = createIcon({\n  color: \"#00aced\",\n  path: \"M48,22.1c-1.2,0.5-2.4,0.9-3.8,1c1.4-0.8,2.4-2.1,2.9-3.6c-1.3,0.8-2.7,1.3-4.2,1.6 C41.7,19.8,40,19,38.2,19c-3.6,0-6.6,2.9-6.6,6.6c0,0.5,0.1,1,0.2,1.5c-5.5-0.3-10.3-2.9-13.5-6.9c-0.6,1-0.9,2.1-0.9,3.3 c0,2.3,1.2,4.3,2.9,5.5c-1.1,0-2.1-0.3-3-0.8c0,0,0,0.1,0,0.1c0,3.2,2.3,5.8,5.3,6.4c-0.6,0.1-1.1,0.2-1.7,0.2c-0.4,0-0.8,0-1.2-0.1 c0.8,2.6,3.3,4.5,6.1,4.6c-2.2,1.8-5.1,2.8-8.2,2.8c-0.5,0-1.1,0-1.6-0.1c2.9,1.9,6.4,2.9,10.1,2.9c12.1,0,18.7-10,18.7-18.7 c0-0.3,0-0.6,0-0.8C46,24.5,47.1,23.4,48,22.1z\"\n});\nfunction twitterLink(url, {\n  title,\n  via,\n  hashtags = [],\n  related = []\n}) {\n  assert(url, \"twitter.url\");\n  assert(Array.isArray(hashtags), \"twitter.hashtags is not an array\");\n  assert(Array.isArray(related), \"twitter.related is not an array\");\n  return \"https://twitter.com/intent/tweet\" + objectToGetParams({\n    url,\n    text: title,\n    via,\n    hashtags: hashtags.length > 0 ? hashtags.join(\",\") : void 0,\n    related: related.length > 0 ? related.join(\",\") : void 0\n  });\n}\nconst TwitterShareButton = createShareButton(\n  \"twitter\",\n  twitterLink,\n  (props) => ({\n    hashtags: props.hashtags,\n    title: props.title,\n    via: props.via,\n    related: props.related\n  }),\n  {\n    windowWidth: 550,\n    windowHeight: 400\n  }\n);\nconst ViberIcon = createIcon({\n  color: \"#7360f2\",\n  path: \"m31.0,12.3c9.0,0.2 16.4,6.2 18.0,15.2c0.2,1.5 0.3,3.0 0.4,4.6a1.0,1.0 0 0 1 -0.8,1.2l-0.1,0a1.1,1.1 0 0 1 -1.0,-1.2l0,0c-0.0,-1.2 -0.1,-2.5 -0.3,-3.8a16.1,16.1 0 0 0 -13.0,-13.5c-1.0,-0.1 -2.0,-0.2 -3.0,-0.3c-0.6,-0.0 -1.4,-0.1 -1.6,-0.8a1.1,1.1 0 0 1 0.9,-1.2l0.6,0l0.0,-0.0zm10.6,39.2a19.9,19.9 0 0 1 -2.1,-0.6c-6.9,-2.9 -13.2,-6.6 -18.3,-12.2a47.5,47.5 0 0 1 -7.0,-10.7c-0.8,-1.8 -1.6,-3.7 -2.4,-5.6c-0.6,-1.7 0.3,-3.4 1.4,-4.7a11.3,11.3 0 0 1 3.7,-2.8a2.4,2.4 0 0 1 3.0,0.7a39.0,39.0 0 0 1 4.7,6.5a3.1,3.1 0 0 1 -0.8,4.2c-0.3,0.2 -0.6,0.5 -1.0,0.8a3.3,3.3 0 0 0 -0.7,0.7a2.1,2.1 0 0 0 -0.1,1.9c1.7,4.9 4.7,8.7 9.7,10.8a5.0,5.0 0 0 0 2.5,0.6c1.5,-0.1 2.0,-1.8 3.1,-2.7a2.9,2.9 0 0 1 3.5,-0.1c1.1,0.7 2.2,1.4 3.3,2.2a37.8,37.8 0 0 1 3.1,2.4a2.4,2.4 0 0 1 0.7,3.0a10.4,10.4 0 0 1 -4.4,4.8a10.8,10.8 0 0 1 -1.9,0.6c-0.7,-0.2 0.6,-0.2 0,0l0.0,0l0,-0.0zm3.1,-21.4a4.2,4.2 0 0 1 -0.0,0.6a1.0,1.0 0 0 1 -1.9,0.1a2.7,2.7 0 0 1 -0.1,-0.8a10.9,10.9 0 0 0 -1.4,-5.5a10.2,10.2 0 0 0 -4.2,-4.0a12.3,12.3 0 0 0 -3.4,-1.0c-0.5,-0.0 -1.0,-0.1 -1.5,-0.2a0.9,0.9 0 0 1 -0.9,-1.0l0,-0.1a0.9,0.9 0 0 1 0.9,-0.9l0.1,0a14.1,14.1 0 0 1 5.9,1.5a11.9,11.9 0 0 1 6.5,9.3c0,0.1 0.0,0.3 0.0,0.5c0,0.4 0.0,0.9 0.0,1.5l0,0l0.0,0.0zm-5.6,-0.2a1.1,1.1 0 0 1 -1.2,-0.9l0,-0.1a11.3,11.3 0 0 0 -0.2,-1.4a4.0,4.0 0 0 0 -1.5,-2.3a3.9,3.9 0 0 0 -1.2,-0.5c-0.5,-0.1 -1.1,-0.1 -1.6,-0.2a1.0,1.0 0 0 1 -0.8,-1.1l0,0l0,0a1.0,1.0 0 0 1 1.1,-0.8c3.4,0.2 6.0,2.0 6.3,6.2a2.8,2.8 0 0 1 0,0.8a0.8,0.8 0 0 1 -0.8,0.7l0,0l0.0,-0.0z\"\n});\nfunction viberLink(url, { title, separator }) {\n  assert(url, \"viber.url\");\n  return \"viber://forward\" + objectToGetParams({\n    text: title ? title + separator + url : url\n  });\n}\nconst ViberShareButton = createShareButton(\n  \"viber\",\n  viberLink,\n  (props) => ({\n    title: props.title,\n    separator: props.separator || \" \"\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460\n  }\n);\nconst VKIcon = createIcon({\n  color: \"#4C75A3\",\n  path: \"M44.94,44.84h-0.2c-2.17-.36-3.66-1.92-4.92-3.37C39.1,40.66,38,38.81,36.7,39c-1.85.3-.93,3.52-1.71,4.9-0.62,1.11-3.29.91-5.12,0.71-5.79-.62-8.75-3.77-11.35-7.14A64.13,64.13,0,0,1,11.6,26a10.59,10.59,0,0,1-1.51-4.49C11,20.7,12.56,21,14.11,21c1.31,0,3.36-.29,4.32.2C19,21.46,19.57,23,20,24a37.18,37.18,0,0,0,3.31,5.82c0.56,0.81,1.41,2.35,2.41,2.14s1.06-2.63,1.1-4.18c0-1.77,0-4-.5-4.9S25,22,24.15,21.47c0.73-1.49,2.72-1.63,5.12-1.63,2,0,4.84-.23,5.62,1.12s0.25,3.85.2,5.71c-0.06,2.09-.41,4.25,1,5.21,1.09-.12,1.68-1.2,2.31-2A28,28,0,0,0,41.72,24c0.44-1,.91-2.65,1.71-3,1.21-.47,3.15-0.1,4.92-0.1,1.46,0,4.05-.41,4.52.61,0.39,0.85-.75,3-1.1,3.57a61.88,61.88,0,0,1-4.12,5.61c-0.58.78-1.78,2-1.71,3.27,0.05,0.94,1,1.67,1.71,2.35a33.12,33.12,0,0,1,3.92,4.18c0.47,0.62,1.5,2,1.4,2.76C52.66,45.81,46.88,44.24,44.94,44.84Z\"\n});\nfunction vkLink(url, { title, image, noParse, noVkLinks }) {\n  assert(url, \"vk.url\");\n  return \"https://vk.com/share.php\" + objectToGetParams({\n    url,\n    title,\n    image,\n    noparse: noParse ? 1 : 0,\n    no_vk_links: noVkLinks ? 1 : 0\n  });\n}\nconst VKShareButton = createShareButton(\n  \"vk\",\n  vkLink,\n  (props) => ({\n    title: props.title,\n    image: props.image,\n    noParse: props.noParse,\n    noVkLinks: props.noVkLinks\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 460\n  }\n);\nfunction getVKShareCount(shareUrl, callback) {\n  if (!window.VK) window.VK = {};\n  window.VK.Share = {\n    count: (index2, count) => {\n      var _a, _b;\n      return (_b = (_a = window.VK.callbacks) == null ? void 0 : _a[index2]) == null ? void 0 : _b.call(_a, count);\n    }\n  };\n  window.VK.callbacks = [];\n  const url = \"https://vk.com/share.php\";\n  const index = window.VK.callbacks.length;\n  window.VK.callbacks.push(callback);\n  return jsonp(\n    url + objectToGetParams({\n      act: \"count\",\n      index,\n      url: shareUrl\n    })\n  );\n}\nconst VKShareCount = createShareCount(getVKShareCount);\nconst WeiboIcon = createIcon({\n  color: \"#DF2029\",\n  path: \"M40.9756152,15.0217119 C40.5000732,15.0546301 39.9999314,15.1204666 39.5325878,15.2192213 C38.6634928,15.4085016 38.0977589,16.2643757 38.2863368,17.1284787 C38.4667163,18.0008129 39.3194143,18.5686519 40.1885094,18.3793715 C42.8613908,17.8115326 45.7720411,18.6427174 47.7316073,20.8153207 C49.6911735,22.996153 50.2077122,25.975254 49.3714112,28.5840234 C49.1008441,29.4316684 49.5763861,30.3533789 50.4208857,30.6249537 C51.2653852,30.8965286 52.1754769,30.4192153 52.4542425,29.5715703 C53.6349013,25.9011885 52.9133876,21.7699494 50.1585171,18.7085538 C48.0923641,16.4042776 45.2063093,15.1533848 42.3530505,15.0217119 C41.8775084,14.9970227 41.4511594,14.9887937 40.9756152,15.0217119 Z M27.9227762,19.8277737 C24.9957268,20.140498 20.863421,22.4365431 17.2312548,26.0822378 C13.2711279,30.0571148 11,34.2871065 11,37.9328012 C11,44.9032373 19.8713401,49.125 28.5786978,49.125 C39.9917329,49.125 47.600423,42.4261409 47.600423,37.1427636 C47.600423,33.9496952 44.9603397,32.1638816 42.549827,31.4149913 C41.9594976,31.2339421 41.5167516,31.1434164 41.8283133,30.3616079 C42.5006339,28.66632 42.6236176,27.1932286 41.8939054,26.1480742 C40.5328692,24.1894405 36.7203236,24.2881952 32.448635,26.0822378 C32.448635,26.0822378 31.1203949,26.6912261 31.4647526,25.6213825 C32.1206742,23.4981576 32.0304845,21.712342 31.0056075,20.6836478 C30.2840938,19.9512176 29.2510184,19.6878718 27.9227762,19.8277737 Z M42.0906819,20.6836478 C41.6233383,20.6589586 41.1723917,20.716566 40.7132466,20.8153207 C39.9671353,20.9716828 39.4997917,21.7781784 39.6637721,22.5270687 C39.8277525,23.275959 40.5574647,23.7450433 41.303576,23.5804521 C42.1972686,23.3911718 43.2057485,23.6380596 43.8616701,24.3704897 C44.5175916,25.1029198 44.6733735,26.0657797 44.3864073,26.9381118 C44.1486363,27.6705419 44.5093932,28.4770397 45.2391054,28.7156963 C45.9688176,28.9461239 46.780521,28.5922524 47.0100936,27.8598223 C47.584026,26.0740087 47.2396661,24.0248493 45.8950269,22.5270687 C44.886547,21.4078489 43.4845162,20.7494842 42.0906819,20.6836478 Z M29.496988,29.9665891 C35.3100922,30.1723275 39.9917329,33.0691319 40.3852858,37.0769272 C40.8362324,41.6607904 35.5970585,45.9319315 28.6442899,46.6232144 C21.6915214,47.3144973 15.6488446,44.154347 15.197898,39.5787128 C14.7469514,34.9948495 20.059916,30.7237084 27.004486,30.0324256 C27.8735831,29.950131 28.6688875,29.9336709 29.496988,29.9665891 Z M25.5614586,34.3776322 C23.183744,34.5916017 20.9372116,35.9577073 19.9205332,37.9328012 C18.5348994,40.6238672 19.9041362,43.6029661 23.0689567,44.582284 C26.340366,45.5945202 30.1857056,44.0638213 31.5303448,41.1587879 C32.8503864,38.3195909 31.1613894,35.3734082 27.9227762,34.5751416 C27.1438688,34.3776322 26.356763,34.3035667 25.5614586,34.3776322 Z M24.052839,38.7228388 C24.3316067,38.7310678 24.5857748,38.8215935 24.8399449,38.9203482 C25.8648218,39.3400561 26.1845841,40.4428158 25.5614586,41.4221338 C24.9219361,42.3932227 23.5690963,42.8623069 22.5442194,42.4096807 C21.5357395,41.9652856 21.2487754,40.8542948 21.8882979,39.9078951 C22.3638421,39.2001542 23.2247386,38.7146097 24.052839,38.7228388 Z\"\n});\nfunction weiboLink(url, { title, image }) {\n  assert(url, \"weibo.url\");\n  return \"http://service.weibo.com/share/share.php\" + objectToGetParams({\n    url,\n    title,\n    pic: image\n  });\n}\nconst WeiboShareButton = createShareButton(\n  \"weibo\",\n  weiboLink,\n  (props) => ({\n    title: props.title,\n    image: props.image\n  }),\n  {\n    windowWidth: 660,\n    windowHeight: 550,\n    windowPosition: \"screenCenter\"\n  }\n);\nconst WhatsappIcon = createIcon({\n  color: \"#25D366\",\n  path: \"m42.32286,33.93287c-0.5178,-0.2589 -3.04726,-1.49644 -3.52105,-1.66732c-0.4712,-0.17346 -0.81554,-0.2589 -1.15987,0.2589c-0.34175,0.51004 -1.33075,1.66474 -1.63108,2.00648c-0.30032,0.33658 -0.60064,0.36247 -1.11327,0.12945c-0.5178,-0.2589 -2.17994,-0.80259 -4.14759,-2.56312c-1.53269,-1.37217 -2.56312,-3.05503 -2.86603,-3.57283c-0.30033,-0.5178 -0.03366,-0.80259 0.22524,-1.06149c0.23301,-0.23301 0.5178,-0.59547 0.7767,-0.90616c0.25372,-0.31068 0.33657,-0.5178 0.51262,-0.85437c0.17088,-0.36246 0.08544,-0.64725 -0.04402,-0.90615c-0.12945,-0.2589 -1.15987,-2.79613 -1.58964,-3.80584c-0.41424,-1.00971 -0.84142,-0.88027 -1.15987,-0.88027c-0.29773,-0.02588 -0.64208,-0.02588 -0.98382,-0.02588c-0.34693,0 -0.90616,0.12945 -1.37736,0.62136c-0.4712,0.5178 -1.80194,1.76053 -1.80194,4.27186c0,2.51134 1.84596,4.945 2.10227,5.30747c0.2589,0.33657 3.63497,5.51458 8.80262,7.74113c1.23237,0.5178 2.1903,0.82848 2.94111,1.08738c1.23237,0.38836 2.35599,0.33657 3.24402,0.20712c0.99159,-0.15534 3.04985,-1.24272 3.47963,-2.45956c0.44013,-1.21683 0.44013,-2.22654 0.31068,-2.45955c-0.12945,-0.23301 -0.46601,-0.36247 -0.98382,-0.59548m-9.40068,12.84407l-0.02589,0c-3.05503,0 -6.08417,-0.82849 -8.72495,-2.38189l-0.62136,-0.37023l-6.47252,1.68286l1.73463,-6.29129l-0.41424,-0.64725c-1.70875,-2.71846 -2.6149,-5.85116 -2.6149,-9.07706c0,-9.39809 7.68934,-17.06155 17.15993,-17.06155c4.58253,0 8.88029,1.78642 12.11655,5.02268c3.23625,3.21036 5.02267,7.50812 5.02267,12.06476c-0.0078,9.3981 -7.69712,17.06155 -17.14699,17.06155m14.58906,-31.58846c-3.93529,-3.80584 -9.1133,-5.95471 -14.62789,-5.95471c-11.36055,0 -20.60848,9.2065 -20.61625,20.52564c0,3.61684 0.94757,7.14565 2.75211,10.26282l-2.92557,10.63564l10.93337,-2.85309c3.0136,1.63108 6.4052,2.4958 9.85634,2.49839l0.01037,0c11.36574,0 20.61884,-9.2091 20.62403,-20.53082c0,-5.48093 -2.14111,-10.64081 -6.03239,-14.51915\"\n});\nfunction isMobileOrTablet() {\n  return /(android|iphone|ipad|mobile)/i.test(navigator.userAgent);\n}\nfunction whatsappLink(url, { title, separator }) {\n  assert(url, \"whatsapp.url\");\n  return \"https://\" + (isMobileOrTablet() ? \"api\" : \"web\") + \".whatsapp.com/send\" + objectToGetParams({\n    text: title ? title + separator + url : url\n  });\n}\nconst WhatsappShareButton = createShareButton(\n  \"whatsapp\",\n  whatsappLink,\n  (props) => ({\n    title: props.title,\n    separator: props.separator || \" \"\n  }),\n  {\n    windowWidth: 550,\n    windowHeight: 400\n  }\n);\nconst WorkplaceIcon = createIcon({\n  color: \"#4326c4\",\n  path: \"M34.019,10.292c0.21,0.017,0.423,0.034,0.636,0.049 c3.657,0.262,6.976,1.464,9.929,3.635c3.331,2.448,5.635,5.65,6.914,9.584c0.699,2.152,0.983,4.365,0.885,6.623 c-0.136,3.171-1.008,6.13-2.619,8.867c-0.442,0.75-0.908,1.492-1.495,2.141c-0.588,0.651-1.29,1.141-2.146,1.383 c-1.496,0.426-3.247-0.283-3.961-1.642c-0.26-0.494-0.442-1.028-0.654-1.548c-1.156-2.838-2.311-5.679-3.465-8.519 c-0.017-0.042-0.037-0.082-0.065-0.145c-0.101,0.245-0.192,0.472-0.284,0.698c-1.237,3.051-2.475,6.103-3.711,9.155 c-0.466,1.153-1.351,1.815-2.538,2.045c-1.391,0.267-2.577-0.154-3.496-1.247c-0.174-0.209-0.31-0.464-0.415-0.717 c-2.128-5.22-4.248-10.442-6.37-15.665c-0.012-0.029-0.021-0.059-0.036-0.104c0.054-0.003,0.103-0.006,0.15-0.006 c1.498-0.001,2.997,0,4.495-0.004c0.12-0.001,0.176,0.03,0.222,0.146c1.557,3.846,3.117,7.691,4.679,11.536 c0.018,0.046,0.039,0.091,0.067,0.159c0.273-0.673,0.536-1.32,0.797-1.968c1.064-2.627,2.137-5.25,3.19-7.883 c0.482-1.208,1.376-1.917,2.621-2.135c1.454-0.255,2.644,0.257,3.522,1.449c0.133,0.18,0.229,0.393,0.313,0.603 c1.425,3.495,2.848,6.991,4.269,10.488c0.02,0.047,0.04,0.093,0.073,0.172c0.196-0.327,0.385-0.625,0.559-0.935 c0.783-1.397,1.323-2.886,1.614-4.461c0.242-1.312,0.304-2.634,0.187-3.962c-0.242-2.721-1.16-5.192-2.792-7.38 c-2.193-2.939-5.086-4.824-8.673-5.625c-1.553-0.346-3.124-0.405-4.705-0.257c-3.162,0.298-6.036,1.366-8.585,3.258 c-3.414,2.534-5.638,5.871-6.623,10.016c-0.417,1.76-0.546,3.547-0.384,5.348c0.417,4.601,2.359,8.444,5.804,11.517 c2.325,2.073,5.037,3.393,8.094,3.989c1.617,0.317,3.247,0.395,4.889,0.242c1-0.094,1.982-0.268,2.952-0.529 c0.04-0.01,0.081-0.018,0.128-0.028c0,1.526,0,3.047,0,4.586c-0.402,0.074-0.805,0.154-1.21,0.221 c-0.861,0.14-1.728,0.231-2.601,0.258c-0.035,0.002-0.071,0.013-0.108,0.021c-0.493,0-0.983,0-1.476,0 c-0.049-0.007-0.1-0.018-0.149-0.022c-0.315-0.019-0.629-0.033-0.945-0.058c-1.362-0.105-2.702-0.346-4.017-0.716 c-3.254-0.914-6.145-2.495-8.66-4.752c-2.195-1.971-3.926-4.29-5.176-6.963c-1.152-2.466-1.822-5.057-1.993-7.774 c-0.014-0.226-0.033-0.451-0.05-0.676c0-0.502,0-1.003,0-1.504c0.008-0.049,0.02-0.099,0.022-0.148 c0.036-1.025,0.152-2.043,0.338-3.052c0.481-2.616,1.409-5.066,2.8-7.331c2.226-3.625,5.25-6.386,9.074-8.254 c2.536-1.24,5.217-1.947,8.037-2.126c0.23-0.015,0.461-0.034,0.691-0.051C33.052,10.292,33.535,10.292,34.019,10.292z\"\n});\nfunction workplaceLink(url, { quote, hashtag }) {\n  assert(url, \"workplace.url\");\n  return \"https://work.facebook.com/sharer.php\" + objectToGetParams({\n    u: url,\n    quote,\n    hashtag\n  });\n}\nconst WorkplaceShareButton = createShareButton(\n  \"workplace\",\n  workplaceLink,\n  (props) => ({\n    quote: props.quote,\n    hashtag: props.hashtag\n  }),\n  {\n    windowWidth: 550,\n    windowHeight: 400\n  }\n);\nconst XIcon = createIcon({\n  color: \"#000000\",\n  path: \"M 41.116 18.375 h 4.962 l -10.8405 12.39 l 12.753 16.86 H 38.005 l -7.821 -10.2255 L 21.235 47.625 H 16.27 l 11.595 -13.2525 L 15.631 18.375 H 25.87 l 7.0695 9.3465 z m -1.7415 26.28 h 2.7495 L 24.376 21.189 H 21.4255 z\"\n});\nexport {\n  BlueskyIcon,\n  BlueskyShareButton,\n  EmailIcon,\n  EmailShareButton,\n  FacebookIcon,\n  FacebookMessengerIcon,\n  FacebookMessengerShareButton,\n  FacebookShareButton,\n  FacebookShareCount,\n  GabIcon,\n  GabShareButton,\n  HatenaIcon,\n  HatenaShareButton,\n  HatenaShareCount,\n  InstapaperIcon,\n  InstapaperShareButton,\n  LineIcon,\n  LineShareButton,\n  LinkedinIcon,\n  LinkedinShareButton,\n  LivejournalIcon,\n  LivejournalShareButton,\n  MailruIcon,\n  MailruShareButton,\n  OKIcon,\n  OKShareButton,\n  OKShareCount,\n  PinterestIcon,\n  PinterestShareButton,\n  PinterestShareCount,\n  PocketIcon,\n  PocketShareButton,\n  RedditIcon,\n  RedditShareButton,\n  RedditShareCount,\n  TelegramIcon,\n  TelegramShareButton,\n  ThreadsIcon,\n  ThreadsShareButton,\n  TumblrIcon,\n  TumblrShareButton,\n  TumblrShareCount,\n  TwitterIcon,\n  TwitterShareButton,\n  VKIcon,\n  VKShareButton,\n  VKShareCount,\n  ViberIcon,\n  ViberShareButton,\n  WeiboIcon,\n  WeiboShareButton,\n  WhatsappIcon,\n  WhatsappShareButton,\n  WorkplaceIcon,\n  WorkplaceShareButton,\n  XIcon\n};\n//# sourceMappingURL=index.js.map\n","import React, { useState, useRef } from 'react';\nimport { Dropdown, InputGroup, FormControl, Button } from 'react-bootstrap';\nimport {\n    FacebookShareButton,\n    TwitterShareButton,\n    LinkedinShareButton,\n    EmailShareButton,\n    WeiboShareButton,\n    FacebookIcon,\n    TwitterIcon,\n    LinkedinIcon,\n    EmailIcon,\n    WeiboIcon,\n} from 'react-share';\nimport { useTranslation } from '../libs/i18n';\nimport { showSuccess, showError } from '../libs/toast';\n\ninterface ShareDropdownProps {\n    shareUrl: string;\n    title: string;\n    description?: string;\n    className?: string;\n}\n\nexport const ShareDropdown: React.FC<ShareDropdownProps> = ({\n    shareUrl,\n    title,\n    description = '',\n    className = '',\n}) => {\n    const { t } = useTranslation();\n    const [copied, setCopied] = useState(false);\n    const linkInputRef = useRef<HTMLInputElement>(null);\n\n    const handleCopyLink = async (e?: React.MouseEvent) => {\n        e?.preventDefault();\n        e?.stopPropagation();\n\n        try {\n            if (navigator.clipboard) {\n                await navigator.clipboard.writeText(absoluteShareUrl);\n            } else {\n                // 降级方案\n                if (linkInputRef.current) {\n                    linkInputRef.current.select();\n                    document.execCommand('copy');\n                }\n            }\n            setCopied(true);\n            showSuccess(t('ui.share.linkCopied'));\n\n            // 重置复制状态\n            setTimeout(() => {\n                setCopied(false);\n            }, 2000);\n        } catch (err) {\n            console.error('Failed to copy link:', err);\n            showError(t('ui.error.generic'));\n        }\n    };\n\n    // 检测是否为移动设备并尝试原生分享\n    const handleNativeShare = async () => {\n        if (navigator.share) {\n            try {\n                await navigator.share({\n                    title: title,\n                    text: description,\n                    url: absoluteShareUrl,\n                });\n                return true;\n            } catch (err) {\n                console.log('Native share cancelled or failed:', err);\n            }\n        }\n        return false;\n    };\n\n    // 生成完整的分享URL（确保是绝对URL）\n    const getAbsoluteUrl = (url: string) => {\n        if (url.startsWith('http')) {\n            return url;\n        }\n        return `${window.location.origin}${url.startsWith('/') ? url : '/' + url}`;\n    };\n\n    const absoluteShareUrl = getAbsoluteUrl(shareUrl);\n\n    const CustomToggle = React.forwardRef<\n        HTMLButtonElement,\n        { onClick: (e: React.MouseEvent) => void }\n    >(({ onClick }, ref) => (\n        <Button\n            ref={ref}\n            variant=\"light\"\n            className={`d-flex align-items-center ${className}`}\n            onClick={async e => {\n                // 移动端优先尝试原生分享\n                const isMobile = window.innerWidth <= 768;\n                if (isMobile) {\n                    await handleNativeShare();\n                    return;\n                }\n                onClick(e);\n            }}\n            title={t('ui.button.share')}\n        >\n            <i className=\"bi bi-box-arrow-up\" />\n        </Button>\n    ));\n\n    return (\n        <Dropdown>\n            <Dropdown.Toggle as={CustomToggle} />\n\n            <Dropdown.Menu\n                className=\"shadow-lg border-0\"\n                style={{\n                    minWidth: '320px',\n                    borderRadius: '12px',\n                    padding: '16px',\n                    marginTop: '8px',\n                }}\n            >\n                {/* 标语 */}\n                <div className=\"mb-3\">\n                    <strong>{t('ui.share.slogan')}</strong>\n                </div>\n\n                {/* 复制链接区域 */}\n                <div className=\"mb-3\">\n                    <small className=\"text-muted fw-medium mb-2 d-block\">\n                        {t('ui.share.copyLink')}\n                    </small>\n                    <InputGroup size=\"sm\">\n                        <FormControl\n                            ref={linkInputRef}\n                            type=\"text\"\n                            value={absoluteShareUrl}\n                            readOnly\n                            style={{\n                                backgroundColor: '#f8f9fa',\n                                border: '1px solid #e9ecef',\n                                fontSize: '12px',\n                            }}\n                        />\n                        <Button\n                            variant={copied ? 'secondary' : 'outline-secondary'}\n                            size=\"sm\"\n                            onClick={handleCopyLink}\n                            disabled={copied}\n                            style={{\n                                fontSize: '12px',\n                                padding: '4px 8px',\n                            }}\n                        >\n                            {copied ? (\n                                <i className=\"bi bi-check2\" />\n                            ) : (\n                                <i className=\"bi bi-clipboard\" />\n                            )}\n                        </Button>\n                    </InputGroup>\n                </div>\n\n                {/* 社交分享按钮 */}\n                <div>\n                    <small className=\"text-muted fw-medium mb-2 d-block\">\n                        {t('ui.share.shareVia')}\n                    </small>\n                    <div className=\"d-flex flex-wrap gap-2\">\n                        <FacebookShareButton\n                            url={absoluteShareUrl}\n                            hashtag=\"#zentube\"\n                            className=\"share-btn\"\n                        >\n                            <div className=\"p-2 rounded\">\n                                <FacebookIcon size={32} round />\n                            </div>\n                        </FacebookShareButton>\n\n                        <TwitterShareButton\n                            url={absoluteShareUrl}\n                            title={title}\n                            className=\"share-btn\"\n                        >\n                            <TwitterIcon size={32} round />\n                        </TwitterShareButton>\n\n                        <LinkedinShareButton\n                            url={absoluteShareUrl}\n                            title={title}\n                            summary={description}\n                            className=\"share-btn\"\n                        >\n                            <LinkedinIcon size={32} round />\n                        </LinkedinShareButton>\n\n                        <WeiboShareButton\n                            url={absoluteShareUrl}\n                            title={`${title} ${description}`}\n                            className=\"share-btn\"\n                        >\n                            <WeiboIcon size={32} round />\n                        </WeiboShareButton>\n\n                        <EmailShareButton\n                            url={absoluteShareUrl}\n                            subject={title}\n                            body={description}\n                            className=\"share-btn\"\n                        >\n                            <EmailIcon size={32} round />\n                        </EmailShareButton>\n                    </div>\n                </div>\n            </Dropdown.Menu>\n        </Dropdown>\n    );\n};\n","import { useState, useEffect, useRef, useCallback } from 'react';\nimport {\n    Modal,\n    Button,\n    Form,\n    Spinner,\n    Row,\n    Col,\n    OverlayTrigger,\n    Tooltip,\n} from 'react-bootstrap';\nimport { useTranslation } from '../libs/i18n';\nimport { showError, showSuccess } from '../libs/toast';\nimport { Gift, PaymentType, PaymentStatus } from '@zentube/schema';\nimport { trackPayment } from '../libs/analytics';\nimport { isInAppBrowser } from '../utils/browser';\n\n// localStorage key for pending payment state (shared with payment callback pages)\nconst PENDING_PAYMENT_KEY = 'pendingPayment';\n\ninterface GiftModalProps {\n    show: boolean;\n    onHide: () => void;\n    videoId?: string;\n    videoAuthorId?: number;\n}\n\nexport function GiftModal({\n    show,\n    onHide,\n    videoId,\n    videoAuthorId,\n}: GiftModalProps) {\n    const { t } = useTranslation();\n    const [selectedGift, setSelectedGift] = useState<Gift | null>(null);\n    const [message, setMessage] = useState<string>(t('ui.gift.defaultMessage'));\n    const [gifts, setGifts] = useState<Gift[]>([]);\n    const [giftsLoading, setGiftsLoading] = useState(false);\n    const [donationLoading, setDonationLoading] = useState(false);\n    const [showPaymentResult, setShowPaymentResult] = useState(false);\n    const [paymentId, setPaymentId] = useState<number | null>(null);\n    const [checkingPayment, setCheckingPayment] = useState(false);\n    const paymentWindowRef = useRef<Window | null>(null);\n    const pollingIntervalRef = useRef<NodeJS.Timeout | null>(null);\n    const pollingStartTimeRef = useRef<number | null>(null);\n    const pollingAttemptRef = useRef<number>(0);\n    const hasNotifiedSuccessRef = useRef(false);\n    const hasShownSuccessToastRef = useRef(false);\n    const isVerifyingRef = useRef(false);\n    // 保存用户选择，用于返回时恢复\n    const savedGiftRef = useRef<Gift | null>(null);\n    const savedMessageRef = useRef<string>('');\n\n    // Check if in-app browser\n    const isInApp = isInAppBrowser();\n\n    // 轮询配置\n    const POLLING_CONFIG = {\n        INITIAL_INTERVAL: 2000, // 初始间隔 2 秒\n        MAX_INTERVAL: 10000, // 最大间隔 10 秒\n        TIMEOUT: 30000, // 超时时间 30 秒\n        MAX_ATTEMPTS: 15, // 最大尝试次数（约30秒）\n    };\n\n    // 计算指数退避的轮询间隔\n    const getPollingInterval = useCallback((attempt: number): number => {\n        const interval = Math.min(\n            POLLING_CONFIG.INITIAL_INTERVAL * Math.pow(1.5, attempt),\n            POLLING_CONFIG.MAX_INTERVAL\n        );\n        return Math.round(interval);\n    }, []);\n\n    // 获取道具列表\n    useEffect(() => {\n        if (show) {\n            fetchGifts();\n        }\n    }, [show]);\n\n    // 清理轮询和窗口\n    useEffect(() => {\n        return () => {\n            if (pollingIntervalRef.current) {\n                if (typeof pollingIntervalRef.current === 'number') {\n                    clearTimeout(pollingIntervalRef.current);\n                } else {\n                    clearTimeout(\n                        pollingIntervalRef.current as unknown as number\n                    );\n                }\n            }\n            if (paymentWindowRef.current && !paymentWindowRef.current.closed) {\n                paymentWindowRef.current.close();\n            }\n        };\n    }, []);\n\n    // 停止轮询\n    const stopPolling = useCallback(() => {\n        if (pollingIntervalRef.current) {\n            if (typeof pollingIntervalRef.current === 'number') {\n                clearTimeout(pollingIntervalRef.current);\n            } else {\n                clearTimeout(pollingIntervalRef.current as unknown as number);\n            }\n            pollingIntervalRef.current = null;\n        }\n        pollingStartTimeRef.current = null;\n        pollingAttemptRef.current = 0;\n    }, []);\n\n    const closePaymentWindow = useCallback(() => {\n        if (paymentWindowRef.current && !paymentWindowRef.current.closed) {\n            paymentWindowRef.current.close();\n        }\n        paymentWindowRef.current = null;\n    }, []);\n\n    // 返回到随喜表单\n    const returnToGiftForm = useCallback(() => {\n        // 停止轮询\n        stopPolling();\n        // 关闭支付结果弹窗\n        setShowPaymentResult(false);\n        setCheckingPayment(false);\n        // 恢复用户选择\n        if (savedGiftRef.current) {\n            setSelectedGift(savedGiftRef.current);\n        }\n        if (savedMessageRef.current) {\n            setMessage(savedMessageRef.current);\n        }\n        // 关闭 PayPal 窗口\n        closePaymentWindow();\n        hasNotifiedSuccessRef.current = false;\n        hasShownSuccessToastRef.current = false;\n        isVerifyingRef.current = false;\n    }, [closePaymentWindow, stopPolling]);\n\n    const notifyDonationSuccess = useCallback(() => {\n        if (hasNotifiedSuccessRef.current) {\n            return;\n        }\n        hasNotifiedSuccessRef.current = true;\n\n        const gift = savedGiftRef.current ?? selectedGift;\n        const amount = gift?.amount ?? 0;\n        const donationMessage =\n            savedMessageRef.current || message || t('ui.gift.defaultMessage');\n\n        if (videoId) {\n            window.dispatchEvent(\n                new CustomEvent('donation:completed', {\n                    detail: {\n                        videoId,\n                        amount,\n                        message: donationMessage,\n                        timestamp: Date.now(),\n                    },\n                })\n            );\n        }\n    }, [message, selectedGift, t, videoId]);\n\n    const showDonationSuccessToast = useCallback(() => {\n        if (hasShownSuccessToastRef.current) {\n            return;\n        }\n        hasShownSuccessToastRef.current = true;\n        showSuccess(t('ui.gift.messages.donationRecorded'));\n    }, [t]);\n\n    const handlePaymentSuccess = useCallback(() => {\n        stopPolling();\n        closePaymentWindow();\n        setShowPaymentResult(false);\n        setCheckingPayment(false);\n        setPaymentId(null);\n        pollingStartTimeRef.current = null;\n        pollingAttemptRef.current = 0;\n        notifyDonationSuccess();\n        showDonationSuccessToast();\n        isVerifyingRef.current = false;\n\n        // 追踪支付成功\n        trackPayment({\n            action: 'success',\n            video_id: videoId,\n        });\n\n        onHide();\n    }, [\n        closePaymentWindow,\n        notifyDonationSuccess,\n        onHide,\n        showDonationSuccessToast,\n        stopPolling,\n        videoId,\n    ]);\n\n    const handlePaymentFailure = useCallback(\n        (errorMessage?: string) => {\n            // 追踪支付失败\n            trackPayment({\n                action: 'failure',\n                video_id: videoId,\n                error: errorMessage,\n            });\n\n            if (errorMessage) {\n                showError(errorMessage);\n            }\n            returnToGiftForm();\n        },\n        [returnToGiftForm, videoId]\n    );\n\n    // 检查支付状态（简化版，只做状态检查，不做窗口关闭检测）\n    const checkPaymentStatus = useCallback(async () => {\n        if (!paymentId) return;\n\n        // 检查是否超时\n        if (pollingStartTimeRef.current) {\n            const elapsed = Date.now() - pollingStartTimeRef.current;\n            if (elapsed > POLLING_CONFIG.TIMEOUT) {\n                // 超时后最后检查一次状态\n                try {\n                    const response = await fetch(\n                        `/api/payments/${paymentId}/status`\n                    );\n                    const data = await response.json();\n\n                    if (data.success && data.data) {\n                        const status = data.data.status;\n\n                        if (status === PaymentStatus.PENDING) {\n                            // 超时后还是 pending，提示并返回\n                            stopPolling();\n                            setCheckingPayment(false);\n                            showError(\n                                t('ui.gift.messages.paymentStatusNotUpdated')\n                            );\n                            returnToGiftForm();\n                            return;\n                        } else if (status === PaymentStatus.COMPLETED) {\n                            handlePaymentSuccess();\n                            return;\n                        } else if (\n                            status === PaymentStatus.CANCELLED ||\n                            status === PaymentStatus.FAILED\n                        ) {\n                            handlePaymentFailure(\n                                status === PaymentStatus.CANCELLED\n                                    ? t('ui.gift.messages.paymentCancelled')\n                                    : t('ui.gift.messages.paymentFailed')\n                            );\n                            return;\n                        }\n                    }\n                } catch (error) {\n                    console.error('Error checking payment status:', error);\n                    handlePaymentFailure(\n                        t('ui.gift.messages.checkPaymentStatusFailed')\n                    );\n                    return;\n                }\n            }\n        }\n\n        // 正常轮询检查\n        try {\n            const response = await fetch(`/api/payments/${paymentId}/status`);\n            const data = await response.json();\n\n            if (data.success && data.data) {\n                const status = data.data.status;\n\n                if (status === PaymentStatus.COMPLETED) {\n                    handlePaymentSuccess();\n                    return;\n                } else if (\n                    status === PaymentStatus.CANCELLED ||\n                    status === PaymentStatus.FAILED\n                ) {\n                    handlePaymentFailure(\n                        status === PaymentStatus.CANCELLED\n                            ? t('ui.gift.messages.paymentCancelled')\n                            : t('ui.gift.messages.paymentFailed')\n                    );\n                    return;\n                }\n                // 如果状态还是 pending，继续轮询\n            }\n        } catch (error) {\n            console.error('Error checking payment status:', error);\n            // 轮询出错时不停止，继续尝试\n        }\n    }, [\n        handlePaymentFailure,\n        handlePaymentSuccess,\n        paymentId,\n        returnToGiftForm,\n        stopPolling,\n        t,\n    ]);\n\n    const fetchGifts = async () => {\n        setGiftsLoading(true);\n        try {\n            const response = await fetch('/api/gifts');\n            const data = await response.json();\n\n            if (data.success) {\n                setGifts(data.data);\n            } else {\n                showError(data.error || t('ui.gift.errors.giftNotFound'));\n            }\n        } catch (err) {\n            showError(t('ui.error.network'));\n            console.error('Error fetching gifts:', err);\n        } finally {\n            setGiftsLoading(false);\n        }\n    };\n\n    const handleGiftSelect = (gift: Gift) => {\n        setSelectedGift(gift);\n    };\n\n    const handleClose = () => {\n        // 清理轮询\n        stopPolling();\n        // 关闭 PayPal 窗口\n        if (paymentWindowRef.current && !paymentWindowRef.current.closed) {\n            paymentWindowRef.current.close();\n            paymentWindowRef.current = null;\n        }\n        // 重置状态\n        setSelectedGift(null);\n        setMessage(t('ui.gift.defaultMessage'));\n        setShowPaymentResult(false);\n        setPaymentId(null);\n        setCheckingPayment(false);\n        pollingStartTimeRef.current = null;\n        savedGiftRef.current = null;\n        savedMessageRef.current = '';\n        onHide();\n    };\n\n    // 处理\"已完成支付\"按钮点击（手动触发轮询）\n    const handlePaymentCompleted = useCallback(() => {\n        if (!paymentId || isVerifyingRef.current) return;\n\n        isVerifyingRef.current = true;\n\n        setCheckingPayment(true);\n        // 开始轮询\n        pollingStartTimeRef.current = Date.now();\n        pollingAttemptRef.current = 0;\n\n        // 使用动态轮询间隔（指数退避）\n        const scheduleNextPoll = () => {\n            // 检查轮询是否应该继续（如果已停止，pollingIntervalRef.current 会被设置为 null）\n            // 第一次调用时，pollingIntervalRef.current 是 null，但应该继续，所以不在这里检查\n            // 而是在设置 timeout 后，在 finally 中检查\n\n            const interval = getPollingInterval(pollingAttemptRef.current);\n            pollingAttemptRef.current += 1;\n\n            pollingIntervalRef.current = setTimeout(() => {\n                checkPaymentStatus().finally(() => {\n                    // 如果还在轮询中（pollingIntervalRef.current 不为 null），继续调度下一次\n                    if (pollingIntervalRef.current) {\n                        scheduleNextPoll();\n                    }\n                });\n            }, interval) as unknown as NodeJS.Timeout;\n        };\n\n        // 立即执行第一次检查\n        checkPaymentStatus().finally(() => {\n            // 第一次调用时，pollingIntervalRef.current 是 null，但应该继续轮询\n            // 所以直接调用 scheduleNextPoll，它会设置第一个 timeout\n            scheduleNextPoll();\n        });\n    }, [paymentId, getPollingInterval, checkPaymentStatus]);\n\n    // 检测 URL 参数处理支付结果（应用内浏览器重定向模式）\n    useEffect(() => {\n        const urlParams = new URLSearchParams(window.location.search);\n        const paymentSuccess = urlParams.get('payment_success');\n        const paymentCancelled = urlParams.get('payment_cancelled');\n        const paymentError = urlParams.get('payment_error');\n        const urlPaymentId = urlParams.get('payment_id');\n\n        // 清理 URL 参数（避免刷新时重复处理）\n        const cleanUrl = () => {\n            const url = new URL(window.location.href);\n            url.searchParams.delete('payment_success');\n            url.searchParams.delete('payment_cancelled');\n            url.searchParams.delete('payment_error');\n            url.searchParams.delete('payment_id');\n            url.searchParams.delete('error_message');\n            window.history.replaceState({}, '', url.toString());\n        };\n\n        if (paymentSuccess === '1' && urlPaymentId) {\n            // 支付成功：设置 paymentId 并触发验证\n            setPaymentId(parseInt(urlPaymentId));\n            cleanUrl();\n            // 延迟触发支付验证，等待 paymentId 状态更新\n            setTimeout(() => {\n                handlePaymentCompleted();\n            }, 100);\n        } else if (paymentCancelled === '1') {\n            // 支付取消\n            cleanUrl();\n            showError(t('ui.gift.messages.paymentCancelled'));\n\n            // 追踪支付取消\n            trackPayment({\n                action: 'cancel',\n                video_id: videoId,\n            });\n        } else if (paymentError === '1') {\n            // 支付错误\n            const errorMessage = urlParams.get('error_message');\n            cleanUrl();\n            showError(\n                errorMessage\n                    ? decodeURIComponent(errorMessage)\n                    : t('ui.gift.messages.paymentFailed')\n            );\n\n            // 追踪支付失败\n            trackPayment({\n                action: 'failure',\n                video_id: videoId,\n                error: errorMessage || 'payment_error',\n            });\n        }\n    }, [handlePaymentCompleted, t]);\n\n    const handleDonation = async () => {\n        if (!selectedGift) return;\n\n        setDonationLoading(true);\n\n        // 应用内浏览器使用重定向模式，普通浏览器使用弹窗模式\n        let paymentWindow: Window | null = null;\n\n        if (!isInApp) {\n            // Safari 兼容性修复: 立即打开窗口(在用户点击事件的同步上下文中)\n            // 这样 Safari 不会阻止弹窗\n            paymentWindow = window.open(\n                'about:blank',\n                '_blank',\n                'width=800,height=600'\n            );\n\n            if (!paymentWindow) {\n                // 在普通浏览器中，提示允许弹窗\n                showError(t('ui.gift.messages.allowPopup'));\n                setDonationLoading(false);\n                return;\n            }\n        }\n\n        // 在新窗口中显示加载状态（仅弹窗模式）\n        if (paymentWindow) {\n            paymentWindow.document.write(`\n            <!DOCTYPE html>\n            <html>\n            <head>\n                <meta charset=\"utf-8\">\n                <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n                <title>${t('ui.gift.paymentRedirect.title')}</title>\n                <style>\n                    * {\n                        margin: 0;\n                        padding: 0;\n                        box-sizing: border-box;\n                    }\n                    body {\n                        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n                        display: flex;\n                        align-items: center;\n                        justify-content: center;\n                        min-height: 100vh;\n                        background-color: #f8f9fa;\n                        color: #212529;\n                    }\n                    .container {\n                        text-align: center;\n                        padding: 2rem;\n                        background: white;\n                        border-radius: 8px;\n                        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n                        max-width: 400px;\n                        width: 90%;\n                    }\n                    .spinner {\n                        width: 40px;\n                        height: 40px;\n                        margin: 0 auto 1.5rem;\n                        border: 3px solid #e9ecef;\n                        border-top-color: #0d6efd;\n                        border-radius: 50%;\n                        animation: spin 0.8s linear infinite;\n                    }\n                    @keyframes spin {\n                        to { transform: rotate(360deg); }\n                    }\n                    h2 {\n                        margin: 0 0 0.75rem;\n                        font-size: 1.25rem;\n                        font-weight: 500;\n                        color: #212529;\n                    }\n                    p {\n                        margin: 0;\n                        font-size: 0.875rem;\n                        color: #6c757d;\n                        line-height: 1.5;\n                    }\n                </style>\n            </head>\n            <body>\n                <div class=\"container\">\n                    <div class=\"spinner\"></div>\n                    <h2>${t('ui.gift.paymentRedirect.heading')}</h2>\n                    <p>${t('ui.gift.paymentRedirect.description')}</p>\n                </div>\n            </body>\n            </html>\n        `);\n            // 保存窗口引用\n            paymentWindowRef.current = paymentWindow;\n        }\n\n        // 保存用户选择\n        savedGiftRef.current = selectedGift;\n        savedMessageRef.current = message;\n        hasNotifiedSuccessRef.current = false;\n        hasShownSuccessToastRef.current = false;\n        isVerifyingRef.current = false;\n\n        // 追踪支付开始\n        trackPayment({\n            action: 'start',\n            video_id: videoId,\n        });\n\n        try {\n            // 1. 先创建随喜记录\n            const donationResponse = await fetch('/api/donations', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json',\n                },\n                body: JSON.stringify({\n                    videoId,\n                    videoAuthorId,\n                    giftId: selectedGift.id,\n                    amount: selectedGift.amount,\n                    message,\n                    // 不传 paymentId,因为还没有支付\n                }),\n            });\n\n            const donationData = await donationResponse.json();\n\n            if (!donationData.success) {\n                throw new Error(\n                    donationData.message ||\n                        donationData.error ||\n                        t('ui.gift.errors.donationFailed')\n                );\n            }\n\n            // 2. 基于随喜记录创建支付订单\n            const paymentResponse = await fetch('/api/payments/create-order', {\n                method: 'POST',\n                headers: {\n                    'Content-Type': 'application/json',\n                },\n                body: JSON.stringify({\n                    amount: selectedGift.amount,\n                    currency: 'USD',\n                    description: t('ui.gift.paymentDescription', {\n                        authorName: selectedGift.name,\n                        message,\n                    }),\n                    type: PaymentType.DONATION,\n                    metadata: {\n                        donationId: donationData.data.id,\n                        videoId,\n                        videoAuthorId,\n                        giftId: selectedGift.id,\n                        giftAmount: selectedGift.amount,\n                        message,\n                    },\n                }),\n            });\n\n            const paymentData = await paymentResponse.json();\n\n            if (!paymentData.success) {\n                throw new Error(\n                    paymentData.message ||\n                        paymentData.error ||\n                        t('api.payment.createOrderFailed')\n                );\n            }\n\n            const paymentId = paymentData.data.paymentId;\n\n            // 保存 paymentId\n            setPaymentId(paymentId);\n\n            // 3. 获取支付 URL 并重定向窗口\n            let paymentUrl: string | null = null;\n            if (paymentData.data.approvalUrl) {\n                // PayPal 支付\n                paymentUrl = paymentData.data.approvalUrl;\n            } else if (paymentData.data.checkoutUrl) {\n                // Stripe 支付\n                paymentUrl = paymentData.data.checkoutUrl;\n            } else {\n                // 未知的支付方式响应格式\n                throw new Error(\n                    paymentData.message ||\n                        paymentData.error ||\n                        t('api.payment.createOrderFailed')\n                );\n            }\n\n            // 重定向到支付页面\n            if (paymentUrl) {\n                if (isInApp) {\n                    // 应用内浏览器：保存状态到 localStorage，然后重定向\n                    localStorage.setItem(\n                        PENDING_PAYMENT_KEY,\n                        JSON.stringify({\n                            videoId,\n                            giftId: selectedGift.id,\n                            message,\n                            paymentId,\n                            returnUrl: window.location.href,\n                        })\n                    );\n                    // 直接重定向到支付页面\n                    window.location.href = paymentUrl;\n                    return; // 页面会重定向，不需要继续执行\n                } else if (paymentWindow && !paymentWindow.closed) {\n                    // 普通浏览器：弹窗模式\n                    paymentWindow.location.href = paymentUrl;\n                }\n            }\n\n            // 隐藏随喜弹窗,显示支付结果弹窗（仅弹窗模式）\n            setDonationLoading(false);\n            setShowPaymentResult(true);\n        } catch (err) {\n            // 如果出错,关闭已打开的空白窗口（仅弹窗模式）\n            if (!isInApp && paymentWindow && !paymentWindow.closed) {\n                paymentWindow.close();\n            }\n            paymentWindowRef.current = null;\n\n            let errorMessage = '';\n\n            // 处理不同类型的错误\n            if (err instanceof Error) {\n                errorMessage = err.message;\n            } else if (\n                typeof err === 'object' &&\n                err !== null &&\n                'error' in err\n            ) {\n                // 处理 API 返回的错误格式\n                errorMessage = (err as { error: string }).error;\n            } else {\n                errorMessage = t('ui.gift.errors.donationFailed');\n            }\n\n            // 直接显示后端返回的错误消息\n            showError(errorMessage);\n            console.error('Donation process failed:', err);\n            setDonationLoading(false);\n        }\n    };\n\n    // 监听来自支付回调页面的消息（支付窗口 postMessage）\n    useEffect(() => {\n        const handleMessage = (event: MessageEvent) => {\n            if (event.origin !== window.location.origin) {\n                return;\n            }\n\n            const { type, message, timestamp } = event.data;\n\n            if (timestamp) {\n                const age = Date.now() - timestamp;\n                if (age > 5 * 60 * 1000) {\n                    console.warn('Message too old, ignoring:', type);\n                    return;\n                }\n            }\n\n            if (type === 'payment-cancelled') {\n                stopPolling();\n                setCheckingPayment(false);\n                setShowPaymentResult(false);\n                showError(t('ui.gift.messages.paymentCancelled'));\n\n                // 追踪支付取消\n                trackPayment({\n                    action: 'cancel',\n                    video_id: videoId,\n                });\n\n                returnToGiftForm();\n            } else if (type === 'payment-error') {\n                stopPolling();\n                setCheckingPayment(false);\n                setShowPaymentResult(false);\n                showError(message || t('ui.gift.messages.paymentFailed'));\n\n                // 追踪支付失败\n                trackPayment({\n                    action: 'failure',\n                    video_id: videoId,\n                    error: message || 'payment_error',\n                });\n\n                returnToGiftForm();\n            } else if (type === 'payment-success') {\n                handlePaymentCompleted();\n            }\n        };\n\n        window.addEventListener('message', handleMessage);\n        return () => window.removeEventListener('message', handleMessage);\n    }, [stopPolling, returnToGiftForm, t, handlePaymentCompleted]);\n\n    return (\n        <>\n            {/* 支付结果弹窗 */}\n            <Modal show={showPaymentResult} onHide={handleClose} centered>\n                <Modal.Header closeButton>\n                    <Modal.Title as=\"h5\">\n                        {t('ui.gift.paymentResult.title')}\n                    </Modal.Title>\n                </Modal.Header>\n                <Modal.Body className=\"py-4\">\n                    <h6 className=\"mb-2\">\n                        {t('ui.gift.paymentResult.paying')}\n                    </h6>\n                    <p className=\"mb-0\">\n                        {t('ui.gift.paymentResult.instruction')}\n                    </p>\n                </Modal.Body>\n                <Modal.Footer>\n                    <Button\n                        variant=\"link\"\n                        className=\"text-decoration-none\"\n                        onClick={returnToGiftForm}\n                    >\n                        {t('ui.gift.paymentResult.hasProblem')}\n                    </Button>\n                    <Button\n                        variant=\"primary\"\n                        onClick={handlePaymentCompleted}\n                        disabled={checkingPayment}\n                    >\n                        {checkingPayment ? (\n                            <>\n                                <Spinner\n                                    as=\"span\"\n                                    animation=\"border\"\n                                    size=\"sm\"\n                                    role=\"status\"\n                                    aria-hidden=\"true\"\n                                    className=\"me-2\"\n                                />\n                                {t('ui.gift.paymentResult.checking')}\n                            </>\n                        ) : (\n                            t('ui.gift.paymentResult.completed')\n                        )}\n                    </Button>\n                </Modal.Footer>\n            </Modal>\n\n            {/* 随喜弹窗 */}\n            <Modal\n                show={show && !showPaymentResult}\n                onHide={handleClose}\n                centered\n            >\n                <Modal.Header closeButton>\n                    <Modal.Title as=\"h5\">{t('ui.gift.title')}</Modal.Title>\n                </Modal.Header>\n                <Modal.Body>\n                    {/* 道具选择区域 - 3列网格布局 */}\n                    {giftsLoading ? (\n                        <div className=\"text-center py-4\">\n                            <Spinner animation=\"border\" variant=\"primary\" />\n                            <div className=\"mt-2 text-muted\">\n                                {t('ui.gift.loading')}\n                            </div>\n                        </div>\n                    ) : (\n                        <Row className=\"mb-2 g-2\">\n                            {gifts.map(gift => {\n                                const tooltip = (\n                                    <Tooltip id={`gift-tooltip-${gift.id}`}>\n                                        {gift.buddhistMeaning ||\n                                            gift.description}\n                                    </Tooltip>\n                                );\n\n                                return (\n                                    <Col key={gift.id} xs={4}>\n                                        <OverlayTrigger\n                                            placement=\"top\"\n                                            overlay={tooltip}\n                                            delay={{\n                                                show: 300,\n                                                hide: 100,\n                                            }}\n                                        >\n                                            <div\n                                                className={`p-3 rounded-2 text-center h-100 ${selectedGift?.id === gift.id ? 'bg-primary-subtle' : ''}`}\n                                                onClick={() =>\n                                                    handleGiftSelect(gift)\n                                                }\n                                                style={{\n                                                    cursor: 'pointer',\n                                                    transition: 'all 0.2s ease',\n                                                }}\n                                                onMouseEnter={e => {\n                                                    e.currentTarget.style.transform =\n                                                        'scale(1.05)';\n                                                }}\n                                                onMouseLeave={e => {\n                                                    e.currentTarget.style.transform =\n                                                        'scale(1)';\n                                                }}\n                                            >\n                                                <div\n                                                    className=\"lh-1\"\n                                                    style={{\n                                                        fontSize: '48px',\n                                                    }}\n                                                >\n                                                    {gift.emoji}\n                                                </div>\n                                                <div className=\"fw-medium\">\n                                                    ${gift.amount}\n                                                </div>\n                                            </div>\n                                        </OverlayTrigger>\n                                    </Col>\n                                );\n                            })}\n                        </Row>\n                    )}\n\n                    {/* 附言输入框 */}\n                    <Form.Group>\n                        <Form.Label className=\"fs-6 fw-semibold\">\n                            {t('ui.gift.messageLabel')}\n                        </Form.Label>\n                        <Form.Control\n                            type=\"text\"\n                            placeholder={t('ui.gift.defaultMessage')}\n                            value={message}\n                            onChange={e => setMessage(e.target.value)}\n                            maxLength={200}\n                        />\n                        <Form.Text className=\"text-muted\">\n                            {t('ui.gift.meritNotice')}\n                        </Form.Text>\n                    </Form.Group>\n                </Modal.Body>\n                <Modal.Footer>\n                    {selectedGift ? (\n                        <Button\n                            variant=\"primary\"\n                            onClick={handleDonation}\n                            disabled={donationLoading}\n                        >\n                            {donationLoading ? (\n                                <>\n                                    <Spinner\n                                        as=\"span\"\n                                        animation=\"border\"\n                                        size=\"sm\"\n                                        role=\"status\"\n                                        aria-hidden=\"true\"\n                                        className=\"me-2\"\n                                    />\n                                    {t('ui.gift.processing')}\n                                </>\n                            ) : (\n                                `${t('ui.gift.donateButton')} $${selectedGift.amount}`\n                            )}\n                        </Button>\n                    ) : (\n                        <Button variant=\"secondary\" disabled>\n                            {t('ui.gift.selectGift')}\n                        </Button>\n                    )}\n                </Modal.Footer>\n            </Modal>\n        </>\n    );\n}\n","import { Badge } from 'react-bootstrap';\nimport { Comment } from '@zentube/schema';\n\ninterface DonationCommentDisplayProps {\n    comment: Comment;\n}\n\nexport function DonationCommentDisplay({\n    comment,\n}: DonationCommentDisplayProps) {\n    // 检查是否为随喜评论\n    const isDonationComment = comment.metadata?.type === 'donation';\n\n    if (!isDonationComment) {\n        return null;\n    }\n\n    const giftAmount = comment.metadata?.giftAmount || 0;\n\n    return (\n        <Badge bg=\"warning\" pill text=\"dark\" className=\"ms-1\">\n            <span className=\"fw-bold\">${giftAmount}</span>\n        </Badge>\n    );\n}\n","import { VideoPlayer } from './videoplayer';\nimport { Video } from '@zentube/schema';\nimport { useTranslation } from '../../libs/i18n';\n\ninterface VideoPlayerContainerProps {\n    video: Video | null;\n    loading: boolean;\n    error: string;\n    currentUserId?: number;\n    initialProgress?: number;\n}\n\nexport function VideoPlayerContainer({\n    video,\n    loading,\n    error,\n    currentUserId,\n    initialProgress,\n}: VideoPlayerContainerProps) {\n    const { t } = useTranslation();\n\n    if (loading) {\n        return (\n            <div\n                className=\"bg-dark rounded d-flex align-items-center justify-content-center\"\n                style={{ aspectRatio: '16/9', minHeight: '400px' }}\n            >\n                <div className=\"text-center text-white\">\n                    <div className=\"spinner-border\" role=\"status\">\n                        <span className=\"visually-hidden\">\n                            {t('ui.common.loading')}\n                        </span>\n                    </div>\n                    <p className=\"mt-3\">{t('ui.player.uploading')}</p>\n                </div>\n            </div>\n        );\n    }\n\n    if (error || !video) {\n        return (\n            <div\n                className=\"bg-danger rounded d-flex align-items-center justify-content-center\"\n                style={{ aspectRatio: '16/9', minHeight: '400px' }}\n            >\n                <div className=\"text-center text-white\">\n                    <h4>{t('ui.error.errorLoadingVideo')}</h4>\n                    <p>{error || t('ui.error.videoNotFound')}</p>\n                </div>\n            </div>\n        );\n    }\n\n    return (\n        <VideoPlayer\n            videoId={video.id}\n            streamId={video.streamId}\n            token={video.token}\n            status={video.status}\n            processStatus={video.processStatus}\n            poster={video.thumbnailUrls?.large}\n            currentUserId={currentUserId}\n            initialProgress={initialProgress}\n            reviewReason={video.reviewReason}\n            coursePlayback={video.coursePlayback}\n            title={video.title}\n        />\n    );\n}\n","import React from 'react';\nimport { Modal, Button } from 'react-bootstrap';\n\ninterface ConfirmModalProps {\n    show: boolean;\n    title?: string;\n    message: string;\n    confirmText?: string;\n    cancelText?: string;\n    variant?: 'primary' | 'danger' | 'warning' | 'success';\n    onConfirm: () => void;\n    onCancel: () => void;\n}\n\nexport const ConfirmModal: React.FC<ConfirmModalProps> = ({\n    show,\n    title = '确认操作',\n    message,\n    confirmText = '确认',\n    cancelText = '取消',\n    variant = 'danger',\n    onConfirm,\n    onCancel,\n}) => {\n    return (\n        <Modal show={show} onHide={onCancel} centered>\n            <Modal.Header closeButton>\n                <Modal.Title>{title}</Modal.Title>\n            </Modal.Header>\n            <Modal.Body>\n                <p className=\"mb-0\">{message}</p>\n            </Modal.Body>\n            <Modal.Footer>\n                <Button\n                    variant=\"link\"\n                    className=\"text-decoration-none\"\n                    onClick={onCancel}\n                >\n                    {cancelText}\n                </Button>\n                <Button\n                    variant={variant}\n                    onClick={() => {\n                        onConfirm();\n                        onCancel(); // 关闭模态框\n                    }}\n                >\n                    {confirmText}\n                </Button>\n            </Modal.Footer>\n        </Modal>\n    );\n};\n","import { useState, useEffect } from 'react';\nimport { Modal, Button, Form, Alert, Stack } from 'react-bootstrap';\nimport { api, getErrorMessage } from '../../libs';\nimport { useTranslation } from '../../libs/i18n';\n\ninterface ReportReason {\n    value: string;\n    label: string;\n}\n\ninterface ReportModalProps {\n    show: boolean;\n    onHide: () => void;\n    videoId: string;\n}\n\nexport function ReportModal({ show, onHide, videoId }: ReportModalProps) {\n    const { t } = useTranslation();\n    const [reasons, setReasons] = useState<ReportReason[]>([]);\n    const [selectedReason, setSelectedReason] = useState('');\n    const [description, setDescription] = useState('');\n    const [loading, setLoading] = useState(false);\n    const [error, setError] = useState('');\n    const [success, setSuccess] = useState(false);\n    const [loadingReasons, setLoadingReasons] = useState(false);\n\n    // Load report reasons when modal shows\n    useEffect(() => {\n        if (show && reasons.length === 0) {\n            loadReportReasons();\n        }\n    }, [show, reasons.length]);\n\n    // Reset form when modal is hidden\n    useEffect(() => {\n        if (!show) {\n            setSelectedReason('');\n            setDescription('');\n            setError('');\n            setSuccess(false);\n        }\n    }, [show]);\n\n    const loadReportReasons = async () => {\n        try {\n            setLoadingReasons(true);\n            const response = await api.get('/api/reports/reasons');\n            if (response.data?.data) {\n                setReasons(response.data.data);\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setLoadingReasons(false);\n        }\n    };\n\n    const handleSubmit = async (e: React.FormEvent) => {\n        e.preventDefault();\n\n        if (!selectedReason.trim()) {\n            setError(t('ui.report.selectReason'));\n            return;\n        }\n\n        try {\n            setLoading(true);\n            setError('');\n\n            await api.post('/api/reports', {\n                videoId,\n                reason: selectedReason,\n                description: description.trim() || undefined,\n            });\n\n            setSuccess(true);\n            // Close modal after 1.5 seconds\n            setTimeout(() => {\n                onHide();\n            }, 1500);\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setLoading(false);\n        }\n    };\n\n    const canSubmit = !loading && selectedReason.trim();\n\n    return (\n        <Modal show={show} onHide={onHide} centered>\n            <Modal.Header closeButton>\n                <Modal.Title as=\"h5\">{t('ui.report.title')}</Modal.Title>\n            </Modal.Header>\n\n            <Form onSubmit={handleSubmit}>\n                <Modal.Body className=\"pt-2\">\n                    {error && (\n                        <Alert variant=\"danger\" className=\"mb-3\">\n                            {error}\n                        </Alert>\n                    )}\n\n                    {success && (\n                        <Alert variant=\"success\" className=\"mb-3\">\n                            {t('ui.report.success')}\n                        </Alert>\n                    )}\n\n                    {!success && (\n                        <Stack gap={4}>\n                            {/* Report reasons section */}\n                            <div>\n                                <h6 className=\"mb-3\">\n                                    {t('ui.report.reason')}\n                                </h6>\n                                {loadingReasons ? (\n                                    <div className=\"text-muted\">\n                                        {t('common.loading')}\n                                    </div>\n                                ) : (\n                                    <Stack gap={2}>\n                                        {reasons.map(reason => (\n                                            <Form.Check\n                                                key={reason.value}\n                                                type=\"radio\"\n                                                name=\"reportReason\"\n                                                id={`reason-${reason.value}`}\n                                                label={reason.label}\n                                                value={reason.value}\n                                                checked={\n                                                    selectedReason ===\n                                                    reason.value\n                                                }\n                                                onChange={e =>\n                                                    setSelectedReason(\n                                                        e.target.value\n                                                    )\n                                                }\n                                            />\n                                        ))}\n                                    </Stack>\n                                )}\n\n                                {/* Community guidelines note */}\n                                <div className=\"text-muted small mt-3\">\n                                    {t('ui.report.communityNote')}\n                                </div>\n                            </div>\n\n                            {/* Additional description section */}\n                            <div>\n                                <h6 className=\"mb-3\">\n                                    {t('ui.report.description')}\n                                </h6>\n                                <Form.Control\n                                    as=\"textarea\"\n                                    rows={4}\n                                    value={description}\n                                    onChange={e =>\n                                        setDescription(e.target.value)\n                                    }\n                                    placeholder=\"\"\n                                    maxLength={500}\n                                    className=\"mb-2\"\n                                />\n                                <Form.Text className=\"text-muted\">\n                                    {t('ui.report.descriptionHelp')}\n                                </Form.Text>\n                            </div>\n                        </Stack>\n                    )}\n                </Modal.Body>\n\n                {!success && (\n                    <Modal.Footer>\n                        <Button\n                            variant=\"link\"\n                            className=\"text-decoration-none\"\n                            onClick={onHide}\n                            disabled={loading}\n                        >\n                            {t('common.cancel')}\n                        </Button>\n                        <Button\n                            variant=\"primary\"\n                            type=\"submit\"\n                            disabled={!canSubmit}\n                        >\n                            {loading\n                                ? t('common.loading')\n                                : t('ui.report.submit')}\n                        </Button>\n                    </Modal.Footer>\n                )}\n            </Form>\n        </Modal>\n    );\n}\n","import { useEffect, useState } from 'react';\nimport { Button, Alert, Badge, Dropdown } from 'react-bootstrap';\nimport { Video, VideoLikeResponse } from '@zentube/schema';\nimport {\n    FavoriteButton,\n    FollowButton,\n    VerifiedBadge,\n    ShareDropdown,\n    UserAvatar,\n} from '../../components';\nimport { ConfirmModal } from '../../components/ConfirmModal';\nimport { GiftModal } from '../../components/GiftModal';\nimport {\n    api,\n    appPath,\n    consumeNativeAuthResume,\n    getErrorMessage,\n    useEmbedded,\n} from '../../libs';\nimport { trackLike } from '../../libs/analytics';\nimport { showSuccess, showError } from '../../libs/toast';\nimport { useTranslation } from '../../libs/i18n';\nimport { authorProfileHref } from '../../libs/profileRoutes';\nimport { useVideoPermissions } from '../../libs/usePermissions';\nimport { ReportModal } from './reportmodal';\nimport { redirectToLogin } from '../../utils/redirect';\nimport './videoinfo.scss';\n\ninterface VideoInfoProps {\n    video: Video | null;\n    loading: boolean;\n    error: string;\n    currentUserId?: number;\n    onVideoUpdate?: (updatedVideo: Partial<Video>) => void;\n}\n\nexport function VideoInfo({\n    video,\n    loading,\n    error,\n    currentUserId,\n    onVideoUpdate,\n}: VideoInfoProps) {\n    const { t } = useTranslation();\n    const embedded = useEmbedded();\n    const [liking, setLiking] = useState(false);\n    const [showReportModal, setShowReportModal] = useState(false);\n    const [recommending, setRecommending] = useState(false);\n    const [deleting, setDeleting] = useState(false);\n    const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n    const [showGiftModal, setShowGiftModal] = useState(false);\n    const [shareUrl, setShareUrl] = useState('');\n\n    // Get video permissions\n    const { canEdit, canDelete, canRecommend } = useVideoPermissions(\n        video,\n        currentUserId\n    );\n\n    useEffect(() => {\n        setShareUrl(window.location.href);\n    }, []);\n\n    const handleLike = async () => {\n        if (!video || liking) return;\n\n        // If user is not logged in, redirect to login\n        if (!currentUserId) {\n            redirectToLogin(\n                { action: 'like', targetId: video.id },\n                window.location.pathname + window.location.search\n            );\n            return;\n        }\n\n        const action = video.isLikedByUser ? 'unlike' : 'like';\n\n        // Save original state for rollback\n        const originalLikedStatus = video.isLikedByUser;\n        const originalLikesCount = video.likes;\n\n        // Optimistically update UI immediately\n        const newLikedStatus = !video.isLikedByUser;\n        const newLikesCount = newLikedStatus\n            ? (video.likes || 0) + 1\n            : Math.max((video.likes || 0) - 1, 0);\n\n        onVideoUpdate?.({\n            likes: newLikesCount,\n            isLikedByUser: newLikedStatus,\n        });\n\n        try {\n            setLiking(true);\n            const response = await api.post<VideoLikeResponse>(\n                `/api/videos/${video.id}/like`,\n                { action }\n            );\n\n            if (response.data.success) {\n                // Update with actual server response\n                onVideoUpdate?.({\n                    likes: response.data.data.likes,\n                    isLikedByUser: response.data.data.isLikedByUser,\n                });\n\n                // 追踪点赞事件\n                trackLike({\n                    action: response.data.data.isLikedByUser\n                        ? 'like'\n                        : 'unlike',\n                    video_id: video.id,\n                    success: true,\n                    likes_count: response.data.data.likes,\n                });\n            } else {\n                // Rollback on server rejection\n                onVideoUpdate?.({\n                    likes: originalLikesCount,\n                    isLikedByUser: originalLikedStatus,\n                });\n                showError(t('ui.error.likeFailed'));\n\n                // 追踪失败事件\n                trackLike({\n                    action: originalLikedStatus ? 'unlike' : 'like',\n                    video_id: video.id,\n                    success: false,\n                    error: 'server_rejected',\n                });\n            }\n        } catch (err) {\n            // Rollback on error\n            onVideoUpdate?.({\n                likes: originalLikesCount,\n                isLikedByUser: originalLikedStatus,\n            });\n            const errorMessage = getErrorMessage(err);\n            console.error('Failed to toggle like:', errorMessage);\n            showError(errorMessage);\n\n            // 追踪失败事件\n            trackLike({\n                action: originalLikedStatus ? 'unlike' : 'like',\n                video_id: video.id,\n                success: false,\n                error: errorMessage,\n            });\n        } finally {\n            setLiking(false);\n        }\n    };\n\n    useEffect(() => {\n        if (\n            currentUserId &&\n            video?.id &&\n            consumeNativeAuthResume({ action: 'like', targetId: video.id })\n        ) {\n            if (!video.isLikedByUser) void handleLike();\n        }\n    }, [currentUserId, video?.id, video?.isLikedByUser]);\n\n    const handleRecommend = async () => {\n        if (!video || !currentUserId || recommending) return;\n\n        try {\n            setRecommending(true);\n            const response = await api.post(\n                `/api/videos/${video.id}/recommend`\n            );\n\n            if (response.data.success) {\n                // 根据操作类型显示不同的消息\n                const message =\n                    response.data.action === 'recommend'\n                        ? t('api.video.recommendedSuccessfully')\n                        : t('api.video.unrecommendedSuccessfully');\n                showSuccess(message);\n\n                // 更新视频的推荐状态\n                onVideoUpdate?.({\n                    isRecommended: response.data.isRecommended,\n                });\n            } else {\n                showError(response.data.message || t('api.error.server'));\n            }\n        } catch (err) {\n            console.error(\n                'Failed to toggle video recommendation:',\n                getErrorMessage(err)\n            );\n            showError(t('api.error.server'));\n        } finally {\n            setRecommending(false);\n        }\n    };\n\n    const handleReport = () => {\n        // If user is not logged in, redirect to login\n        if (!currentUserId) {\n            redirectToLogin(\n                { action: 'report', targetId: video?.id },\n                window.location.pathname + window.location.search\n            );\n            return;\n        }\n        setShowReportModal(true);\n    };\n\n    useEffect(() => {\n        if (\n            currentUserId &&\n            video?.id &&\n            consumeNativeAuthResume({ action: 'report', targetId: video.id })\n        ) {\n            setShowReportModal(true);\n        }\n    }, [currentUserId, video?.id]);\n\n    const handleDelete = () => {\n        setShowDeleteConfirm(true);\n    };\n\n    const authorDonationsEnabled = Boolean(\n        video?.author &&\n            (video.author as { donationsEnabled?: boolean }).donationsEnabled\n    );\n\n    const handleGift = () => {\n        if (!video) {\n            return;\n        }\n\n        // If user is not logged in, redirect to login\n        if (!currentUserId) {\n            const returnUrl = encodeURIComponent(\n                window.location.pathname + window.location.search\n            );\n            window.location.href = appPath(\n                `/auth/login?returnUrl=${returnUrl}`\n            );\n            return;\n        }\n\n        // 视频状态必须为\"已发布\"\n        if (video && video.status !== 'published') {\n            showError(t('ui.gift.messages.videoNotPublished'));\n            return;\n        }\n\n        if (!authorDonationsEnabled) {\n            showError(t('ui.gift.messages.donationDisabled'));\n            return;\n        }\n\n        if (Number(video.author.id) === Number(currentUserId)) {\n            showError(t('ui.gift.messages.cannotDonateToSelf'));\n            return;\n        }\n\n        setShowGiftModal(true);\n    };\n\n    const performDelete = async () => {\n        if (!video || !currentUserId || deleting) return;\n\n        try {\n            setDeleting(true);\n            const response = await api.delete(`/api/videos/${video.id}`);\n\n            if (response.data.success) {\n                showSuccess(t('api.video.deletedSuccessfully'));\n                // 延迟跳转，让用户看到成功提示\n                setTimeout(() => {\n                    window.location.href = appPath('/');\n                }, 1500);\n            } else {\n                showError(response.data.message || t('api.error.server'));\n            }\n        } catch (err) {\n            console.error('Failed to delete video:', getErrorMessage(err));\n            showError(t('api.error.server'));\n        } finally {\n            setDeleting(false);\n        }\n    };\n\n    if (loading) {\n        return (\n            <div className=\"placeholder-glow\">\n                <div\n                    className=\"placeholder col-8 mb-2\"\n                    style={{ height: '32px' }}\n                ></div>\n                <div\n                    className=\"placeholder col-6 mb-2\"\n                    style={{ height: '20px' }}\n                ></div>\n                <div\n                    className=\"placeholder col-12\"\n                    style={{ height: '80px' }}\n                ></div>\n            </div>\n        );\n    }\n\n    if (error || !video) {\n        return (\n            <Alert variant=\"warning\">\n                <small>{t('ui.error.videoInfoLoadError')}</small>\n            </Alert>\n        );\n    }\n\n    return (\n        <>\n            <h1 className=\"h4 mb-2\">{video.title}</h1>\n\n            {/* 作者信息和操作按钮区域 */}\n            <div className=\"mb-3\">\n                <div className=\"d-flex flex-column flex-md-row align-items-stretch align-items-md-center justify-content-md-between gap-3 gap-md-0\">\n                    {/* 作者信息区域 */}\n                    <div className=\"d-flex align-items-center justify-content-between justify-content-md-start w-100 w-md-auto\">\n                        <div className=\"d-flex align-items-center\">\n                            <div className=\"me-3 flex-shrink-0\">\n                                {video.author.username ? (\n                                    <a\n                                        href={authorProfileHref(\n                                            video.author.username\n                                        )}\n                                        className=\"text-decoration-none\"\n                                    >\n                                        <UserAvatar\n                                            username={video.author.username}\n                                            displayName={\n                                                video.author.displayName\n                                            }\n                                            avatarUrls={video.author.avatarUrls}\n                                            preferTeacherPortrait\n                                            size=\"medium\"\n                                        />\n                                    </a>\n                                ) : (\n                                    <UserAvatar\n                                        username={video.author.username}\n                                        displayName={video.author.displayName}\n                                        avatarUrls={video.author.avatarUrls}\n                                        preferTeacherPortrait\n                                        size=\"medium\"\n                                    />\n                                )}\n                            </div>\n                            <div className=\"flex-grow-1\">\n                                <div className=\"fw-semibold d-flex align-items-center\">\n                                    {video.author.username ? (\n                                        <a\n                                            href={authorProfileHref(\n                                                video.author.username\n                                            )}\n                                            className=\"text-decoration-none link-dark\"\n                                            style={{ cursor: 'pointer' }}\n                                        >\n                                            {video.author.displayName}\n                                        </a>\n                                    ) : (\n                                        video.author.displayName\n                                    )}\n                                    <VerifiedBadge\n                                        isVerified={video.author.isVerified}\n                                    />\n                                </div>\n                                <small className=\"text-muted\">\n                                    {video.author.followersCount !==\n                                        undefined &&\n                                        t(\n                                            'ui.user.followers',\n                                            {\n                                                count: video.author\n                                                    .followersCount,\n                                            },\n                                            {\n                                                count: video.author\n                                                    .followersCount,\n                                            }\n                                        )}\n                                </small>\n                            </div>\n                        </div>\n                        {/* 关注按钮 - 对所有用户显示（除了视频作者本人）*/}\n                        {video.author.id &&\n                            Number(currentUserId || 0) !==\n                                Number(video.author.id) && (\n                                <div className=\"ms-3 flex-shrink-0\">\n                                    <FollowButton userId={video.author.id} />\n                                </div>\n                            )}\n                    </div>\n\n                    {/* 操作按钮区域 */}\n                    <div className=\"flex-shrink-0\">\n                        <div className=\"d-flex gap-2 flex-wrap justify-content-start\">\n                            {video.status === 'published' && (\n                                <Button\n                                    variant=\"light\"\n                                    onClick={handleLike}\n                                    disabled={liking}\n                                    className=\"d-flex align-items-center\"\n                                >\n                                    <i\n                                        className={`me-1 bi ${\n                                            video.isLikedByUser\n                                                ? 'bi-hand-thumbs-up-fill'\n                                                : 'bi-hand-thumbs-up'\n                                        }`}\n                                    ></i>\n                                    {video.likes !== undefined &&\n                                    video.likes > 0\n                                        ? video.likes.toLocaleString()\n                                        : t('ui.button.like')}\n                                </Button>\n                            )}\n                            {/* 随喜 - 不显示自己的视频且创作者开启 */}\n                            {video &&\n                                video.status === 'published' &&\n                                authorDonationsEnabled &&\n                                !embedded && (\n                                    <Button\n                                        variant=\"light\"\n                                        className=\"d-flex align-items-center\"\n                                        onClick={handleGift}\n                                    >\n                                        <i className=\"bi bi-coin me-1\"></i>\n                                        {t('ui.button.thanks')}\n                                    </Button>\n                                )}\n                            <FavoriteButton\n                                videoId={video.id}\n                                currentUserId={currentUserId}\n                                className=\"d-flex align-items-center\"\n                            />\n                            <ShareDropdown\n                                shareUrl={shareUrl}\n                                title={video.title}\n                                description={`${video.title} - ${video.author.displayName}`}\n                                className=\"d-flex align-items-center\"\n                            />\n                            {/* Actions dropdown menu */}\n                            <Dropdown>\n                                <Dropdown.Toggle\n                                    variant=\"light\"\n                                    className=\"d-flex align-items-center dropdown-toggle-no-arrow h-100\"\n                                >\n                                    <i className=\"bi bi-three-dots-vertical\"></i>\n                                </Dropdown.Toggle>\n\n                                <Dropdown.Menu>\n                                    {/* Report - show for all users */}\n                                    <Dropdown.Item onClick={handleReport}>\n                                        {t('ui.button.report')}\n                                    </Dropdown.Item>\n\n                                    {/* Edit - only show for video owner and admins */}\n                                    {canEdit && video && (\n                                        <Dropdown.Item\n                                            href={appPath(\n                                                `/video/${video.id}/edit`\n                                            )}\n                                        >\n                                            {t('ui.button.edit')}\n                                        </Dropdown.Item>\n                                    )}\n\n                                    {/* Recommend - only show for admins */}\n                                    {canRecommend && (\n                                        <Dropdown.Item\n                                            onClick={handleRecommend}\n                                            disabled={recommending}\n                                        >\n                                            {recommending\n                                                ? t('common.loading')\n                                                : video.isRecommended\n                                                  ? t('ui.button.unrecommend')\n                                                  : t('ui.button.recommend')}\n                                        </Dropdown.Item>\n                                    )}\n\n                                    {/* Delete - only show for video owner and admins */}\n                                    {canDelete && (\n                                        <Dropdown.Item\n                                            onClick={handleDelete}\n                                            disabled={deleting}\n                                        >\n                                            {deleting\n                                                ? t('common.loading')\n                                                : t('ui.button.delete')}\n                                        </Dropdown.Item>\n                                    )}\n                                </Dropdown.Menu>\n                            </Dropdown>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            {/* Video Description */}\n            {video.description && (\n                <div className=\"video-description-section\">\n                    <div className=\"video-stats mb-2\">\n                        <span className=\"views-count\">\n                            {t(\n                                'ui.video.views',\n                                { count: video.views },\n                                { count: video.views }\n                            )}\n                        </span>\n                        <span className=\"stats-separator\">•</span>\n                        <span className=\"upload-date\">\n                            {t('ui.video.uploadedAt', {\n                                date: video.uploadDate,\n                            })}\n                        </span>\n                    </div>\n                    <div\n                        className=\"description-content\"\n                        style={{ whiteSpace: 'pre-wrap' }}\n                    >\n                        {video.description.replace(/\\\\n/g, '\\n')}\n                    </div>\n\n                    {/* Tags */}\n                    {video.tags && video.tags.length > 0 && (\n                        <div className=\"video-tags mt-3\">\n                            {video.tags.map((tag, index) => (\n                                <Badge\n                                    key={index}\n                                    bg=\"primary\"\n                                    className=\"tag-badge me-1 mb-1 rounded-pill\"\n                                    style={{ fontSize: '0.75rem' }}\n                                >\n                                    #{tag}\n                                </Badge>\n                            ))}\n                        </div>\n                    )}\n                </div>\n            )}\n\n            {/* Report Modal */}\n            {video && (\n                <ReportModal\n                    show={showReportModal}\n                    onHide={() => setShowReportModal(false)}\n                    videoId={video.id}\n                />\n            )}\n\n            {/* Delete Confirmation Modal */}\n            {video && (\n                <ConfirmModal\n                    show={showDeleteConfirm}\n                    title={t('ui.button.delete')}\n                    message={t('ui.video.confirmDelete', {\n                        title: video.title,\n                    })}\n                    confirmText={t('ui.button.delete')}\n                    cancelText={t('ui.button.cancel')}\n                    variant=\"danger\"\n                    onConfirm={performDelete}\n                    onCancel={() => setShowDeleteConfirm(false)}\n                />\n            )}\n\n            {/* Gift Modal */}\n            {video && (\n                <GiftModal\n                    show={showGiftModal}\n                    onHide={() => setShowGiftModal(false)}\n                    videoId={video.id}\n                    videoAuthorId={video.author.id}\n                />\n            )}\n        </>\n    );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { Video, VideoHistoryProgressResponse } from '@zentube/schema';\nimport type { SupportedLanguage } from '@zentube/i18n';\nimport { api, getErrorMessage } from '../../libs';\nimport { trackEvent } from '../../libs/analytics';\nimport { VideoPlayerContainer } from './videoplayercontainer';\nimport { VideoInfo } from './videoinfo';\n\nexport interface VideoWatchMainProps {\n    videoId: string;\n    currentUserId?: number;\n    currentUserRole?: string;\n    videoOwnerId?: number;\n    initialVideo?: Video | null;\n    language?: SupportedLanguage;\n}\n\nexport function VideoWatchMain({\n    videoId,\n    currentUserId,\n    initialVideo,\n}: VideoWatchMainProps) {\n    const [video, setVideo] = useState<Video | null>(initialVideo ?? null);\n    const [loading, setLoading] = useState(!initialVideo);\n    const [error, setError] = useState('');\n    const [resumeProgress, setResumeProgress] = useState<number | null>(() =>\n        currentUserId ? null : 0\n    );\n    const trackedContentVideoId = useRef<string | null>(null);\n\n    useEffect(() => {\n        if (!video) {\n            loadVideo();\n        }\n    }, [videoId]);\n\n    useEffect(() => {\n        let active = true;\n        if (!currentUserId) {\n            setResumeProgress(0);\n            return () => undefined;\n        }\n        setResumeProgress(null);\n\n        api.get<VideoHistoryProgressResponse>(\n            `/api/videos/history/${videoId}`\n        )\n            .then(response => {\n                const saved = response.data.data;\n                const progress = saved?.watchProgress || 0;\n                const duration = saved?.watchDuration || 0;\n                if (active) {\n                    setResumeProgress(\n                        progress > 0 && (!duration || progress < duration - 10)\n                            ? progress\n                            : 0\n                    );\n                }\n            })\n            .catch(() => {\n                if (active) setResumeProgress(0);\n            });\n\n        return () => {\n            active = false;\n        };\n    }, [currentUserId, videoId]);\n\n    const loadVideo = async () => {\n        try {\n            setLoading(true);\n            setError('');\n\n            const response = await api.get<Video>(`/api/videos/${videoId}`);\n            setVideo(response.data);\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setLoading(false);\n        }\n    };\n\n    const handleVideoUpdate = (updatedFields: Partial<Video>) => {\n        if (video) {\n            setVideo({ ...video, ...updatedFields });\n        }\n    };\n\n    useEffect(() => {\n        if (!video?.id || trackedContentVideoId.current === video.id) return;\n\n        trackedContentVideoId.current = video.id;\n        trackEvent('content_view', {\n            content_type: 'video',\n            video_id: video.id,\n            title: video.title,\n            author_id: video.author?.id,\n        });\n    }, [video]);\n\n    return (\n        <div>\n            {/* 视频播放器 */}\n            <div className=\"mb-4\">\n                <VideoPlayerContainer\n                    video={video}\n                    loading={loading || resumeProgress === null}\n                    error={error}\n                    currentUserId={currentUserId}\n                    initialProgress={resumeProgress ?? 0}\n                />\n            </div>\n\n            {/* 视频信息 */}\n            <div className=\"mb-3\">\n                <VideoInfo\n                    video={video}\n                    loading={loading}\n                    error={error}\n                    currentUserId={currentUserId}\n                    onVideoUpdate={handleVideoUpdate}\n                />\n            </div>\n        </div>\n    );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { Form, Button, Alert, Spinner } from 'react-bootstrap';\nimport { CommentCreateRequest } from '@zentube/schema';\nimport {\n    api,\n    consumeNativeAuthResume,\n    getErrorMessage,\n    useAuth,\n} from '../../../libs';\nimport { useTranslation } from '../../../libs/i18n';\nimport { redirectToLogin } from '../../../utils/redirect';\n\ninterface CommentFormProps {\n    videoId: string;\n    parentId?: string;\n    replyUserId?: number;\n    placeholder?: string;\n    onSubmit?: (comment: any) => void;\n    onCancel?: () => void;\n    className?: string;\n    autoFocus?: boolean;\n}\n\ninterface CommentFormData {\n    content: string;\n}\n\nexport function CommentForm({\n    videoId,\n    parentId,\n    replyUserId,\n    placeholder,\n    onSubmit,\n    onCancel,\n    className = '',\n    autoFocus = false,\n}: CommentFormProps) {\n    const { t } = useTranslation();\n    const { user: currentUser } = useAuth();\n    const [isSubmitting, setIsSubmitting] = useState(false);\n    const [error, setError] = useState('');\n    const [isFocused, setIsFocused] = useState(false);\n    const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n    const {\n        register,\n        handleSubmit,\n        reset,\n        watch,\n        formState: { errors, isValid },\n    } = useForm<CommentFormData>({\n        mode: 'onChange',\n    });\n\n    const content = watch('content', '');\n\n    useEffect(() => {\n        if (autoFocus && textareaRef.current) {\n            textareaRef.current.focus();\n        }\n    }, [autoFocus]);\n\n    useEffect(() => {\n        if (\n            currentUser &&\n            consumeNativeAuthResume({ action: 'comment', targetId: videoId })\n        ) {\n            textareaRef.current?.focus();\n        }\n    }, [currentUser, videoId]);\n\n    // Auto-resize textarea\n    useEffect(() => {\n        const textarea = textareaRef.current;\n        if (textarea) {\n            textarea.style.height = 'auto';\n            textarea.style.height =\n                Math.max(36, Math.min(120, textarea.scrollHeight)) + 'px';\n        }\n    }, [content]);\n\n    const onFormSubmit = async (data: CommentFormData) => {\n        // Check authentication first\n        if (!currentUser) {\n            redirectToLogin(\n                { action: 'comment', targetId: videoId },\n                window.location.pathname + window.location.search\n            );\n            return;\n        }\n\n        try {\n            setIsSubmitting(true);\n            setError('');\n\n            const payload: CommentCreateRequest = {\n                videoId,\n                content: data.content.trim(),\n                ...(parentId && { parentId }),\n                ...(replyUserId && { replyUserId }),\n            };\n\n            const response = await api.post('/api/comments', payload);\n\n            if (response.data.success) {\n                reset();\n                setIsFocused(false);\n                onSubmit?.(response.data.data);\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setIsSubmitting(false);\n        }\n    };\n\n    const handleCancel = () => {\n        reset();\n        setError('');\n        setIsFocused(false);\n        onCancel?.();\n    };\n\n    const handleFocus = () => {\n        setIsFocused(true);\n    };\n\n    const handleBlur = () => {\n        if (!content.trim()) {\n            setIsFocused(false);\n        }\n    };\n\n    const isReplyForm = Boolean(parentId);\n    const showActions = isFocused || content.trim() || isReplyForm;\n    const defaultPlaceholder = placeholder || t('ui.comment.addComment');\n\n    return (\n        <div className={`comment-form ${className}`}>\n            <Form\n                onSubmit={handleSubmit(onFormSubmit)}\n                className=\"position-relative\"\n            >\n                <Form.Group className=\"mb-0\">\n                    <Form.Control\n                        ref={textareaRef}\n                        as=\"textarea\"\n                        placeholder={defaultPlaceholder}\n                        rows={4}\n                        isInvalid={!!errors.content}\n                        {...register('content', {\n                            required: t('ui.comment.validation.required'),\n                            minLength: {\n                                value: 1,\n                                message: t('ui.comment.validation.notEmpty'),\n                            },\n                            maxLength: {\n                                value: 1000,\n                                message: t('ui.comment.validation.tooLong'),\n                            },\n                        })}\n                        disabled={isSubmitting}\n                        onFocus={handleFocus}\n                        onBlur={handleBlur}\n                    />\n                    <Form.Control.Feedback type=\"invalid\">\n                        {errors.content?.message}\n                    </Form.Control.Feedback>\n                </Form.Group>\n\n                {showActions && (\n                    <div\n                        className=\"d-flex justify-content-end align-items-center pt-3\"\n                        style={{\n                            animation: showActions\n                                ? 'fadeIn 0.2s ease-out'\n                                : 'none',\n                        }}\n                    >\n                        <div className=\"d-flex gap-2\">\n                            {onCancel && (\n                                <Button\n                                    variant=\"outline-secondary\"\n                                    onClick={handleCancel}\n                                    disabled={isSubmitting}\n                                >\n                                    {t('ui.button.cancel')}\n                                </Button>\n                            )}\n                            <Button\n                                type=\"submit\"\n                                variant=\"primary\"\n                                disabled={\n                                    !isValid || isSubmitting || !content.trim()\n                                }\n                            >\n                                {isSubmitting ? (\n                                    <>\n                                        <Spinner\n                                            as=\"span\"\n                                            animation=\"border\"\n                                            size=\"sm\"\n                                            role=\"status\"\n                                            aria-hidden=\"true\"\n                                            className=\"me-1\"\n                                        />\n                                        {parentId\n                                            ? t('ui.comment.replying')\n                                            : t('ui.comment.posting')}\n                                    </>\n                                ) : parentId ? (\n                                    t('ui.comment.reply')\n                                ) : (\n                                    t('ui.comment.addComment')\n                                )}\n                            </Button>\n                        </div>\n                    </div>\n                )}\n\n                {error && (\n                    <Alert\n                        variant=\"danger\"\n                        className=\"mt-3 py-2 px-3\"\n                        style={{ fontSize: '12px' }}\n                    >\n                        <i className=\"bi bi-exclamation-triangle me-2\"></i>\n                        {error}\n                    </Alert>\n                )}\n            </Form>\n\n            <style>{`\n                @keyframes fadeIn {\n                    from {\n                        opacity: 0;\n                        transform: translateY(-10px);\n                    }\n                    to {\n                        opacity: 1;\n                        transform: translateY(0);\n                    }\n                }\n\n                .form-control:focus {\n                    box-shadow: none !important;\n                    border-color: #0d6efd !important;\n                }\n\n                .resize-none {\n                    resize: none;\n                }\n            `}</style>\n        </div>\n    );\n}\n","import React, { useState, useRef, useEffect } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { Form, Button, Alert, Spinner } from 'react-bootstrap';\nimport { CommentUpdateRequest, Comment } from '@zentube/schema';\nimport { api, getErrorMessage } from '../../../libs';\nimport { useTranslation } from '../../../libs/i18n';\n\ninterface CommentEditFormProps {\n    comment: Comment;\n    onSubmit?: (updatedComment: Comment) => void;\n    onCancel?: () => void;\n}\n\ninterface CommentEditFormData {\n    content: string;\n}\n\nexport function CommentEditForm({\n    comment,\n    onSubmit,\n    onCancel,\n}: CommentEditFormProps) {\n    const { t } = useTranslation();\n    const [isSubmitting, setIsSubmitting] = useState(false);\n    const [error, setError] = useState('');\n    const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n    const {\n        register,\n        handleSubmit,\n        watch,\n        formState: { errors, isValid, isDirty },\n    } = useForm<CommentEditFormData>({\n        mode: 'onChange',\n        defaultValues: {\n            content: comment.content,\n        },\n    });\n\n    const content = watch('content', '');\n\n    useEffect(() => {\n        if (textareaRef.current) {\n            textareaRef.current.focus();\n            // Move cursor to end\n            const length = textareaRef.current.value.length;\n            textareaRef.current.setSelectionRange(length, length);\n        }\n    }, []);\n\n    // Auto-resize textarea\n    useEffect(() => {\n        const textarea = textareaRef.current;\n        if (textarea) {\n            textarea.style.height = 'auto';\n            textarea.style.height =\n                Math.max(72, Math.min(150, textarea.scrollHeight)) + 'px';\n        }\n    }, [content]);\n\n    const onFormSubmit = async (data: CommentEditFormData) => {\n        try {\n            setIsSubmitting(true);\n            setError('');\n\n            const payload: CommentUpdateRequest = {\n                content: data.content.trim(),\n            };\n\n            const response = await api.put(\n                `/api/comments/${comment.id}`,\n                payload\n            );\n\n            if (response.data.success) {\n                onSubmit?.(response.data.data);\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setIsSubmitting(false);\n        }\n    };\n\n    const handleCancel = () => {\n        setError('');\n        onCancel?.();\n    };\n\n    const hasChanges = isDirty && content.trim() !== comment.content;\n\n    return (\n        <div className=\"comment-edit-form\">\n            <Form\n                onSubmit={handleSubmit(onFormSubmit)}\n                className=\"position-relative\"\n            >\n                <Form.Group className=\"mb-3\">\n                    <Form.Control\n                        ref={textareaRef}\n                        as=\"textarea\"\n                        placeholder={t('ui.placeholder.editComment')}\n                        isInvalid={!!errors.content}\n                        rows={4}\n                        {...register('content', {\n                            required: 'Comment content is required',\n                            minLength: {\n                                value: 1,\n                                message: 'Comment must not be empty',\n                            },\n                            maxLength: {\n                                value: 1000,\n                                message:\n                                    'Comment must be less than 1000 characters',\n                            },\n                        })}\n                        disabled={isSubmitting}\n                    />\n                    <Form.Control.Feedback type=\"invalid\">\n                        {errors.content?.message}\n                    </Form.Control.Feedback>\n                </Form.Group>\n\n                {error && (\n                    <Alert\n                        variant=\"danger\"\n                        className=\"py-2 px-3 mb-3\"\n                        style={{ fontSize: '12px' }}\n                    >\n                        <i className=\"bi bi-exclamation-triangle me-2\"></i>\n                        {error}\n                    </Alert>\n                )}\n\n                <div className=\"d-flex gap-2 justify-content-end\">\n                    <Button\n                        variant=\"outline-secondary\"\n                        onClick={handleCancel}\n                        disabled={isSubmitting}\n                    >\n                        Cancel\n                    </Button>\n                    <Button\n                        type=\"submit\"\n                        disabled={!isValid || isSubmitting || !content.trim()}\n                    >\n                        {isSubmitting ? (\n                            <>\n                                <Spinner\n                                    as=\"span\"\n                                    animation=\"border\"\n                                    size=\"sm\"\n                                    role=\"status\"\n                                    aria-hidden=\"true\"\n                                    className=\"me-1\"\n                                />\n                                Saving...\n                            </>\n                        ) : hasChanges ? (\n                            <>\n                                <i className=\"bi bi-check-lg me-1\"></i>\n                                Save\n                            </>\n                        ) : (\n                            'Save'\n                        )}\n                    </Button>\n                </div>\n            </Form>\n\n            <style>{`\n                .resize-none {\n                    resize: none;\n                }\n\n                .form-control:focus {\n                    border-color: #0d6efd;\n                    box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);\n                }\n            `}</style>\n        </div>\n    );\n}\n","import { useState, useEffect } from 'react';\nimport { Comment } from '@zentube/schema';\nimport { api, getErrorMessage, useAuth } from '../../../libs';\nimport { useTranslation } from '../../../libs/i18n';\nimport { CommentForm } from './commentform';\nimport { CommentEditForm } from './commenteditform';\nimport { DonationCommentDisplay, UserAvatar } from '../../../components';\nimport { Button } from 'react-bootstrap';\nimport { formatTimeAgo } from '../../../libs/datetime';\nimport { redirectToLogin } from '../../../utils/redirect';\n\ninterface CommentItemProps {\n    comment: Comment;\n    videoId: string;\n    currentUserId?: number;\n    currentUserRole?: string;\n    videoOwnerId?: number;\n    onUpdate?: (updatedComment: Comment) => void;\n    onDelete?: (commentId: number | string) => void;\n    onReply?: (\n        newComment: Comment,\n        parentId?: string,\n        insertAfterId?: string\n    ) => void;\n    onLoadMoreReplies?: (parentId: string, newReplies: Comment[]) => void;\n    onRemoveReply?: (parentId: string, replyId: string) => void;\n    level?: number;\n    topLevelCommentId?: string; // 顶级评论的ID\n}\n\nexport function CommentItem({\n    comment,\n    videoId,\n    currentUserId,\n    currentUserRole,\n    videoOwnerId,\n    onUpdate,\n    onDelete,\n    onReply,\n    onLoadMoreReplies,\n    onRemoveReply,\n    level = 0,\n    topLevelCommentId,\n}: CommentItemProps) {\n    const { t } = useTranslation();\n    const { user: currentUser } = useAuth();\n    const [isEditing, setIsEditing] = useState(false);\n    const [isReplying, setIsReplying] = useState(false);\n    const [isLiking, setIsLiking] = useState(false);\n    const [isDeleting, setIsDeleting] = useState(false);\n    const [loadingMoreReplies, setLoadingMoreReplies] = useState(false);\n    const [isFlagging, setIsFlagging] = useState(false);\n    const [isHovered, setIsHovered] = useState(false);\n\n    // Local state for comment content to handle updates\n    const [currentComment, setCurrentComment] = useState(comment);\n\n    const [likes, setLikes] = useState(comment.likes || 0);\n    const [dislikes, setDislikes] = useState(comment.dislikes || 0);\n    const [isLikedByUser, setIsLikedByUser] = useState(\n        comment.isLikedByUser || false\n    );\n    const [isDislikedByUser, setIsDislikedByUser] = useState(\n        comment.isDislikedByUser || false\n    );\n    const [isDisliking, setIsDisliking] = useState(false);\n    const [error, setError] = useState('');\n\n    const canEdit = Number(currentUserId) === Number(currentComment.userId);\n\n    const canDelete =\n        currentUserRole === 'admin' || // 管理员可以删除任何评论\n        Number(currentUserId) === Number(currentComment.userId) || // 用户可以删除自己的评论\n        Number(currentUserId) === Number(videoOwnerId); // 视频作者可以删除视频上的评论\n\n    const canFlag = currentUserId && currentComment.status === 'active';\n\n    // Sync with prop changes\n    useEffect(() => {\n        setCurrentComment(comment);\n        setLikes(comment.likes || 0);\n        setDislikes(comment.dislikes || 0);\n        setIsLikedByUser(comment.isLikedByUser || false);\n        setIsDislikedByUser(comment.isDislikedByUser || false);\n    }, [comment]);\n\n    const handleLike = async () => {\n        // Check authentication first\n        if (!currentUserId) {\n            redirectToLogin();\n            return;\n        }\n\n        if (isLiking) return;\n\n        // Save original state for rollback\n        const originalLiked = isLikedByUser;\n        const originalDisliked = isDislikedByUser;\n        const originalLikes = likes;\n        const originalDislikes = dislikes;\n\n        // Optimistically update UI immediately\n        const newIsLiked = !isLikedByUser;\n        const newIsDisliked = newIsLiked ? false : isDislikedByUser; // If liking, remove dislike\n        const newLikes = newIsLiked\n            ? originalLikes + 1\n            : Math.max(originalLikes - 1, 0);\n        const newDislikes =\n            newIsLiked && originalDisliked\n                ? Math.max(originalDislikes - 1, 0)\n                : originalDislikes;\n\n        setIsLikedByUser(newIsLiked);\n        setIsDislikedByUser(newIsDisliked);\n        setLikes(newLikes);\n        setDislikes(newDislikes);\n\n        try {\n            setIsLiking(true);\n            setError('');\n\n            const action = originalLiked ? 'unlike' : 'like';\n\n            const response = await api.post(\n                `/api/comments/${currentComment.id}/like`,\n                { action }\n            );\n\n            if (response.data.success) {\n                const {\n                    likes: serverLikes,\n                    dislikes: serverDislikes,\n                    isLikedByUser: serverIsLiked,\n                    isDislikedByUser: serverIsDisliked,\n                } = response.data.data;\n                setLikes(serverLikes || 0);\n                setDislikes(serverDislikes || 0);\n                setIsLikedByUser(serverIsLiked || false);\n                setIsDislikedByUser(serverIsDisliked || false);\n            } else {\n                // Rollback on server rejection\n                setIsLikedByUser(originalLiked);\n                setIsDislikedByUser(originalDisliked);\n                setLikes(originalLikes);\n                setDislikes(originalDislikes);\n            }\n        } catch (err) {\n            // Rollback on error\n            setIsLikedByUser(originalLiked);\n            setIsDislikedByUser(originalDisliked);\n            setLikes(originalLikes);\n            setDislikes(originalDislikes);\n            setError(getErrorMessage(err));\n        } finally {\n            setIsLiking(false);\n        }\n    };\n\n    const handleDislike = async () => {\n        // Check authentication first\n        if (!currentUserId) {\n            redirectToLogin();\n            return;\n        }\n\n        if (isDisliking) return;\n\n        // Save original state for rollback\n        const originalLiked = isLikedByUser;\n        const originalDisliked = isDislikedByUser;\n        const originalLikes = likes;\n        const originalDislikes = dislikes;\n\n        // Optimistically update UI immediately\n        const newIsDisliked = !isDislikedByUser;\n        const newIsLiked = newIsDisliked ? false : isLikedByUser; // If disliking, remove like\n        const newDislikes = newIsDisliked\n            ? originalDislikes + 1\n            : Math.max(originalDislikes - 1, 0);\n        const newLikes =\n            newIsDisliked && originalLiked\n                ? Math.max(originalLikes - 1, 0)\n                : originalLikes;\n\n        setIsLikedByUser(newIsLiked);\n        setIsDislikedByUser(newIsDisliked);\n        setLikes(newLikes);\n        setDislikes(newDislikes);\n\n        try {\n            setIsDisliking(true);\n            setError('');\n\n            const action = originalDisliked ? 'undislike' : 'dislike';\n\n            const response = await api.post(\n                `/api/comments/${currentComment.id}/dislike`,\n                { action }\n            );\n\n            if (response.data.success) {\n                const {\n                    likes: serverLikes,\n                    dislikes: serverDislikes,\n                    isLikedByUser: serverIsLiked,\n                    isDislikedByUser: serverIsDisliked,\n                } = response.data.data;\n                setLikes(serverLikes || 0);\n                setDislikes(serverDislikes || 0);\n                setIsLikedByUser(serverIsLiked || false);\n                setIsDislikedByUser(serverIsDisliked || false);\n            } else {\n                // Rollback on server rejection\n                setIsLikedByUser(originalLiked);\n                setIsDislikedByUser(originalDisliked);\n                setLikes(originalLikes);\n                setDislikes(originalDislikes);\n            }\n        } catch (err) {\n            // Rollback on error\n            setIsLikedByUser(originalLiked);\n            setIsDislikedByUser(originalDisliked);\n            setLikes(originalLikes);\n            setDislikes(originalDislikes);\n            setError(getErrorMessage(err));\n        } finally {\n            setIsDisliking(false);\n        }\n    };\n\n    // 加载更多第一级评论的回复\n    const loadMoreReplies = async () => {\n        if (loadingMoreReplies || level !== 0) return;\n\n        try {\n            setLoadingMoreReplies(true);\n            setError('');\n\n            // 直接调用接口一次性加载所有剩余回复\n            if (\n                currentComment.replies > (currentComment.children || []).length\n            ) {\n                const response = await api.get(\n                    `/api/comments/${currentComment.id}/replies`\n                );\n\n                if (response.data) {\n                    const newReplies = response.data;\n                    // 通知父组件加载更多回复\n                    onLoadMoreReplies?.(currentComment.id, newReplies);\n                }\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setLoadingMoreReplies(false);\n        }\n    };\n\n    const handleFlag = async () => {\n        if (!canFlag || isFlagging) return;\n\n        try {\n            setIsFlagging(true);\n            setError('');\n\n            const response = await api.post(\n                `/api/comments/${currentComment.id}/flag`\n            );\n\n            if (response.data.success) {\n                // Handle successful flagging (e.g., show a message or update state)\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setIsFlagging(false);\n        }\n    };\n\n    const handleDelete = async () => {\n        if (!canDelete || isDeleting) return;\n\n        if (!confirm(t('ui.comment.confirmDelete'))) {\n            return;\n        }\n\n        try {\n            setIsDeleting(true);\n            setError('');\n\n            await api.delete(`/api/comments/${currentComment.id}`);\n\n            // 如果是顶级评论，通知父组件删除\n            if (level === 0) {\n                onDelete?.(currentComment.id);\n            } else {\n                // 如果是子级评论，需要找到父评论ID并通知父组件删除\n                // 这里需要从父组件传递父评论ID，暂时先通知父组件删除\n                onDelete?.(currentComment.id);\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n            setIsDeleting(false);\n        }\n    };\n\n    const handleEditSubmit = (updatedComment: Comment) => {\n        setIsEditing(false);\n        setCurrentComment(updatedComment); // Update local state\n        onUpdate?.(updatedComment);\n    };\n\n    const handleReplySubmit = (newComment: Comment) => {\n        setIsReplying(false);\n\n        // Use local user information to set the author field for replies\n        const commentWithLocalUser = {\n            ...newComment,\n            author:\n                currentUser?.displayName ||\n                currentUser?.username ||\n                'Anonymous',\n            authorAvatarUrls: currentUser?.avatarUrls,\n            // 从前端数据结构中获取replyToAuthor\n            replyToAuthor: currentComment.author,\n        };\n\n        // 通知父组件有新回复，传递正确的父评论ID和插入位置\n        // 如果是顶级评论，使用自己的ID；如果是子级评论，使用顶级评论的ID\n        const parentId = level === 0 ? currentComment.id : topLevelCommentId;\n        // 传递被回复评论的ID，用于确定插入位置\n        // 回复顶级评论时，插入到最前面（insertAfterId = undefined 表示插入到开头）\n        const insertAfterId = level === 0 ? undefined : currentComment.id;\n\n        onReply?.(commentWithLocalUser, parentId, insertAfterId);\n    };\n\n    const formatDate = (dateString: string) => {\n        // 使用统一的 formatTimeAgo 函数，它正确处理了 UTC 时间和用户时区\n        return formatTimeAgo(dateString);\n    };\n\n    if (currentComment.status === 'deleted') {\n        return (\n            <div\n                className=\"comment-item deleted mb-3\"\n                style={{\n                    marginLeft:\n                        level > 0 ? `${Math.min(level * 24, 72)}px` : '0',\n                    paddingLeft: '12px',\n                    borderLeft: level > 0 ? '2px solid #e9ecef' : 'none',\n                }}\n            >\n                <div className=\"text-muted fst-italic py-2\">\n                    <small>\n                        <i className=\"bi bi-trash me-2\"></i>\n                        {t('ui.comment.deletedMessage')}\n                    </small>\n                </div>\n            </div>\n        );\n    }\n\n    return (\n        <div id={`comment-${currentComment.id}`} className=\"comment-item mb-4\">\n            <div className=\"comment-main-area\">\n                <div\n                    onMouseEnter={() => setIsHovered(true)}\n                    onMouseLeave={() => setIsHovered(false)}\n                >\n                    <div className=\"d-flex mb-2 align-items-center\">\n                        <div className=\"position-relative me-2 flex-shrink-0\">\n                            <UserAvatar\n                                displayName={currentComment.author}\n                                avatarUrls={currentComment.authorAvatarUrls}\n                                size={32}\n                                className=\"rounded-circle\"\n                            />\n                        </div>\n                        <div>\n                            <small className=\"text-primary\">\n                                {currentComment.author}\n                            </small>\n                            {likes > 0 && (\n                                <small className=\"text-secondary ms-1 fw-bold\">\n                                    {likes}\n                                </small>\n                            )}\n                            <span className=\"text-muted mx-1\">•</span>\n                            <small className=\"text-muted\">\n                                {formatDate(currentComment.createdAt)}\n                            </small>\n                            <DonationCommentDisplay comment={currentComment} />\n                            {currentComment.isPinned && (\n                                <small className=\"badge bg-warning text-dark\">\n                                    <i className=\"bi bi-pin-fill me-1\"></i>\n                                    {t('ui.comment.pinned')}\n                                </small>\n                            )}\n                        </div>\n                    </div>\n\n                    <div className=\"flex-grow-1 min-w-0\">\n                        <div>\n                            {isEditing ? (\n                                <div className=\"mt-1\">\n                                    <CommentEditForm\n                                        comment={currentComment}\n                                        onSubmit={handleEditSubmit}\n                                        onCancel={() => setIsEditing(false)}\n                                    />\n                                </div>\n                            ) : (\n                                <>\n                                    <div\n                                        className=\"comment-content mb-2\"\n                                        style={{\n                                            whiteSpace: 'pre-wrap',\n                                        }}\n                                    >\n                                        {/* 评论内容显示 */}\n                                        {(() => {\n                                            const shouldShowAt =\n                                                currentComment.level === 3 &&\n                                                currentComment.replyToAuthor;\n\n                                            return shouldShowAt ? (\n                                                <>\n                                                    @\n                                                    <span className=\"text-primary\">\n                                                        {\n                                                            currentComment.replyToAuthor\n                                                        }\n                                                    </span>{' '}\n                                                    {currentComment.content}\n                                                </>\n                                            ) : (\n                                                currentComment.content\n                                            );\n                                        })()}\n                                    </div>\n\n                                    <div className=\"d-flex align-items-center justify-content-between\">\n                                        <div className=\"d-flex align-items-center\">\n                                            <Button\n                                                variant=\"link\"\n                                                className=\"p-0 text-small link-secondary text-decoration-none me-1\"\n                                                onClick={handleLike}\n                                                disabled={isLiking}\n                                            >\n                                                <i\n                                                    className={`bi ${isLikedByUser ? 'bi-hand-thumbs-up-fill' : 'bi-hand-thumbs-up'} me-1`}\n                                                ></i>\n                                                {likes > 0\n                                                    ? likes\n                                                    : t('ui.button.like')}\n                                            </Button>\n\n                                            <Button\n                                                variant=\"link\"\n                                                className=\"p-0 text-small link-secondary text-decoration-none\"\n                                                onClick={handleDislike}\n                                                disabled={isDisliking}\n                                            >\n                                                <i\n                                                    className={`bi ${isDislikedByUser ? 'bi-hand-thumbs-down-fill' : 'bi-hand-thumbs-down'} ${dislikes > 0 ? 'me-1' : ''}`}\n                                                ></i>\n                                                {dislikes > 0 ? dislikes : ''}\n                                            </Button>\n                                            {level < 2 && (\n                                                <Button\n                                                    variant=\"link\"\n                                                    className=\"text-decoration-none text-small p-0 link-secondary ms-3\"\n                                                    onClick={() => {\n                                                        // Check authentication first\n                                                        if (!currentUserId) {\n                                                            redirectToLogin();\n                                                            return;\n                                                        }\n                                                        setIsReplying(\n                                                            !isReplying\n                                                        );\n                                                    }}\n                                                >\n                                                    {t('ui.comment.reply')}\n                                                </Button>\n                                            )}\n                                        </div>\n\n                                        {(canEdit || canDelete || canFlag) &&\n                                            isHovered && (\n                                                <div className=\"d-flex gap-3\">\n                                                    {canEdit && (\n                                                        <Button\n                                                            variant=\"link\"\n                                                            className=\"text-decoration-none text-small p-0 link-secondary\"\n                                                            onClick={() =>\n                                                                setIsEditing(\n                                                                    true\n                                                                )\n                                                            }\n                                                        >\n                                                            {t(\n                                                                'ui.comment.edit'\n                                                            )}\n                                                        </Button>\n                                                    )}\n                                                    {canDelete && (\n                                                        <Button\n                                                            variant=\"link\"\n                                                            className=\"text-decoration-none text-small p-0 link-secondary\"\n                                                            onClick={\n                                                                handleDelete\n                                                            }\n                                                            disabled={\n                                                                isDeleting\n                                                            }\n                                                        >\n                                                            {isDeleting\n                                                                ? t(\n                                                                      'ui.comment.deleting'\n                                                                  )\n                                                                : t(\n                                                                      'ui.comment.delete'\n                                                                  )}\n                                                        </Button>\n                                                    )}\n                                                    {/* flag */}\n                                                    {canFlag && (\n                                                        <Button\n                                                            variant=\"link\"\n                                                            className=\"text-decoration-none text-small p-0 link-secondary\"\n                                                            onClick={handleFlag}\n                                                            disabled={\n                                                                isFlagging\n                                                            }\n                                                        >\n                                                            {isFlagging\n                                                                ? t(\n                                                                      'ui.comment.flagging'\n                                                                  )\n                                                                : t(\n                                                                      'ui.comment.flag'\n                                                                  )}\n                                                        </Button>\n                                                    )}\n                                                </div>\n                                            )}\n                                    </div>\n                                </>\n                            )}\n                        </div>\n\n                        {error && (\n                            <div\n                                className=\"alert alert-danger py-2 px-3 mt-3\"\n                                style={{ fontSize: '12px' }}\n                            >\n                                <i className=\"bi bi-exclamation-triangle me-2\"></i>\n                                {error}\n                            </div>\n                        )}\n\n                        {isReplying && (\n                            <div className=\"mt-3\">\n                                <div className=\"d-flex\">\n                                    <div className=\"me-3 flex-shrink-0\">\n                                        <div\n                                            className=\"bg-primary rounded-circle d-flex align-items-center justify-content-center\"\n                                            style={{\n                                                width: '24px',\n                                                height: '24px',\n                                                background: `hsl(${((currentUserId?.toString() || '').charCodeAt(0) * 7) % 360}, 65%, 50%)`,\n                                            }}\n                                        >\n                                            <span\n                                                className=\"text-white fw-semibold\"\n                                                style={{ fontSize: '10px' }}\n                                            >\n                                                U\n                                            </span>\n                                        </div>\n                                    </div>\n                                    <div className=\"flex-grow-1\">\n                                        <CommentForm\n                                            videoId={videoId}\n                                            parentId={currentComment.id}\n                                            replyUserId={currentComment.userId}\n                                            placeholder={\n                                                currentComment.level === 2\n                                                    ? `Reply to @${currentComment.author}...`\n                                                    : `Reply to ${currentComment.author}...`\n                                            }\n                                            onSubmit={handleReplySubmit}\n                                            onCancel={() =>\n                                                setIsReplying(false)\n                                            }\n                                            className=\"reply-form\"\n                                        />\n                                    </div>\n                                </div>\n                            </div>\n                        )}\n                    </div>\n                </div>\n\n                {/* 显示子级评论（包括level=2和level=3） */}\n                {level === 0 && (currentComment.children || []).length > 0 && (\n                    <div\n                        className=\"mt-3 border-start ps-4\"\n                        onMouseEnter={e => e.stopPropagation()}\n                        onMouseLeave={e => e.stopPropagation()}\n                    >\n                        {(currentComment.children || []).map(childComment => (\n                            <CommentItem\n                                key={childComment.id}\n                                comment={childComment}\n                                videoId={videoId}\n                                currentUserId={currentUserId}\n                                currentUserRole={currentUserRole}\n                                videoOwnerId={videoOwnerId}\n                                onUpdate={onUpdate}\n                                onDelete={onDelete}\n                                onReply={onReply}\n                                onLoadMoreReplies={onLoadMoreReplies}\n                                onRemoveReply={onRemoveReply}\n                                level={1}\n                                topLevelCommentId={currentComment.id} // 传递顶级评论ID\n                            />\n                        ))}\n\n                        {/* 第一级评论的\"加载更多回复\"按钮 */}\n                        {currentComment.replies >\n                            (currentComment.children || []).length && (\n                            <Button\n                                variant=\"link\"\n                                size=\"sm\"\n                                className=\"text-decoration-none p-0 text-primary\"\n                                onClick={loadMoreReplies}\n                                disabled={loadingMoreReplies}\n                            >\n                                {loadingMoreReplies ? (\n                                    <>\n                                        <span\n                                            className=\"spinner-border spinner-border-sm me-2\"\n                                            role=\"status\"\n                                            aria-hidden=\"true\"\n                                        ></span>\n                                        {t('ui.common.loading')}\n                                    </>\n                                ) : (\n                                    <>\n                                        <i className=\"bi bi-chevron-down me-1\"></i>\n                                        {t('ui.comment.moreComments', {\n                                            count:\n                                                currentComment.replies -\n                                                (currentComment.children || [])\n                                                    .length,\n                                        })}\n                                    </>\n                                )}\n                            </Button>\n                        )}\n                    </div>\n                )}\n            </div>\n        </div>\n    );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { Button, Alert, Spinner, ButtonGroup } from 'react-bootstrap';\nimport { Comment, CommentListResponse } from '@zentube/schema';\nimport { api, getErrorMessage, useAuth } from '../../libs';\nimport { useTranslation } from '../../libs/i18n';\nimport { redirectToLogin } from '../../utils/redirect';\nimport { CommentForm, CommentItem } from './comment';\n\ninterface VideoCommentsProps {\n    videoId: string;\n    currentUserId?: number;\n    currentUserRole?: string;\n    videoOwnerId?: number;\n    collapsible?: boolean;\n}\n\ninterface CommentsSortOption {\n    value: 'newest' | 'oldest' | 'likes';\n    label: string;\n}\n\n// 动态生成排序选项，支持国际化\n\nexport function VideoComments({\n    videoId,\n    currentUserId,\n    currentUserRole,\n    videoOwnerId,\n    collapsible = false,\n}: VideoCommentsProps) {\n    const { t } = useTranslation();\n    const { user: currentUser } = useAuth();\n    const [comments, setComments] = useState<Comment[]>([]);\n    const [loading, setLoading] = useState(true);\n    const [loadingMore, setLoadingMore] = useState(false);\n    const [error, setError] = useState('');\n    const [total, setTotal] = useState(0);\n    const [page, setPage] = useState(1);\n    const [hasMore, setHasMore] = useState(false);\n    const [sortBy, setSortBy] = useState<'newest' | 'oldest' | 'likes'>(\n        'likes'\n    );\n    const [isExpanded, setIsExpanded] = useState(false);\n\n    // 动态生成排序选项\n    const getSortOptions = (): CommentsSortOption[] => [\n        { value: 'likes', label: t('ui.comment.score') },\n        { value: 'newest', label: t('ui.comment.newest') },\n        {\n            value: 'oldest',\n            label: t('ui.comment.oldest'),\n        },\n    ];\n\n    const loadComments = useCallback(\n        async (\n            pageNum = 1,\n            append = false,\n            sortOption = sortBy,\n            topCommentId?: string\n        ) => {\n            try {\n                if (!append) {\n                    setLoading(true);\n                } else {\n                    setLoadingMore(true);\n                }\n                setError('');\n\n                const sortConfig = (() => {\n                    switch (sortOption) {\n                        case 'likes':\n                            return { sortBy: 'likes', sortOrder: 'desc' };\n                        case 'newest':\n                            return { sortBy: 'createdAt', sortOrder: 'desc' };\n                        case 'oldest':\n                            return { sortBy: 'createdAt', sortOrder: 'asc' };\n                        default:\n                            return { sortBy: 'createdAt', sortOrder: 'desc' };\n                    }\n                })();\n\n                // 检查topComment来源：URL参数或函数参数\n                const urlParams = new URLSearchParams(window.location.search);\n                const urlTopComment = urlParams.get('topComment');\n                const topComment = topCommentId || urlTopComment;\n\n                // 只有在初始加载（pageNum === 1 && !append）时才传递topComment\n                const shouldIncludeTopComment =\n                    pageNum === 1 && !append && topComment;\n\n                const response = await api.get<CommentListResponse>(\n                    `/api/videos/${videoId}/comments`,\n                    {\n                        params: {\n                            page: pageNum,\n                            pageSize: 30, // 顶层评论默认显示30条\n                            ...sortConfig,\n                            ...(shouldIncludeTopComment && { topComment }), // 只在初始加载时传递\n                        },\n                    }\n                );\n\n                if (response.data) {\n                    const {\n                        comments: newComments,\n                        total: newTotal,\n                        hasMore: newHasMore,\n                        page: newPage,\n                    } = response.data;\n\n                    if (append) {\n                        setComments(prev => {\n                            // 检查新加载的评论中是否包含锚点评论\n                            const hash = window.location.hash;\n                            const topCommentId = hash.startsWith('#comment-')\n                                ? hash.replace('#comment-', '')\n                                : null;\n\n                            if (topCommentId) {\n                                // 检查新评论中是否包含锚点评论\n                                const hasTopCommentInNew = newComments.some(\n                                    c => c.id === topCommentId\n                                );\n\n                                if (hasTopCommentInNew) {\n                                    // 如果新评论中包含锚点评论，移除列表顶部的锚点评论（第一条）\n                                    const filteredPrev = prev.filter(\n                                        c => c.id !== topCommentId\n                                    );\n                                    return [...filteredPrev, ...newComments];\n                                }\n                            }\n\n                            // 正常追加评论\n                            return [...prev, ...newComments];\n                        });\n                    } else {\n                        setComments(newComments);\n                    }\n\n                    setTotal(newTotal);\n                    setPage(newPage);\n                    setHasMore(newHasMore);\n                }\n            } catch (err) {\n                setError(getErrorMessage(err));\n            } finally {\n                setLoading(false);\n                setLoadingMore(false);\n            }\n        },\n        [videoId, sortBy]\n    );\n\n    // 处理初始加载和锚点跳转\n    useEffect(() => {\n        // 获取锚点中的评论ID\n        const hash = window.location.hash;\n        const topCommentId = hash.startsWith('#comment-')\n            ? hash.replace('#comment-', '')\n            : undefined;\n\n        // 首次加载时传递锚点参数\n        if (topCommentId) {\n            loadComments(1, false, sortBy, topCommentId);\n        } else {\n            loadComments(1, false, sortBy);\n        }\n\n        const handleHashChange = () => {\n            const newHash = window.location.hash;\n            if (newHash.startsWith('#comment-')) {\n                const newTopCommentId = newHash.replace('#comment-', '');\n                // 检查评论是否已加载\n                const existingComment = comments.find(\n                    c => c.id === newTopCommentId\n                );\n                if (!existingComment) {\n                    // 如果评论未加载，重新加载评论列表并传递topCommentId\n                    loadComments(1, false, sortBy, newTopCommentId);\n                } else {\n                    // 如果评论已加载，直接滚动\n                    scrollToComment(newTopCommentId);\n                }\n            }\n        };\n\n        // 监听hash变化\n        window.addEventListener('hashchange', handleHashChange);\n        return () => window.removeEventListener('hashchange', handleHashChange);\n    }, [loadComments, sortBy]);\n\n    // 监听随喜完成事件，自动刷新评论列表\n    useEffect(() => {\n        const handleDonationCompleted = (event: Event) => {\n            const customEvent = event as CustomEvent<{\n                videoId?: string;\n                amount?: number;\n                message?: string;\n                timestamp: number;\n            }>;\n            if (customEvent.detail?.videoId !== videoId) {\n                return;\n            }\n            loadComments(1, false, sortBy);\n        };\n\n        window.addEventListener(\n            'donation:completed',\n            handleDonationCompleted as EventListener\n        );\n        return () =>\n            window.removeEventListener(\n                'donation:completed',\n                handleDonationCompleted as EventListener\n            );\n    }, [videoId, loadComments, sortBy]);\n\n    // 处理数据加载完成后的滚动\n    useEffect(() => {\n        const hash = window.location.hash;\n        if (hash.startsWith('#comment-')) {\n            const topCommentId = hash.replace('#comment-', '');\n            // 检查目标评论是否已加载\n            const targetComment = comments.find(c => c.id === topCommentId);\n            if (targetComment) {\n                // 延迟执行滚动，确保DOM已更新\n                setTimeout(() => {\n                    scrollToComment(topCommentId);\n                }, 100);\n            }\n        }\n    }, [comments]); // 依赖comments，当评论数据更新时触发\n\n    // 滚动到指定评论\n    const scrollToComment = (commentId: string) => {\n        const element = document.getElementById(`comment-${commentId}`);\n        if (element) {\n            element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n            // 添加高亮效果\n            element.style.backgroundColor = '#fff3cd';\n            setTimeout(() => {\n                element.style.backgroundColor = '';\n            }, 3000);\n        }\n    };\n\n    // 统一的数据更新函数\n    const updateCommentInTree = useCallback(\n        (commentId: string, updater: (comment: Comment) => Comment) => {\n            setComments(prev =>\n                prev.map(comment => {\n                    if (comment.id === commentId) {\n                        return updater(comment);\n                    }\n                    // 递归更新子评论\n                    if (comment.children && comment.children.length > 0) {\n                        const updatedChildren = comment.children.map(child =>\n                            child.id === commentId ? updater(child) : child\n                        );\n                        return {\n                            ...comment,\n                            children: updatedChildren,\n                        };\n                    }\n                    return comment;\n                })\n            );\n        },\n        []\n    );\n\n    // 添加回复到指定评论\n    const addReplyToComment = useCallback(\n        (parentId: string, newReply: Comment, insertAfterId?: string) => {\n            const commentWithLocalUser = {\n                ...newReply,\n                author:\n                    currentUser?.displayName ||\n                    currentUser?.username ||\n                    'Anonymous',\n                authorAvatarUrls: currentUser?.avatarUrls,\n            };\n\n            updateCommentInTree(parentId, comment => {\n                const children = comment.children || [];\n                let newChildren: Comment[];\n\n                if (insertAfterId === null) {\n                    // 插入到最前面（回复顶级评论）\n                    newChildren = [commentWithLocalUser, ...children];\n                } else if (insertAfterId) {\n                    // 找到被回复评论的位置，在其后插入\n                    const insertIndex = children.findIndex(\n                        child => child.id === insertAfterId\n                    );\n                    if (insertIndex !== -1) {\n                        newChildren = [\n                            ...children.slice(0, insertIndex + 1),\n                            commentWithLocalUser,\n                            ...children.slice(insertIndex + 1),\n                        ];\n                    } else {\n                        // 如果找不到被回复的评论，添加到末尾\n                        newChildren = [...children, commentWithLocalUser];\n                    }\n                } else {\n                    // 没有指定插入位置，添加到末尾\n                    newChildren = [...children, commentWithLocalUser];\n                }\n\n                return {\n                    ...comment,\n                    children: newChildren,\n                    replies: (comment.replies || 0) + 1,\n                };\n            });\n        },\n        [currentUser, updateCommentInTree]\n    );\n\n    // 从指定评论中删除回复\n    const removeReplyFromComment = useCallback(\n        (parentId: string, replyId: string) => {\n            updateCommentInTree(parentId, comment => {\n                const updatedChildren = (comment.children || []).filter(\n                    child => child.id !== replyId\n                );\n                return {\n                    ...comment,\n                    children: updatedChildren,\n                    replies: Math.max((comment.replies || 0) - 1, 0),\n                };\n            });\n        },\n        [updateCommentInTree]\n    );\n\n    // 加载更多回复到指定评论\n    const loadMoreRepliesToComment = useCallback(\n        (parentId: string, newReplies: Comment[]) => {\n            updateCommentInTree(parentId, comment => {\n                // 过滤掉已存在的回复，避免重复\n                const existingIds = new Set(\n                    (comment.children || []).map(child => child.id)\n                );\n                const filteredReplies = newReplies.filter(\n                    reply => !existingIds.has(reply.id)\n                );\n\n                return {\n                    ...comment,\n                    children: [...(comment.children || []), ...filteredReplies],\n                };\n            });\n        },\n        [updateCommentInTree]\n    );\n\n    const handleNewComment = useCallback(\n        (newComment: Comment, parentId?: string, insertAfterId?: string) => {\n            if (parentId) {\n                // 回复评论：添加到指定父评论的children数组\n                addReplyToComment(parentId, newComment, insertAfterId);\n            } else {\n                // 顶级评论：添加到主列表\n                const commentWithLocalUser = {\n                    ...newComment,\n                    author:\n                        currentUser?.displayName ||\n                        currentUser?.username ||\n                        'Anonymous',\n                    authorAvatarUrls: currentUser?.avatarUrls,\n                };\n                setComments(prev => [commentWithLocalUser, ...prev]);\n                setTotal(prev => prev + 1);\n            }\n        },\n        [currentUser, addReplyToComment]\n    );\n\n    const handleUpdateComment = useCallback(\n        (updatedComment: Comment) => {\n            updateCommentInTree(updatedComment.id, currentComment => ({\n                ...currentComment,\n                content: updatedComment.content,\n                updatedAt: updatedComment.updatedAt,\n            }));\n        },\n        [updateCommentInTree]\n    );\n\n    const handleDeleteComment = useCallback((commentId: number | string) => {\n        const idToDelete =\n            typeof commentId === 'string' ? commentId : commentId.toString();\n\n        // 递归查找并删除评论\n        const deleteCommentRecursively = (comments: Comment[]): Comment[] => {\n            return comments\n                .map(comment => {\n                    // 如果找到要删除的评论，返回null（稍后过滤掉）\n                    if (comment.id === idToDelete) {\n                        return null;\n                    }\n\n                    // 递归处理子评论\n                    if (comment.children && comment.children.length > 0) {\n                        const updatedChildren = deleteCommentRecursively(\n                            comment.children\n                        );\n                        const filteredChildren = updatedChildren.filter(\n                            child => child !== null\n                        );\n\n                        return {\n                            ...comment,\n                            children: filteredChildren,\n                            replies: filteredChildren.length,\n                        };\n                    }\n\n                    return comment;\n                })\n                .filter(comment => comment !== null) as Comment[];\n        };\n\n        setComments(prev => {\n            const updatedComments = deleteCommentRecursively(prev);\n            // 如果删除的是顶级评论，更新总数\n            const wasTopLevel = prev.some(comment => comment.id === idToDelete);\n            if (wasTopLevel) {\n                setTotal(prevTotal => prevTotal - 1);\n            }\n            return updatedComments;\n        });\n    }, []);\n\n    const handleLoadMore = () => {\n        if (hasMore && !loadingMore) {\n            loadComments(page + 1, true);\n        }\n    };\n\n    const handleSortChange = (newSortBy: 'newest' | 'oldest' | 'likes') => {\n        if (newSortBy !== sortBy) {\n            setSortBy(newSortBy);\n            setPage(1);\n        }\n    };\n\n    if (loading) {\n        return (\n            <div className=\"video-comments\">\n                <div className=\"d-flex align-items-center mb-4\">\n                    <div className=\"placeholder-glow flex-grow-1\">\n                        <div\n                            className=\"placeholder col-4\"\n                            style={{ height: '28px' }}\n                        ></div>\n                    </div>\n                </div>\n\n                <div className=\"mb-4\">\n                    <div className=\"d-flex\">\n                        <div className=\"me-3\">\n                            <div\n                                className=\"placeholder rounded-circle\"\n                                style={{ width: '40px', height: '40px' }}\n                            ></div>\n                        </div>\n                        <div className=\"flex-grow-1 placeholder-glow\">\n                            <div\n                                className=\"placeholder col-12\"\n                                style={{ height: '60px' }}\n                            ></div>\n                        </div>\n                    </div>\n                </div>\n\n                {/* Comment skeleton */}\n                {[...Array(3)].map((_, i) => (\n                    <div key={i} className=\"mb-4 placeholder-glow\">\n                        <div className=\"d-flex\">\n                            <div className=\"me-3\">\n                                <div\n                                    className=\"placeholder rounded-circle\"\n                                    style={{ width: '36px', height: '36px' }}\n                                ></div>\n                            </div>\n                            <div className=\"flex-grow-1\">\n                                <div className=\"d-flex gap-2 mb-2\">\n                                    <div\n                                        className=\"placeholder col-2\"\n                                        style={{ height: '14px' }}\n                                    ></div>\n                                    <div\n                                        className=\"placeholder col-2\"\n                                        style={{ height: '12px' }}\n                                    ></div>\n                                </div>\n                                <div\n                                    className=\"placeholder col-10 mb-2\"\n                                    style={{ height: '16px' }}\n                                ></div>\n                                <div\n                                    className=\"placeholder col-6 mb-3\"\n                                    style={{ height: '16px' }}\n                                ></div>\n                                <div className=\"d-flex gap-2\">\n                                    <div\n                                        className=\"placeholder col-1\"\n                                        style={{ height: '24px' }}\n                                    ></div>\n                                    <div\n                                        className=\"placeholder col-1\"\n                                        style={{ height: '24px' }}\n                                    ></div>\n                                    <div\n                                        className=\"placeholder col-1\"\n                                        style={{ height: '24px' }}\n                                    ></div>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                ))}\n            </div>\n        );\n    }\n\n    if (error) {\n        return (\n            <div className=\"video-comments\">\n                <Alert variant=\"warning\" className=\"d-flex align-items-center\">\n                    <i className=\"bi bi-exclamation-triangle me-2\"></i>\n                    <div>\n                        <strong>{t('ui.comment.loadError')}</strong>\n                        <div className=\"small\">{error}</div>\n                    </div>\n                </Alert>\n                <div className=\"text-center mt-3\">\n                    <Button\n                        variant=\"outline-primary\"\n                        onClick={() => loadComments()}\n                    >\n                        <i className=\"bi bi-arrow-clockwise me-2\"></i>\n                        {t('ui.comment.tryAgain')}\n                    </Button>\n                </div>\n            </div>\n        );\n    }\n\n    // 折叠模式下的点击展开按钮\n    const renderCollapsibleHeader = () => (\n        <div\n            className=\"d-flex align-items-center justify-content-between py-3 border-top\"\n            style={{ cursor: 'pointer' }}\n            onClick={() => setIsExpanded(!isExpanded)}\n        >\n            <div className=\"d-flex align-items-center\">\n                <i className=\"bi bi-chat-left-text me-2 text-muted\"></i>\n                <span className=\"fw-semibold\">\n                    {t('ui.comment.count', {\n                        count: total.toLocaleString(),\n                        plural: total !== 1 ? 's' : '',\n                    })}\n                </span>\n            </div>\n            <i\n                className={`bi bi-chevron-${isExpanded ? 'up' : 'down'} text-muted`}\n            ></i>\n        </div>\n    );\n\n    const renderCommentsContent = () => (\n        <>\n            {/* Comments Header - PC 端显示标题，移动端折叠模式下不显示 */}\n            <div className=\"d-flex align-items-center justify-content-between mb-4\">\n                {!collapsible && (\n                    <h5 className=\"mb-0 fw-semibold\">\n                        {t('ui.comment.count', {\n                            count: total.toLocaleString(),\n                            plural: total !== 1 ? 's' : '',\n                        })}\n                    </h5>\n                )}\n                <ButtonGroup>\n                    {getSortOptions().map(option => (\n                        <Button\n                            size=\"sm\"\n                            key={option.value}\n                            variant={\n                                sortBy === option.value\n                                    ? 'secondary'\n                                    : 'outline-secondary'\n                            }\n                            onClick={() => handleSortChange(option.value)}\n                        >\n                            {option.label}\n                        </Button>\n                    ))}\n                </ButtonGroup>\n            </div>\n\n            <div className=\"mb-5\">\n                <div className=\"d-flex\">\n                    <div className=\"flex-grow-1\">\n                        <CommentForm\n                            videoId={videoId}\n                            onSubmit={handleNewComment}\n                            placeholder={\n                                currentUserId\n                                    ? t('ui.comment.addComment')\n                                    : t('ui.comment.signInToComment')\n                            }\n                        />\n                    </div>\n                </div>\n            </div>\n\n            {/* Comments List */}\n            <div className=\"comments-list\">\n                {comments.length > 0 ? (\n                    comments.map(comment => (\n                        <CommentItem\n                            key={comment.id}\n                            comment={comment}\n                            videoId={videoId}\n                            currentUserId={currentUserId}\n                            currentUserRole={currentUserRole}\n                            videoOwnerId={videoOwnerId}\n                            onUpdate={handleUpdateComment}\n                            onDelete={handleDeleteComment}\n                            onReply={handleNewComment}\n                            onLoadMoreReplies={loadMoreRepliesToComment}\n                            onRemoveReply={removeReplyFromComment}\n                            level={0}\n                        />\n                    ))\n                ) : (\n                    /* Empty State */\n                    <div className=\"text-center py-5\">\n                        <div className=\"mb-4\">\n                            <i\n                                className=\"bi bi-chat-square-text text-muted\"\n                                style={{ fontSize: '3rem' }}\n                            ></i>\n                        </div>\n                        <h6 className=\"text-muted mb-2\">\n                            {t('ui.comment.noComments')}\n                        </h6>\n                        <p className=\"text-muted mb-4\">\n                            {currentUserId\n                                ? t('ui.comment.beFirst')\n                                : t('ui.comment.signInToComment')}\n                        </p>\n                        {!currentUserId && (\n                            <Button\n                                variant=\"outline-primary\"\n                                size=\"sm\"\n                                onClick={() => {\n                                    redirectToLogin(\n                                        {\n                                            action: 'comment',\n                                            targetId: videoId,\n                                        },\n                                        window.location.pathname +\n                                            window.location.search\n                                    );\n                                }}\n                                className=\"rounded-pill px-4\"\n                            >\n                                {t('ui.comment.signInButton')}\n                            </Button>\n                        )}\n                    </div>\n                )}\n            </div>\n\n            {/* Load More Button */}\n            {hasMore && comments.length > 0 && (\n                <div className=\"text-center mt-5\">\n                    <Button\n                        variant=\"outline-secondary\"\n                        onClick={handleLoadMore}\n                        disabled={loadingMore}\n                        className=\"rounded-pill px-4\"\n                        style={{ minWidth: '160px' }}\n                    >\n                        {loadingMore ? (\n                            <>\n                                <Spinner\n                                    as=\"span\"\n                                    animation=\"border\"\n                                    size=\"sm\"\n                                    role=\"status\"\n                                    aria-hidden=\"true\"\n                                    className=\"me-2\"\n                                />\n                                {t('ui.comment.loadingComments')}\n                            </>\n                        ) : (\n                            <>\n                                <i className=\"bi bi-arrow-down me-2\"></i>\n                                {t('ui.comment.showMore')}\n                            </>\n                        )}\n                    </Button>\n                </div>\n            )}\n\n            {/* Footer message */}\n            {!hasMore && comments.length > 10 && (\n                <div className=\"text-center mt-4 pt-4 border-top\">\n                    <small className=\"text-muted\">\n                        <i className=\"bi bi-check-circle me-2\"></i>\n                        {t('ui.comment.endReached')}\n                    </small>\n                </div>\n            )}\n        </>\n    );\n\n    if (collapsible) {\n        return (\n            <div className=\"video-comments mt-4\">\n                {renderCollapsibleHeader()}\n                {isExpanded && (\n                    <div className=\"pt-2\">{renderCommentsContent()}</div>\n                )}\n            </div>\n        );\n    }\n\n    return <div className=\"video-comments mt-5\">{renderCommentsContent()}</div>;\n}\n","export interface YuanhuiNavigationVideo {\n    id: string;\n    title: string;\n}\n\nexport interface YuanhuiVideoNavigationLink {\n    id: string;\n    title: string;\n    href: string;\n}\n\nexport interface YuanhuiVideoNavigation {\n    previous?: YuanhuiVideoNavigationLink;\n    next?: YuanhuiVideoNavigationLink;\n}\n\ninterface SelectYuanhuiVideoNavigationOptions {\n    masterSource?: string;\n    navigation?: {\n        previous?: YuanhuiNavigationVideo;\n        next?: YuanhuiNavigationVideo;\n    };\n}\n\nexport function buildYuanhuiVideoHref(videoId: string): string {\n    return `/video/${encodeURIComponent(videoId)}?source=yuanhui`;\n}\n\nfunction toNavigationLink(\n    video?: YuanhuiNavigationVideo\n): YuanhuiVideoNavigationLink | undefined {\n    if (!video) return undefined;\n\n    return {\n        id: video.id,\n        title: video.title,\n        href: buildYuanhuiVideoHref(video.id),\n    };\n}\n\nexport function selectYuanhuiVideoNavigation({\n    masterSource,\n    navigation,\n}: SelectYuanhuiVideoNavigationOptions): YuanhuiVideoNavigation | null {\n    if (masterSource !== 'yuanhui') return null;\n\n    const links = {\n        previous: toNavigationLink(navigation?.previous),\n        next: toNavigationLink(navigation?.next),\n    };\n\n    return links.previous || links.next ? links : null;\n}\n","import React, { useState, useEffect, useRef } from 'react';\nimport { api, getErrorMessage } from '../../libs';\nimport { formatDuration, formatTimeAgo } from '../../libs/datetime';\nimport { useTranslation } from '../../libs/i18n';\nimport { appPath, appendCurrentChannel, getDefaultUrl } from '../../libs/url';\nimport {\n    selectYuanhuiVideoNavigation,\n    YuanhuiVideoNavigationLink,\n} from './yuanhuiVideoNavigation';\nimport './relatedvideos.scss';\n\ninterface RelatedVideo {\n    id: string;\n    title: string;\n    description?: string;\n    thumbnailUrls?: {\n        small: string;\n        medium: string;\n        large: string;\n    };\n    duration?: number;\n    views: number;\n    likes?: number;\n    publishedAt?: string;\n    tags?: string[];\n    category?: {\n        id: number;\n        name: string;\n    };\n    author: {\n        id?: number;\n        username: string;\n        displayName?: string;\n        avatarUrls?: {\n            small: string;\n            medium: string;\n            large: string;\n        };\n        isVerified?: boolean;\n        url: string;\n    };\n    url: string;\n}\n\ninterface RelatedVideosProps {\n    videoId: string;\n    masterSource?: string;\n}\n\ninterface RelatedVideosResponse {\n    success: boolean;\n    data: {\n        sameAuthor: RelatedVideo[];\n        otherAuthors: RelatedVideo[];\n        navigation?: {\n            previous?: RelatedVideo;\n            next?: RelatedVideo;\n        };\n    };\n}\n\nexport function RelatedVideos({ videoId, masterSource }: RelatedVideosProps) {\n    const { t } = useTranslation();\n    const isMasterMode = Boolean(masterSource);\n    const containerRef = useRef<HTMLDivElement>(null);\n    const [sameAuthorVideos, setSameAuthorVideos] = useState<RelatedVideo[]>(\n        []\n    );\n    const [otherAuthorsVideos, setOtherAuthorsVideos] = useState<\n        RelatedVideo[]\n    >([]);\n    const [adjacentVideos, setAdjacentVideos] = useState<{\n        previous?: RelatedVideo;\n        next?: RelatedVideo;\n    }>({});\n    const [loading, setLoading] = useState(true);\n    const [error, setError] = useState('');\n    const [shouldLoad, setShouldLoad] = useState(false);\n    const [visibleCount, setVisibleCount] = useState(20);\n\n    // 检测容器是否可见（避免桌面端和移动端同时请求）\n    useEffect(() => {\n        const container = containerRef.current;\n        if (!container) return;\n\n        // 检查容器是否可见（通过检查父元素是否有 d-none 类）\n        const checkVisibility = () => {\n            const parent = container.parentElement;\n            if (!parent) return false;\n\n            // 检查父元素或自身是否被隐藏\n            const style = window.getComputedStyle(parent);\n            return style.display !== 'none';\n        };\n\n        // 初始检查\n        if (checkVisibility()) {\n            setShouldLoad(true);\n            return;\n        }\n\n        // 使用 ResizeObserver 监听布局变化\n        const observer = new ResizeObserver(() => {\n            if (checkVisibility()) {\n                setShouldLoad(true);\n                observer.disconnect();\n            }\n        });\n\n        observer.observe(document.body);\n\n        return () => observer.disconnect();\n    }, []);\n\n    useEffect(() => {\n        if (shouldLoad && videoId) {\n            setVisibleCount(20);\n            loadRelatedVideos();\n        }\n    }, [shouldLoad, videoId]);\n\n    const loadRelatedVideos = async () => {\n        try {\n            setLoading(true);\n            setError('');\n\n            const response = await api.get<RelatedVideosResponse>(\n                `/api/videos/${videoId}/related`\n            );\n\n            if (response.data.success) {\n                setSameAuthorVideos(response.data.data.sameAuthor);\n                setOtherAuthorsVideos(\n                    isMasterMode ? [] : response.data.data.otherAuthors\n                );\n                setAdjacentVideos(response.data.data.navigation || {});\n            }\n        } catch (err) {\n            setError(getErrorMessage(err));\n        } finally {\n            setLoading(false);\n        }\n    };\n\n    const relatedHref = (url: string) => {\n        const current = new URLSearchParams(window.location.search);\n        const nextUrl = new URL(\n            appendCurrentChannel(url),\n            window.location.origin\n        );\n        if (masterSource) nextUrl.searchParams.set('source', masterSource);\n        if (current.get('embedded')) {\n            nextUrl.searchParams.set('embedded', current.get('embedded') || '');\n        }\n        if (current.get('lang')) {\n            nextUrl.searchParams.set('lang', current.get('lang') || '');\n        }\n        return `${nextUrl.pathname}${nextUrl.search}`;\n    };\n\n    const navigation = selectYuanhuiVideoNavigation({\n        masterSource,\n        navigation: adjacentVideos,\n    });\n\n    const renderNavigationLink = (\n        label: string,\n        link: YuanhuiVideoNavigationLink,\n        alignment: 'start' | 'end'\n    ) => (\n        <a\n            href={link.href}\n            className={`btn btn-outline-secondary d-flex flex-column text-${alignment} yuanhui-video-navigation-link`}\n        >\n            <span className=\"small text-muted\">{label}</span>\n            <span className=\"yuanhui-video-navigation-title\">{link.title}</span>\n        </a>\n    );\n\n    const renderVideoItem = (video: RelatedVideo) => (\n        <a\n            key={video.id}\n            href={relatedHref(video.url)}\n            className=\"text-decoration-none text-dark d-flex mb-3\"\n        >\n            {/* Thumbnail */}\n            <div className=\"me-2 position-relative bg-secondary-subtle rounded\">\n                <img\n                    src={\n                        video.thumbnailUrls?.medium ||\n                        appPath('/assets/images/cover.svg')\n                    }\n                    alt={video.title}\n                    className=\"rounded\"\n                    style={{\n                        width: '128px',\n                        height: '72px',\n                        objectFit: 'cover',\n                        aspectRatio: '16/9',\n                    }}\n                    onError={event => {\n                        event.currentTarget.onerror = null;\n                        event.currentTarget.src = getDefaultUrl('cover');\n                    }}\n                />\n                {video.duration && (\n                    <span\n                        className=\"position-absolute bottom-0 end-0 bg-dark text-white px-1 rounded\"\n                        style={{\n                            fontSize: '0.75rem',\n                            margin: '4px',\n                        }}\n                    >\n                        {formatDuration(video.duration)}\n                    </span>\n                )}\n            </div>\n\n            {/* Video Info */}\n            <div className=\"flex-grow-1 d-flex flex-column justify-content-between\">\n                <div className=\"fw-medium mb-1 lh-sm text-truncate-2\">\n                    {video.title}\n                </div>\n                <div\n                    className=\"text-muted d-flex align-items-center\"\n                    style={{ fontSize: '0.8rem' }}\n                >\n                    <span>\n                        {t(\n                            'ui.video.views',\n                            { count: video.views },\n                            { count: video.views }\n                        )}\n                    </span>\n                    <span className=\"mx-1\">•</span>\n                    <span>\n                        {video.publishedAt\n                            ? formatTimeAgo(video.publishedAt)\n                            : ''}\n                    </span>\n                </div>\n            </div>\n        </a>\n    );\n\n    if (!shouldLoad) {\n        return <div ref={containerRef}></div>;\n    }\n\n    if (loading) {\n        return (\n            <div ref={containerRef}>\n                {[1, 2, 3, 4, 5].map(i => (\n                    <div key={i} className=\"d-flex mb-3\">\n                        <div\n                            className=\"placeholder me-2\"\n                            style={{\n                                width: '168px',\n                                height: '94px',\n                                borderRadius: '8px',\n                            }}\n                        ></div>\n                        <div className=\"flex-grow-1\">\n                            <div\n                                className=\"placeholder col-12 mb-1\"\n                                style={{ height: '16px' }}\n                            ></div>\n                            <div\n                                className=\"placeholder col-8 mb-1\"\n                                style={{ height: '14px' }}\n                            ></div>\n                            <div\n                                className=\"placeholder col-6\"\n                                style={{ height: '14px' }}\n                            ></div>\n                        </div>\n                    </div>\n                ))}\n            </div>\n        );\n    }\n\n    const totalVideos = sameAuthorVideos.length + otherAuthorsVideos.length;\n\n    if (error || totalVideos === 0) {\n        return (\n            <div ref={containerRef}>\n                <div className=\"text-center py-4 text-muted\">\n                    <small>{t('ui.empty.noRelatedVideos')}</small>\n                </div>\n            </div>\n        );\n    }\n\n    // 合并所有相关视频（先显示同作者，再显示其他作者）\n    const allVideos = [...sameAuthorVideos, ...otherAuthorsVideos].slice(0, 40);\n\n    return (\n        <div ref={containerRef}>\n            {navigation && (\n                <div className=\"yuanhui-video-navigation mb-3\">\n                    {navigation.previous ? (\n                        renderNavigationLink(\n                            '上一篇视频',\n                            navigation.previous,\n                            'start'\n                        )\n                    ) : (\n                        <span className=\"yuanhui-video-navigation-spacer\"></span>\n                    )}\n                    {navigation.next ? (\n                        renderNavigationLink(\n                            '下一篇视频',\n                            navigation.next,\n                            'end'\n                        )\n                    ) : (\n                        <span className=\"yuanhui-video-navigation-spacer\"></span>\n                    )}\n                </div>\n            )}\n            {allVideos.slice(0, visibleCount).map(renderVideoItem)}\n            {visibleCount < allVideos.length && (\n                <button\n                    type=\"button\"\n                    className=\"btn btn-outline-secondary w-100\"\n                    onClick={() => setVisibleCount(count => count + 20)}\n                >\n                    {t('ui.button.loadMore')}\n                </button>\n            )}\n        </div>\n    );\n}\n","import { render } from '../../libs';\nimport { I18nProvider } from '../../libs/i18n';\nimport { isSupportedLanguage, SupportedLanguage } from '@zentube/i18n';\nimport { VideoWatchMain, VideoWatchMainProps } from './videowatchmain';\nimport { VideoComments } from './videocomments';\nimport { RelatedVideos } from './relatedvideos';\n\n// 渲染主要区域（包含播放器和视频信息）\nrender('video-main-container', (props: VideoWatchMainProps) => {\n    const language: SupportedLanguage | undefined =\n        props.language && isSupportedLanguage(props.language)\n            ? props.language\n            : undefined;\n\n    return (\n        <I18nProvider initialLanguage={language}>\n            <VideoWatchMain {...props} language={language} />\n        </I18nProvider>\n    );\n});\n\n// 渲染桌面端评论区域（始终展开）\nrender('video-comments-container', (props: VideoWatchMainProps) => {\n    const language: SupportedLanguage | undefined =\n        props.language && isSupportedLanguage(props.language)\n            ? props.language\n            : undefined;\n\n    return (\n        <I18nProvider initialLanguage={language}>\n            <VideoComments {...props} collapsible={false} />\n        </I18nProvider>\n    );\n});\n\n// 渲染手机端评论区域（可折叠）\nrender('video-comments-container-mobile', (props: VideoWatchMainProps) => {\n    const language: SupportedLanguage | undefined =\n        props.language && isSupportedLanguage(props.language)\n            ? props.language\n            : undefined;\n\n    return (\n        <I18nProvider initialLanguage={language}>\n            <VideoComments {...props} collapsible={true} />\n        </I18nProvider>\n    );\n});\n\n// 渲染相关视频（桌面端右侧边栏）\nrender('related-videos-container', (props: VideoWatchMainProps) => {\n    const language: SupportedLanguage | undefined =\n        props.language && isSupportedLanguage(props.language)\n            ? props.language\n            : undefined;\n\n    return (\n        <I18nProvider initialLanguage={language}>\n            <RelatedVideos {...props} />\n        </I18nProvider>\n    );\n});\n\n// 渲染相关视频（手机端）\nrender('related-videos-container-mobile', (props: VideoWatchMainProps) => {\n    const language: SupportedLanguage | undefined =\n        props.language && isSupportedLanguage(props.language)\n            ? props.language\n            : undefined;\n\n    return (\n        <I18nProvider initialLanguage={language}>\n            <RelatedVideos {...props} />\n        </I18nProvider>\n    );\n});\n"],"names":["InputGroupText","React.forwardRef","className","bsPrefix","Component","props","ref","useBootstrapPrefix","_jsx","classNames","InputGroupCheckbox","FormCheckInput","InputGroupRadio","InputGroup","size","hasValidation","contextValue","useMemo","InputGroupContext","InputGroup$1","createUtilityClassName","utilityValues","breakpoints","DEFAULT_BREAKPOINTS","minBreakpoint","DEFAULT_MIN_BREAKPOINT","classes","utilName","utilValue","brkPoint","bpValue","infix","Stack","direction","gap","useBootstrapBreakpoints","useBootstrapMinBreakpoint","FavoriteButton","videoId","currentUserId","t","useTranslation","isFavorited","setIsFavorited","useState","loading","setLoading","favoriteStatusKnown","setFavoriteStatusKnown","favoriteStatusResolved","setFavoriteStatusResolved","useEffect","loadFavoriteStatus","response","api","err","getErrorMessage","handleToggleFavorite","redirectToLogin","originalFavoriteStatus","trackFavorite","errorMsg","showError","errorMessage","consumeNativeAuthResume","jsxs","Button","jsx","s","m","h","d","y","ms","val","options","type","parse","fmtLong","fmtShort","str","match","n","plural","name","exports","module","createDebug","coerce","disable","enable","enabled","require$$0","prevTime","selectColor","namespace","hash","i","debug","self","curr","args","index","format","formatter","logFn","namespaces","split","len","log","formatArgs","save","load","useColors","localstorage","v","c","lastC","r","define_process_env_default","jsonp_1","jsonp","count","noop","url","opts","fn","prefix","id","param","timeout","enc","target","script","timer","cleanup","cancel","data","__defProp","__defProps","__getOwnPropDescs","__getOwnPropSymbols","__hasOwnProp","__propIsEnum","__defNormalProp","obj","key","value","__spreadValues","a","b","prop","__spreadProps","__objRest","source","exclude","createIcon","iconConfig","_a","_b","bgStyle","borderRadius","iconFillColor","round","rest","AssertionError","message","assert","objectToGetParams","object","params","isPromise","getBoxPositionOnWindowCenter","width","height","getBoxPositionOnScreenCenter","windowOpen","onClose","configRest","config","shareDialog","interval","e","ShareButton","_c","_d","beforeOnClick","children","disabled","disabledStyle","forwardedRef","htmlTitle","networkLink","networkName","onClick","onShareWindowClose","openShareDialogOnClick","resetButtonStyle","style","title","windowHeight","windowPosition","windowWidth","handleClick","event","link","returnVal","windowConfig","newClassName","cx","newStyle","createShareButton","optsMap","defaultProps","CreatedButton","passedProps","forwardRef","blueskyLink","separator","EmailIcon","emailLink","subject","body","EmailShareButton","_","FacebookIcon","facebookMessengerLink","appId","redirectUri","to","facebookLink","hashtag","FacebookShareButton","useIsMounted","isMounted","useRef","useCallback","SocialMediaShareCount","_e","_f","shareCount","getCount","setCount","isLoading","setIsLoading","count2","createShareCount","ShareCount","getFacebookShareCount","shareUrl","callback","endpoint","hatenaLink","getHatenaShareCount","instapaperLink","description","lineLink","LinkedinIcon","linkedinLink","summary","LinkedinShareButton","livejournalLink","mailruLink","imageUrl","okLink","image","getOKShareCount","index2","_count","callbackIndex","pinterestLink","media","pinId","getPinterestShareCount","pocketLink","redditLink","gabLink","getRedditShareCount","telegramLink","threadsLink","tumblrLink","caption","tags","posttype","getTumblrShareCount","TwitterIcon","twitterLink","via","hashtags","related","TwitterShareButton","viberLink","vkLink","noParse","noVkLinks","getVKShareCount","WeiboIcon","weiboLink","WeiboShareButton","isMobileOrTablet","whatsappLink","workplaceLink","quote","ShareDropdown","copied","setCopied","linkInputRef","handleCopyLink","absoluteShareUrl","showSuccess","handleNativeShare","CustomToggle","React","Dropdown","FormControl","PENDING_PAYMENT_KEY","GiftModal","show","onHide","videoAuthorId","selectedGift","setSelectedGift","setMessage","gifts","setGifts","giftsLoading","setGiftsLoading","donationLoading","setDonationLoading","showPaymentResult","setShowPaymentResult","paymentId","setPaymentId","checkingPayment","setCheckingPayment","paymentWindowRef","pollingIntervalRef","pollingStartTimeRef","pollingAttemptRef","hasNotifiedSuccessRef","hasShownSuccessToastRef","isVerifyingRef","savedGiftRef","savedMessageRef","isInApp","isInAppBrowser","POLLING_CONFIG","getPollingInterval","attempt","fetchGifts","stopPolling","closePaymentWindow","returnToGiftForm","notifyDonationSuccess","amount","donationMessage","showDonationSuccessToast","handlePaymentSuccess","trackPayment","handlePaymentFailure","checkPaymentStatus","status","PaymentStatus","error","handleGiftSelect","gift","handleClose","handlePaymentCompleted","scheduleNextPoll","urlParams","paymentSuccess","paymentCancelled","paymentError","urlPaymentId","cleanUrl","handleDonation","paymentWindow","donationData","paymentData","PaymentType","paymentUrl","handleMessage","timestamp","Fragment","Modal","Spinner","Row","tooltip","Tooltip","Col","OverlayTrigger","Form","DonationCommentDisplay","comment","giftAmount","Badge","VideoPlayerContainer","video","initialProgress","VideoPlayer","ConfirmModal","confirmText","cancelText","variant","onConfirm","onCancel","ReportModal","reasons","setReasons","selectedReason","setSelectedReason","setDescription","setError","success","setSuccess","loadingReasons","setLoadingReasons","loadReportReasons","handleSubmit","canSubmit","Alert","reason","VideoInfo","onVideoUpdate","embedded","useEmbedded","liking","setLiking","showReportModal","setShowReportModal","recommending","setRecommending","deleting","setDeleting","showDeleteConfirm","setShowDeleteConfirm","showGiftModal","setShowGiftModal","setShareUrl","canEdit","canDelete","canRecommend","useVideoPermissions","handleLike","action","originalLikedStatus","originalLikesCount","newLikedStatus","newLikesCount","trackLike","handleRecommend","handleReport","handleDelete","authorDonationsEnabled","handleGift","returnUrl","appPath","performDelete","authorProfileHref","UserAvatar","VerifiedBadge","FollowButton","tag","VideoWatchMain","initialVideo","setVideo","resumeProgress","setResumeProgress","trackedContentVideoId","loadVideo","active","saved","progress","duration","handleVideoUpdate","updatedFields","trackEvent","CommentForm","parentId","replyUserId","placeholder","onSubmit","autoFocus","currentUser","useAuth","isSubmitting","setIsSubmitting","isFocused","setIsFocused","textareaRef","register","reset","watch","errors","isValid","useForm","content","textarea","onFormSubmit","payload","handleCancel","handleFocus","handleBlur","isReplyForm","showActions","defaultPlaceholder","CommentEditForm","isDirty","length","hasChanges","CommentItem","currentUserRole","videoOwnerId","onUpdate","onDelete","onReply","onLoadMoreReplies","onRemoveReply","level","topLevelCommentId","isEditing","setIsEditing","isReplying","setIsReplying","isLiking","setIsLiking","isDeleting","setIsDeleting","loadingMoreReplies","setLoadingMoreReplies","isFlagging","setIsFlagging","isHovered","setIsHovered","currentComment","setCurrentComment","likes","setLikes","dislikes","setDislikes","isLikedByUser","setIsLikedByUser","isDislikedByUser","setIsDislikedByUser","isDisliking","setIsDisliking","canFlag","originalLiked","originalDisliked","originalLikes","originalDislikes","newIsLiked","newIsDisliked","newLikes","newDislikes","serverLikes","serverDislikes","serverIsLiked","serverIsDisliked","handleDislike","loadMoreReplies","newReplies","handleFlag","handleEditSubmit","updatedComment","handleReplySubmit","newComment","commentWithLocalUser","insertAfterId","formatDate","dateString","formatTimeAgo","childComment","VideoComments","collapsible","comments","setComments","loadingMore","setLoadingMore","total","setTotal","page","setPage","hasMore","setHasMore","sortBy","setSortBy","isExpanded","setIsExpanded","getSortOptions","loadComments","pageNum","append","sortOption","topCommentId","sortConfig","urlTopComment","topComment","shouldIncludeTopComment","newComments","newTotal","newHasMore","newPage","prev","handleHashChange","newHash","newTopCommentId","scrollToComment","handleDonationCompleted","commentId","element","updateCommentInTree","updater","updatedChildren","child","addReplyToComment","newReply","newChildren","insertIndex","removeReplyFromComment","replyId","loadMoreRepliesToComment","existingIds","filteredReplies","reply","handleNewComment","handleUpdateComment","handleDeleteComment","idToDelete","deleteCommentRecursively","filteredChildren","updatedComments","prevTotal","handleLoadMore","handleSortChange","newSortBy","renderCollapsibleHeader","renderCommentsContent","ButtonGroup","option","buildYuanhuiVideoHref","toNavigationLink","selectYuanhuiVideoNavigation","masterSource","navigation","links","RelatedVideos","isMasterMode","containerRef","sameAuthorVideos","setSameAuthorVideos","otherAuthorsVideos","setOtherAuthorsVideos","adjacentVideos","setAdjacentVideos","shouldLoad","setShouldLoad","visibleCount","setVisibleCount","container","checkVisibility","parent","observer","loadRelatedVideos","relatedHref","current","nextUrl","appendCurrentChannel","renderNavigationLink","label","alignment","renderVideoItem","getDefaultUrl","formatDuration","totalVideos","allVideos","render","language","isSupportedLanguage","I18nProvider"],"mappings":"g5DAMA,MAAMA,GAA8BC,EAAAA,WAAiB,CAAC,CACpD,UAAAC,EACA,SAAAC,EACA,GAAIC,EAAY,OAChB,GAAGC,CACL,EAAGC,KACDH,EAAWI,GAAmBJ,EAAU,kBAAkB,EACtCK,EAAAA,IAAKJ,EAAW,CAClC,IAAKE,EACL,UAAWG,GAAWP,EAAWC,CAAQ,EACzC,GAAGE,CACP,CAAG,EACF,EACDL,GAAe,YAAc,iBCT7B,MAAMU,GAAqBL,GAAsBG,EAAAA,IAAKR,GAAgB,CACpE,SAAuBQ,EAAAA,IAAKG,GAAgB,CAC1C,KAAM,WACN,GAAGN,CACP,CAAG,CACH,CAAC,EACKO,GAAkBP,GAAsBG,EAAAA,IAAKR,GAAgB,CACjE,SAAuBQ,EAAAA,IAAKG,GAAgB,CAC1C,KAAM,QACN,GAAGN,CACP,CAAG,CACH,CAAC,EACKQ,GAA0BZ,EAAAA,WAAiB,CAAC,CAChD,SAAAE,EACA,KAAAW,EACA,cAAAC,EACA,UAAAb,EAEA,GAAIE,EAAY,MAChB,GAAGC,CACL,EAAGC,IAAQ,CACTH,EAAWI,GAAmBJ,EAAU,aAAa,EAIrD,MAAMa,EAAeC,EAAAA,QAAQ,KAAO,CAAA,GAAK,CAAA,CAAE,EAC3C,OAAoBT,EAAAA,IAAKU,GAAkB,SAAU,CACnD,MAAOF,EACP,SAAuBR,EAAAA,IAAKJ,EAAW,CACrC,IAAKE,EACL,GAAGD,EACH,UAAWI,GAAWP,EAAWC,EAAUW,GAAQ,GAAGX,CAAQ,IAAIW,CAAI,GAAIC,GAAiB,gBAAgB,CACjH,CAAK,CACL,CAAG,CACH,CAAC,EACDF,GAAW,YAAc,aACzB,MAAAM,GAAe,OAAO,OAAON,GAAY,CACvC,KAAMb,GACN,MAAOY,GACP,SAAUF,EACZ,CAAC,ECtCc,SAASU,GAAuBC,EAAeC,EAAcC,GAAqBC,EAAgBC,GAAwB,CACvI,MAAMC,EAAU,CAAA,EAChB,cAAO,QAAQL,CAAa,EAAE,QAAQ,CAAC,CAACM,EAAUC,CAAS,IAAM,CAC3DA,GAAa,OACX,OAAOA,GAAc,SACvBN,EAAY,QAAQO,GAAY,CAC9B,MAAMC,EAAUF,EAAUC,CAAQ,EAClC,GAAIC,GAAW,KAAM,CACnB,MAAMC,EAAQF,IAAaL,EAAgB,IAAIK,CAAQ,GAAK,GAC5DH,EAAQ,KAAK,GAAGC,CAAQ,GAAGI,CAAK,IAAID,CAAO,EAAE,CAC/C,CACF,CAAC,EAEDJ,EAAQ,KAAK,GAAGC,CAAQ,IAAIC,CAAS,EAAE,EAG7C,CAAC,EACMF,CACT,CCvBA,MAAMM,GAAqB/B,EAAAA,WAAiB,CAAC,CAC3C,GAAIG,EAAY,MAChB,SAAAD,EACA,UAAAD,EACA,UAAA+B,EACA,IAAAC,EACA,GAAG7B,CACL,EAAGC,IAAQ,CACTH,EAAWI,GAAmBJ,EAAU8B,IAAc,aAAe,SAAW,QAAQ,EACxF,MAAMX,EAAca,GAAuB,EACrCX,EAAgBY,GAAyB,EAC/C,OAAoB5B,EAAAA,IAAKJ,EAAW,CAClC,GAAGC,EACH,IAAKC,EACL,UAAWG,GAAWP,EAAWC,EAAU,GAAGiB,GAAuB,CACnE,IAAAc,CACN,EAAOZ,EAAaE,CAAa,CAAC,CAClC,CAAG,CACH,CAAC,EACDQ,GAAM,YAAc,QCAb,SAASK,GAAe,CAC3B,QAAAC,EACA,cAAAC,EACA,UAAArC,EAAY,EAChB,EAAwB,CACpB,KAAM,CAAE,EAAAsC,CAAA,EAAMC,GAAA,EACR,CAACC,EAAaC,CAAc,EAAIC,EAAAA,SAAS,EAAK,EAC9C,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EACtC,CAACG,EAAqBC,CAAsB,EAAIJ,EAAAA,SAAS,EAAK,EAC9D,CAACK,EAAwBC,CAAyB,EAAIN,EAAAA,SAAS,EAAK,EAG1EO,EAAAA,UAAU,IAAM,CACRZ,GACAa,EAAA,CAER,EAAG,CAACd,EAASC,CAAa,CAAC,EAE3B,MAAMa,EAAqB,SAAY,CACnC,GAAI,CACA,MAAMC,EAAW,MAAMC,GAAI,IACvB,eAAehB,CAAO,WAAA,EAE1BK,EAAeU,EAAS,KAAK,WAAW,EACxCL,EAAuB,EAAI,CAC/B,OAASO,EAAK,CAEV,QAAQ,KACJ,kCACAC,GAAgBD,CAAG,CAAA,CAE3B,QAAA,CACIL,EAA0B,EAAI,CAClC,CACJ,EAEMO,EAAuB,SAAY,CACrC,GAAIZ,EAAS,OAGb,GAAI,CAACN,EAAe,CAChBmB,GAAgB,CAAE,OAAQ,WAAY,SAAUpB,EAAS,EACzD,MACJ,CAGA,MAAMqB,EAAyBjB,EAG/BC,EAAe,CAACD,CAAW,EAE3B,GAAI,CACAI,EAAW,EAAI,EACf,MAAMO,EAAW,MAAMC,GAAI,KACvB,eAAehB,CAAO,WAAA,EAG1B,GAAIe,EAAS,KAAK,QAEdV,EAAeU,EAAS,KAAK,WAAW,EAGxCO,GAAc,CACV,OAAQP,EAAS,KAAK,YAChB,WACA,aACN,SAAUf,EACV,QAAS,EAAA,CACZ,MACE,CAEHK,EAAegB,CAAsB,EACrC,MAAME,EACArB,EADWmB,EACT,4BACA,yBAD2B,EAEnCG,EAAUD,CAAQ,EAGlBD,GAAc,CACV,OAAQD,EAAyB,aAAe,WAChD,SAAUrB,EACV,QAAS,GACT,MAAO,iBAAA,CACV,CACL,CACJ,OAASiB,EAAK,CAEVZ,EAAegB,CAAsB,EACrC,MAAMI,EAAeP,GAAgBD,CAAG,EAWxC,GARAK,GAAc,CACV,OAAQD,EAAyB,aAAe,WAChD,SAAUrB,EACV,QAAS,GACT,MAAOyB,CAAA,CACV,EAIGA,EAAa,SAAS,IAAI,GAC1BA,EAAa,SAAS,SAAS,GAC/BA,EAAa,SAAS,SAAS,GAC/BA,EAAa,SAAS,IAAI,EAE1BD,EAAUtB,EAAE,+BAA+B,CAAC,MACzC,CACH,MAAMqB,EACArB,EADWmB,EACT,4BACA,yBAD2B,EAEnCG,EAAUD,CAAQ,CACtB,CACJ,QAAA,CACIf,EAAW,EAAK,CACpB,CACJ,EAEAK,OAAAA,EAAAA,UAAU,IAAM,CAERZ,GACAU,GACAe,GAAwB,CAAE,OAAQ,WAAY,SAAU1B,CAAA,CAAS,GAE7DS,GAAuB,CAACL,GACnBe,EAAA,CAGjB,EAAG,CACClB,EACAQ,EACAE,EACAP,EACAJ,CAAA,CACH,EAGG2B,EAAAA,KAACC,EAAA,CACG,QAAQ,QACR,UAAAhE,EACA,QAASuD,EACT,SAAUZ,EACV,MAEUL,EADNE,EACQ,uBACA,oBADsB,EAIlC,SAAA,CAAAyB,EAAAA,IAAC,IAAA,CACG,UAAW,MACPzB,EAAc,eAAiB,SACnC,OAAA,CAAA,EAEWF,EAAdE,EAAgB,uBAA4B,oBAAN,CAA0B,CAAA,CAAA,CAG7E,8ECjLA,IAAI0B,EAAI,IACJC,EAAID,EAAI,GACRE,EAAID,EAAI,GACRE,EAAID,EAAI,GACRE,EAAID,EAAI,OAgBZE,GAAiB,SAASC,EAAKC,EAAS,CACtCA,EAAUA,GAAW,CAAA,EACrB,IAAIC,EAAO,OAAOF,EAClB,GAAIE,IAAS,UAAYF,EAAI,OAAS,EACpC,OAAOG,EAAMH,CAAG,EACX,GAAIE,IAAS,UAAY,MAAMF,CAAG,IAAM,GAC7C,OAAOC,EAAQ,KAAOG,EAAQJ,CAAG,EAAIK,EAASL,CAAG,EAEnD,MAAM,IAAI,MACR,wDACE,KAAK,UAAUA,CAAG,EAExB,EAUA,SAASG,EAAMG,EAAK,CAElB,GADAA,EAAM,OAAOA,CAAG,EACZ,EAAAA,EAAI,OAAS,KAGjB,KAAIC,EAAQ,wHAAwH,KAClID,GAEF,GAAKC,EAGL,KAAIC,EAAI,WAAWD,EAAM,CAAC,CAAC,EACvBL,GAAQK,EAAM,CAAC,GAAK,MAAM,YAAW,EACzC,OAAQL,EAAI,CACV,IAAK,QACL,IAAK,OACL,IAAK,MACL,IAAK,KACL,IAAK,IACH,OAAOM,EAAIV,EACb,IAAK,OACL,IAAK,MACL,IAAK,IACH,OAAOU,EAAIX,EACb,IAAK,QACL,IAAK,OACL,IAAK,MACL,IAAK,KACL,IAAK,IACH,OAAOW,EAAIZ,EACb,IAAK,UACL,IAAK,SACL,IAAK,OACL,IAAK,MACL,IAAK,IACH,OAAOY,EAAIb,EACb,IAAK,UACL,IAAK,SACL,IAAK,OACL,IAAK,MACL,IAAK,IACH,OAAOa,EAAId,EACb,IAAK,eACL,IAAK,cACL,IAAK,QACL,IAAK,OACL,IAAK,KACH,OAAOc,EACT,QACE,MACN,GACA,CAUA,SAASH,EAASN,EAAI,CACpB,OAAIA,GAAMF,EACD,KAAK,MAAME,EAAKF,CAAC,EAAI,IAE1BE,GAAMH,EACD,KAAK,MAAMG,EAAKH,CAAC,EAAI,IAE1BG,GAAMJ,EACD,KAAK,MAAMI,EAAKJ,CAAC,EAAI,IAE1BI,GAAML,EACD,KAAK,MAAMK,EAAKL,CAAC,EAAI,IAEvBK,EAAK,IACd,CAUA,SAASK,EAAQL,EAAI,CACnB,OAAOU,EAAOV,EAAIF,EAAG,KAAK,GACxBY,EAAOV,EAAIH,EAAG,MAAM,GACpBa,EAAOV,EAAIJ,EAAG,QAAQ,GACtBc,EAAOV,EAAIL,EAAG,QAAQ,GACtBK,EAAK,KACT,CAMA,SAASU,EAAOV,EAAIS,EAAGE,EAAM,CAC3B,GAAI,EAAAX,EAAKS,GAGT,OAAIT,EAAKS,EAAI,IACJ,KAAK,MAAMT,EAAKS,CAAC,EAAI,IAAME,EAE7B,KAAK,KAAKX,EAAKS,CAAC,EAAI,IAAME,EAAO,GAC1C,+DC/IAC,EAAUC,EAAA,QAAiBC,EAAY,MAAQA,EAAY,QAAaA,EACxEF,EAAA,OAAiBG,EACjBH,EAAA,QAAkBI,EAClBJ,EAAA,OAAiBK,EACjBL,EAAA,QAAkBM,EAClBN,EAAA,SAAmBO,GAAA,EAMnBP,EAAA,MAAgB,CAAA,EAChBA,EAAA,MAAgB,CAAA,EAQhBA,EAAA,WAAqB,CAAA,EAMrB,IAAIQ,EASJ,SAASC,EAAYC,EAAW,CAC9B,IAAIC,EAAO,EAAGC,EAEd,IAAKA,KAAKF,EACRC,GAAUA,GAAQ,GAAKA,EAAQD,EAAU,WAAWE,CAAC,EACrDD,GAAQ,EAGV,OAAOX,EAAQ,OAAO,KAAK,IAAIW,CAAI,EAAIX,EAAQ,OAAO,MAAM,CAC9D,CAUA,SAASE,EAAYQ,EAAW,CAE9B,SAASG,GAAQ,CAEf,GAAKA,EAAM,QAEX,KAAIC,EAAOD,EAGPE,EAAO,CAAC,IAAI,KACZ3B,EAAK2B,GAAQP,GAAYO,GAC7BD,EAAK,KAAO1B,EACZ0B,EAAK,KAAON,EACZM,EAAK,KAAOC,EACZP,EAAWO,EAIX,QADIC,EAAO,IAAI,MAAM,UAAU,MAAM,EAC5BJ,EAAI,EAAGA,EAAII,EAAK,OAAQJ,IAC/BI,EAAKJ,CAAC,EAAI,UAAUA,CAAC,EAGvBI,EAAK,CAAC,EAAIhB,EAAQ,OAAOgB,EAAK,CAAC,CAAC,EAEf,OAAOA,EAAK,CAAC,GAA1B,UAEFA,EAAK,QAAQ,IAAI,EAInB,IAAIC,EAAQ,EACZD,EAAK,CAAC,EAAIA,EAAK,CAAC,EAAE,QAAQ,gBAAiB,SAASpB,EAAOsB,EAAQ,CAEjE,GAAItB,IAAU,KAAM,OAAOA,EAC3BqB,IACA,IAAIE,EAAYnB,EAAQ,WAAWkB,CAAM,EACzC,GAAmB,OAAOC,GAAtB,WAAiC,CACnC,IAAI9B,EAAM2B,EAAKC,CAAK,EACpBrB,EAAQuB,EAAU,KAAKL,EAAMzB,CAAG,EAGhC2B,EAAK,OAAOC,EAAO,CAAC,EACpBA,GACR,CACM,OAAOrB,CACb,CAAK,EAGDI,EAAQ,WAAW,KAAKc,EAAME,CAAI,EAElC,IAAII,EAAQP,EAAM,KAAOb,EAAQ,KAAO,QAAQ,IAAI,KAAK,OAAO,EAChEoB,EAAM,MAAMN,EAAME,CAAI,EAC1B,CAEE,OAAAH,EAAM,UAAYH,EAClBG,EAAM,QAAUb,EAAQ,QAAQU,CAAS,EACzCG,EAAM,UAAYb,EAAQ,UAAS,EACnCa,EAAM,MAAQJ,EAAYC,CAAS,EAGhB,OAAOV,EAAQ,MAA9B,YACFA,EAAQ,KAAKa,CAAK,EAGbA,CACT,CAUA,SAASR,EAAOgB,EAAY,CAC1BrB,EAAQ,KAAKqB,CAAU,EAEvBrB,QAAgB,CAAA,EAChBA,QAAgB,CAAA,EAKhB,QAHIsB,GAAS,OAAOD,GAAe,SAAWA,EAAa,IAAI,MAAM,QAAQ,EACzEE,EAAMD,EAAM,OAEPV,EAAI,EAAGA,EAAIW,EAAKX,IAClBU,EAAMV,CAAC,IACZS,EAAaC,EAAMV,CAAC,EAAE,QAAQ,MAAO,KAAK,EACtCS,EAAW,CAAC,IAAM,IACpBrB,EAAQ,MAAM,KAAK,IAAI,OAAO,IAAMqB,EAAW,OAAO,CAAC,EAAI,GAAG,CAAC,EAE/DrB,EAAQ,MAAM,KAAK,IAAI,OAAO,IAAMqB,EAAa,GAAG,CAAC,EAG3D,CAQA,SAASjB,GAAU,CACjBJ,EAAQ,OAAO,EAAE,CACnB,CAUA,SAASM,EAAQP,EAAM,CACrB,IAAIa,EAAGW,EACP,IAAKX,EAAI,EAAGW,EAAMvB,EAAQ,MAAM,OAAQY,EAAIW,EAAKX,IAC/C,GAAIZ,EAAQ,MAAMY,CAAC,EAAE,KAAKb,CAAI,EAC5B,MAAO,GAGX,IAAKa,EAAI,EAAGW,EAAMvB,EAAQ,MAAM,OAAQY,EAAIW,EAAKX,IAC/C,GAAIZ,EAAQ,MAAMY,CAAC,EAAE,KAAKb,CAAI,EAC5B,MAAO,GAGX,MAAO,EACT,CAUA,SAASI,EAAOd,EAAK,CACnB,OAAIA,aAAe,MAAcA,EAAI,OAASA,EAAI,QAC3CA,CACT,2FCnMAW,EAAUC,UAAiBM,GAAA,EAC3BP,EAAA,IAAcwB,EACdxB,EAAA,WAAqByB,EACrBzB,EAAA,KAAe0B,EACf1B,EAAA,KAAe2B,EACf3B,EAAA,UAAoB4B,EACpB5B,EAAA,QAAiC,OAAO,OAAtB,KACe,OAAO,OAAO,QAA7B,IACE,OAAO,QAAQ,MACf6B,EAAA,EAMpB7B,EAAA,OAAiB,CACf,gBACA,cACA,YACA,aACA,aACA,WAWF,SAAS4B,GAAY,CAInB,OAAI,OAAO,OAAW,KAAe,OAAO,SAAW,OAAO,QAAQ,OAAS,WACtE,GAKD,OAAO,SAAa,KAAe,SAAS,iBAAmB,SAAS,gBAAgB,OAAS,SAAS,gBAAgB,MAAM,kBAErI,OAAO,OAAW,KAAe,OAAO,UAAY,OAAO,QAAQ,SAAY,OAAO,QAAQ,WAAa,OAAO,QAAQ,QAG1H,OAAO,UAAc,KAAe,UAAU,WAAa,UAAU,UAAU,YAAA,EAAc,MAAM,gBAAgB,GAAK,SAAS,OAAO,GAAI,EAAE,GAAK,IAEnJ,OAAO,UAAc,KAAe,UAAU,WAAa,UAAU,UAAU,YAAA,EAAc,MAAM,oBAAoB,CAC5H,CAMA5B,EAAQ,WAAW,EAAI,SAAS8B,EAAG,CACjC,GAAI,CACF,OAAO,KAAK,UAAUA,CAAC,CAAA,OAChB5D,EAAK,CACZ,MAAO,+BAAiCA,EAAI,OAAA,CAEhD,EASA,SAASuD,EAAWT,EAAM,CACxB,IAAIY,EAAY,KAAK,UASrB,GAPAZ,EAAK,CAAC,GAAKY,EAAY,KAAO,IAC1B,KAAK,WACJA,EAAY,MAAQ,KACrBZ,EAAK,CAAC,GACLY,EAAY,MAAQ,KACrB,IAAM5B,EAAQ,SAAS,KAAK,IAAI,EAEhC,EAAC4B,EAEL,KAAIG,EAAI,UAAY,KAAK,MACzBf,EAAK,OAAO,EAAG,EAAGe,EAAG,gBAAgB,EAKrC,IAAId,EAAQ,EACRe,EAAQ,EACZhB,EAAK,CAAC,EAAE,QAAQ,cAAe,SAASpB,EAAO,CAChCA,IAAT,OACJqB,IACarB,IAAT,OAGFoC,EAAQf,GACV,CACD,EAEDD,EAAK,OAAOgB,EAAO,EAAGD,CAAC,EACzB,CASA,SAASP,GAAM,CAGb,OAAoB,OAAO,SAApB,UACF,QAAQ,KACR,SAAS,UAAU,MAAM,KAAK,QAAQ,IAAK,QAAS,SAAS,CACpE,CASA,SAASE,EAAKL,EAAY,CACxB,GAAI,CACUA,GAAR,KACFrB,EAAQ,QAAQ,WAAW,OAAO,EAElCA,EAAQ,QAAQ,MAAQqB,CAC1B,MACS,CAAA,CACb,CASA,SAASM,GAAO,CACd,IAAIM,EACJ,GAAI,CACFA,EAAIjC,EAAQ,QAAQ,KAAA,MACX,CAAA,CAGX,MAAI,CAACiC,GAAK,OAAO,QAAY,KAAe,QAAS,UACnDA,EAAIC,EAAY,OAGXD,CACT,CAMAjC,EAAQ,OAAO2B,GAAM,EAarB,SAASE,GAAe,CACtB,GAAI,CACF,OAAO,OAAO,YAAA,MACJ,CAAA,CACd,2ECpLA,IAAIhB,EAAQN,GAAA,EAAiB,OAAO,EAMpC4B,GAAiBC,EAMjB,IAAIC,EAAQ,EAMZ,SAASC,GAAM,CAAA,CAgBf,SAASF,EAAMG,EAAKC,EAAMC,EAAG,CACT,OAAOD,GAArB,aACFC,EAAKD,EACLA,EAAO,CAAA,GAEJA,IAAMA,EAAO,CAAA,GAElB,IAAIE,EAASF,EAAK,QAAU,OAIxBG,EAAKH,EAAK,MAASE,EAAUL,IAE7BO,EAAQJ,EAAK,OAAS,WACtBK,EAAkBL,EAAK,SAAb,KAAuBA,EAAK,QAAU,IAChDM,EAAM,mBACNC,EAAS,SAAS,qBAAqB,QAAQ,EAAE,CAAC,GAAK,SAAS,KAChEC,EACAC,EAGAJ,IACFI,EAAQ,WAAW,UAAU,CAC3BC,EAAO,EACHT,GAAIA,EAAG,IAAI,MAAM,SAAS,CAAC,CACrC,EAAOI,CAAO,GAGZ,SAASK,GAAS,CACZF,EAAO,YAAYA,EAAO,WAAW,YAAYA,CAAM,EAC3D,OAAOL,CAAE,EAAIL,EACTW,GAAO,aAAaA,CAAK,CACjC,CAEE,SAASE,GAAQ,CACX,OAAOR,CAAE,GACXO,EAAO,CAEb,CAEE,cAAOP,CAAE,EAAI,SAASS,EAAK,CACzBvC,EAAM,YAAauC,CAAI,EACvBF,EAAO,EACHT,GAAIA,EAAG,KAAMW,CAAI,CACzB,EAGEb,IAAQ,CAACA,EAAI,QAAQ,GAAG,EAAI,IAAM,KAAOK,EAAQ,IAAME,EAAIH,CAAE,EAC7DJ,EAAMA,EAAI,QAAQ,KAAM,GAAG,EAE3B1B,EAAM,iBAAkB0B,CAAG,EAG3BS,EAAS,SAAS,cAAc,QAAQ,EACxCA,EAAO,IAAMT,EACbQ,EAAO,WAAW,aAAaC,EAAQD,CAAM,EAEtCI,CACT,uCChGA,IAAIE,GAAY,OAAO,eACnBC,GAAa,OAAO,iBACpBC,GAAoB,OAAO,0BAC3BC,GAAsB,OAAO,sBAC7BC,GAAe,OAAO,UAAU,eAChCC,GAAe,OAAO,UAAU,qBAChCC,GAAkB,CAACC,EAAKC,EAAKC,IAAUD,KAAOD,EAAMP,GAAUO,EAAKC,EAAK,CAAE,WAAY,GAAM,aAAc,GAAM,SAAU,GAAM,MAAAC,CAAK,CAAE,EAAIF,EAAIC,CAAG,EAAIC,EACtJC,GAAiB,CAACC,EAAGC,IAAM,CAC7B,QAASC,KAAQD,IAAMA,EAAI,CAAA,GACrBR,GAAa,KAAKQ,EAAGC,CAAI,GAC3BP,GAAgBK,EAAGE,EAAMD,EAAEC,CAAI,CAAC,EACpC,GAAIV,GACF,QAASU,KAAQV,GAAoBS,CAAC,EAChCP,GAAa,KAAKO,EAAGC,CAAI,GAC3BP,GAAgBK,EAAGE,EAAMD,EAAEC,CAAI,CAAC,EAEtC,OAAOF,CACT,EACIG,GAAgB,CAACH,EAAGC,IAAMX,GAAWU,EAAGT,GAAkBU,CAAC,CAAC,EAC5DG,GAAY,CAACC,EAAQC,IAAY,CACnC,IAAIvB,EAAS,CAAA,EACb,QAASmB,KAAQG,EACXZ,GAAa,KAAKY,EAAQH,CAAI,GAAKI,EAAQ,QAAQJ,CAAI,EAAI,IAC7DnB,EAAOmB,CAAI,EAAIG,EAAOH,CAAI,GAC9B,GAAIG,GAAU,MAAQb,GACpB,QAASU,KAAQV,GAAoBa,CAAM,EACrCC,EAAQ,QAAQJ,CAAI,EAAI,GAAKR,GAAa,KAAKW,EAAQH,CAAI,IAC7DnB,EAAOmB,CAAI,EAAIG,EAAOH,CAAI,GAEhC,OAAOnB,CACT,EAKA,SAASwB,GAAWC,EAAY,CA8B9B,OA7BcC,GAAO,CACnB,IAAIC,EAAKD,EAAI,CACX,QAAAE,EAAU,CAAA,EACV,aAAAC,EAAe,EACf,cAAAC,EAAgB,QAChB,MAAAC,EAAQ,GACR,KAAArJ,EAAO,EACb,EAAQiJ,EAAIK,EAAOX,GAAUM,EAAI,CAC3B,UACA,eACA,gBACA,QACA,MACN,CAAK,EACD,OAAuB9F,EAAAA,KAAK,MAAOuF,GAAcJ,GAAe,CAAE,QAAS,YAAa,MAAOtI,EAAM,OAAQA,CAAI,EAAIsJ,CAAI,EAAG,CAAE,SAAU,CACtID,EAAwBhG,EAAAA,IAAI,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,KAAM0F,EAAW,MAAO,MAAOG,CAAO,CAAE,EAAoB7F,EAAAA,IAC/H,OACA,CACE,MAAO,KACP,OAAQ,KACR,GAAI8F,EACJ,GAAIA,EACJ,KAAMJ,EAAW,MACjB,MAAOG,CACjB,CACA,EACsB7F,EAAAA,IAAI,OAAQ,CAAE,EAAG0F,EAAW,KAAM,KAAMK,CAAa,CAAE,CAC7E,CAAK,CAAE,CAAC,CACN,CAEF,CAKA,MAAMG,WAAuB,KAAM,CACjC,YAAYC,EAAS,CACnB,MAAMA,CAAO,EACb,KAAK,KAAO,gBACd,CACF,CACA,SAASC,EAAOpB,EAAOmB,EAAS,CAC9B,GAAI,CAACnB,EACH,MAAM,IAAIkB,GAAeC,CAAO,CAEpC,CACA,SAASE,EAAkBC,EAAQ,CACjC,MAAMC,EAAS,OAAO,QAAQD,CAAM,EAAE,OAAO,CAAC,CAAA,CAAGtB,CAAK,IAA0BA,GAAU,IAAI,EAAE,IAAI,CAAC,CAACD,EAAKC,CAAK,IAAM,GAAG,mBAAmBD,CAAG,CAAC,IAAI,mBAAmB,OAAOC,CAAK,CAAC,CAAC,EAAE,EACvL,OAAOuB,EAAO,OAAS,EAAI,IAAIA,EAAO,KAAK,GAAG,CAAC,GAAK,EACtD,CACA,MAAMC,GAAa1B,GAAQ,CAAC,CAACA,IAAQ,OAAOA,GAAQ,UAAY,OAAOA,GAAQ,aAAe,SAAUA,GAAO,OAAOA,EAAI,MAAS,WAC7H2B,GAA+B,CAACC,EAAOC,KAAY,CACvD,KAAM,OAAO,WAAa,GAAK,OAAO,SAAW,OAAO,YAAc,GAAKD,EAAQ,EACnF,IAAK,OAAO,YAAc,GAAK,OAAO,SAAW,OAAO,WAAa,GAAKC,EAAS,CACrF,GACMC,GAA+B,CAACF,EAAOC,KAAY,CACvD,KAAM,OAAO,OAAO,OAASA,GAAU,EACvC,MAAO,OAAO,OAAO,MAAQD,GAAS,CACxC,GACA,SAASG,GAAWpD,EAAKkC,EAAImB,EAAS,CACpC,IAAIlB,EAAKD,EAAI,CAAE,OAAAgB,EAAQ,MAAAD,CAAK,EAAKd,EAAImB,EAAazB,GAAUM,EAAI,CAAC,SAAU,OAAO,CAAC,EACnF,MAAMoB,EAAS/B,GAAe,CAC5B,OAAA0B,EACA,MAAAD,EACA,SAAU,KACV,QAAS,KACT,OAAQ,KACR,YAAa,KACb,QAAS,KACT,WAAY,MACZ,UAAW,KACX,aAAc,MACd,OAAQ,KACZ,EAAKK,CAAU,EACPE,EAAc,OAAO,KACzBxD,EACA,GACA,OAAO,KAAKuD,CAAM,EAAE,IAAKjC,GAAQ,GAAGA,CAAG,IAAIiC,EAAOjC,CAAG,CAAC,EAAE,EAAE,KAAK,IAAI,CACvE,EACE,GAAI+B,EAAS,CACX,MAAMI,EAAW,OAAO,YAAY,IAAM,CACxC,GAAI,EACED,IAAgB,MAAQA,EAAY,UACtC,OAAO,cAAcC,CAAQ,EAC7BJ,EAAQG,CAAW,EAEvB,OAASE,EAAG,CACV,QAAQ,MAAMA,CAAC,CACjB,CACF,EAAG,GAAG,CACR,CACA,OAAOF,CACT,CACA,SAASG,GAAYC,EAAI,CACvB,IAAIC,EAAKD,EAAI,CACX,cAAAE,EACA,SAAAC,EACA,UAAAzL,EACA,SAAA0L,EACA,cAAAC,EAAgB,CAAE,QAAS,EAAG,EAC9B,aAAAC,EACA,UAAAC,EACA,YAAAC,EACA,YAAaC,EACb,QAASC,EACT,mBAAAC,EACA,uBAAAC,EAAyB,GACzB,KAAAvE,EACA,iBAAAwE,EAAmB,GACnB,MAAAC,EACA,MAAOC,EACP,IAAK3E,EACL,aAAA4E,EAAe,IACf,eAAAC,EAAiB,eACjB,YAAAC,EAAc,GAClB,EAAMjB,EAAIrB,EAAOX,GAAUgC,EAAI,CAC3B,gBACA,WACA,YACA,WACA,gBACA,eACA,YACA,cAEA,cAEA,UACA,qBACA,yBACA,OACA,mBACA,QAEA,QAEA,MACA,eACA,iBACA,aACJ,CAAG,EACD,MAAMkB,EAAc,MAAOC,GAAU,CACnC,MAAMC,EAAOb,EAAYpE,EAAKC,CAAI,EAClC,GAAI,CAAA+D,EAIJ,IADAgB,EAAM,eAAc,EAChBlB,EAAe,CACjB,MAAMoB,EAAYpB,EAAa,EAC3Bf,GAAUmC,CAAS,GACrB,MAAMA,CAEV,CACA,GAAIV,EAAwB,CAC1B,MAAMW,EAAe3D,GAAe,CAClC,OAAQoD,EACR,MAAOE,CACf,EAASD,IAAmB,eAAiB7B,GAA6B8B,EAAaF,CAAY,EAAIzB,GAA6B2B,EAAaF,CAAY,CAAC,EACxJxB,GAAW6B,EAAME,EAAcZ,CAAkB,CACnD,CACID,GACFA,EAAQU,EAAOC,CAAI,EAEvB,EACMG,EAAeC,GACnB,2BACA,CACE,qCAAsC,CAAC,CAACrB,EACxC,SAAU,CAAC,CAACA,CAClB,EACI1L,CACJ,EACQgN,GAA8B9D,GAAeA,GAAlCiD,EAAiD,CAChE,gBAAiB,cACjB,OAAQ,OACR,QAAS,EACT,KAAM,UACN,MAAO,UACP,OAAQ,SACZ,EAAwE,GAAnEC,CAAK,EAAGV,GAAYC,CAAa,EACpC,OAAuB1H,EAAAA,IACrB,SACAqF,GAAcJ,GAAe,GAAIgB,CAAI,EAAG,CACtC,UAAW4C,EACX,QAASL,EACT,IAAKb,EACL,MAAOoB,GACP,MAAOnB,EACP,SAAAJ,CACN,CAAK,CACL,CACA,CACA,SAASwB,EAAkBlB,EAAaY,EAAMO,EAASC,EAAc,CACnE,MAAMC,EAAgB,CAACjN,EAAOC,IAAQ,CACpC,MAAMuH,EAAOuF,EAAQ/M,CAAK,EACpBkN,EAAcnE,GAAe,CAAA,EAAI/I,CAAK,EAE5C,OADiB,OAAO,KAAKwH,CAAI,EACxB,QAASqB,GAAQ,CACxB,OAAOqE,EAAYrE,CAAG,CACxB,CAAC,EACsB/E,EAAAA,IACrBoH,GACA/B,GAAcJ,GAAeA,GAAe,CAAA,EAAIiE,CAAY,EAAGE,CAAW,EAAG,CAC3E,aAAcjN,EACd,YAAA2L,EACA,YAAaY,EACb,KAAAhF,CACR,CAAO,CACP,CACE,EACA,OAAAyF,EAAc,YAAc,eAAerB,CAAW,GAC/CuB,EAAAA,WAAWF,CAAa,CACjC,CACA,SAASG,GAAY7F,EAAK,CAAE,MAAA2E,EAAO,UAAAmB,CAAS,EAAI,CAC9C,OAAAnD,EAAO3C,EAAK,aAAa,EAClB,kCAAoC4C,EAAkB,CAC3D,KAAM+B,EAAQA,EAAQmB,EAAY9F,EAAMA,CAC5C,CAAG,CACH,CAC2BuF,EACzB,UACAM,GACCpN,IAAW,CACV,MAAOA,EAAM,MACb,UAAWA,EAAM,WAAa,GAClC,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EACA,MAAMsN,GAAY/D,GAAW,CAC3B,MAAO,UACP,KAAM,qFACR,CAAC,EACD,SAASgE,GAAUhG,EAAK,CAAE,QAAAiG,EAAS,KAAAC,EAAM,UAAAJ,CAAS,EAAI,CACpD,MAAO,UAAYlD,EAAkB,CAAE,QAAAqD,EAAS,KAAMC,EAAOA,EAAOJ,EAAY9F,EAAMA,EAAK,CAC7F,CACA,MAAMmG,GAAmBZ,EACvB,QACAS,GACCvN,IAAW,CACV,QAASA,EAAM,QACf,KAAMA,EAAM,KACZ,UAAWA,EAAM,WAAa,GAClC,GACE,CACE,uBAAwB,GACxB,QAAS,CAAC2N,EAAGnB,IAAS,CACpB,OAAO,SAAS,KAAOA,CACzB,CACJ,CACA,EACMoB,GAAerE,GAAW,CAC9B,MAAO,UACP,KAAM,4IACR,CAAC,EAKD,SAASsE,GAAsBtG,EAAK,CAAE,MAAAuG,EAAO,YAAAC,EAAa,GAAAC,CAAE,EAAI,CAC9D,MAAO,uCAAyC7D,EAAkB,CAChE,KAAM5C,EACN,aAAcwG,GAAexG,EAC7B,OAAQuG,EACR,GAAAE,CACJ,CAAG,CACH,CACqClB,EACnC,oBACAe,GACC7N,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,YACnB,GAAIA,EAAM,EACd,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,SAASiO,GAAa1G,EAAK,CAAE,QAAA2G,GAAW,CACtC,OAAAhE,EAAO3C,EAAK,cAAc,EACnB,6CAA+C4C,EAAkB,CAAE,EAAG5C,EAAK,QAAA2G,CAAO,CAAE,CAC7F,CACA,MAAMC,GAAsBrB,EAC1B,WACAmB,GACCjO,IAAW,CAAE,QAASA,EAAM,OAAO,GACpC,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,SAASoO,IAAe,CACtB,MAAMC,EAAYC,EAAAA,OAAO,EAAK,EAC9BxL,OAAAA,EAAAA,UAAU,KACRuL,EAAU,QAAU,GACb,IAAM,CACXA,EAAU,QAAU,EACtB,GACC,CAAA,CAAE,EACEE,cAAY,IAAMF,EAAU,QAAS,CAAA,CAAE,CAChD,CACA,SAASG,GAAsBC,EAAI,CACjC,IAAIC,EAAKD,EAAI,CACX,SAAAnD,EAAYqD,GAAeA,EAC3B,UAAA9O,EACA,SAAA+O,EACA,IAAArH,CACJ,EAAMmH,EAAI3E,EAAOX,GAAUsF,EAAI,CAC3B,WACA,YACA,WACA,KACJ,CAAG,EACD,MAAML,EAAYD,GAAY,EACxB,CAAC/G,EAAOwH,CAAQ,EAAItM,EAAAA,SAAS,MAAM,EACnC,CAACuM,EAAWC,CAAY,EAAIxM,EAAAA,SAAS,EAAK,EAChDO,OAAAA,EAAAA,UAAU,IAAM,CACdiM,EAAa,EAAI,EACjBH,EAASrH,EAAMyH,GAAW,CACpBX,EAAS,IACXQ,EAASG,CAAM,EACfD,EAAa,EAAK,EAEtB,CAAC,CACH,EAAG,CAACxH,CAAG,CAAC,EACezD,EAAAA,IAAI,OAAQqF,GAAcJ,GAAe,CAAE,UAAW6D,GAAG,0BAA2B/M,CAAS,CAAC,EAAIkK,CAAI,EAAG,CAAE,SAAU,CAAC+E,GAAazH,IAAU,QAAUiE,EAASjE,CAAK,CAAC,CAAE,CAAC,CAClM,CACA,SAAS4H,GAAiBL,EAAU,CAClC,MAAMM,EAAclP,GAA0B8D,MAAI0K,GAAuBzF,GAAe,CAAE,SAAA6F,GAAY5O,CAAK,CAAC,EAC5G,OAAAkP,EAAW,YAAc,cAAcN,EAAS,IAAI,IAC7CM,CACT,CACA,SAASC,GAAsBC,EAAUC,EAAU,CACjD,MAAMC,EAAW,kCAAkCF,CAAQ,gCAC3DhI,GAAMkI,EAAU,CAACpM,EAAKkF,IAAS,CAC7BiH,EACE,CAACnM,GAAOkF,GAAQA,EAAK,WAAaA,EAAK,UAAU,WAAaA,EAAK,UAAU,WAAW,MAAQ,MACtG,CACE,CAAC,CACH,CAC2B6G,GAAiBE,EAAqB,EAKjE,SAASI,GAAWhI,EAAK,CAAE,MAAA2E,GAAS,CAClC,OAAAhC,EAAO3C,EAAK,YAAY,EACjB,8CAA8CA,CAAG,UAAU2E,CAAK,EACzE,CAC0BY,EACxB,SACAyC,GACCvP,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EACA,SAASwP,GAAoBJ,EAAUC,EAAU,CAE/CjI,GADY,8CAEJ+C,EAAkB,CACtB,IAAKiF,CACX,CAAK,EACD,CAAClM,EAAKkF,IAAS,CACbiH,EAASjH,GAAsB,MAAM,CACvC,CACJ,CACA,CACyB6G,GAAiBO,EAAmB,EAK7D,SAASC,GAAelI,EAAK,CAAE,MAAA2E,EAAO,YAAAwD,CAAW,EAAI,CACnD,OAAAxF,EAAO3C,EAAK,gBAAgB,EACrB,mCAAqC4C,EAAkB,CAC5D,IAAA5C,EACA,MAAA2E,EACA,YAAAwD,CACJ,CAAG,CACH,CAC8B5C,EAC5B,aACA2C,GACCzP,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,WACvB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EAKA,SAAS2P,GAASpI,EAAK,CAAE,MAAA2E,GAAS,CAChC,OAAAhC,EAAO3C,EAAK,UAAU,EACf,8CAAgD4C,EAAkB,CACvE,IAAA5C,EACA,KAAM2E,CACV,CAAG,CACH,CACwBY,EACtB,OACA6C,GACC3P,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,MAAM4P,GAAerG,GAAW,CAC9B,MAAO,UACP,KAAM,oRACR,CAAC,EACD,SAASsG,GAAatI,EAAK,CAAE,MAAA2E,EAAO,QAAA4D,EAAS,OAAAzG,CAAM,EAAI,CACrD,OAAAa,EAAO3C,EAAK,cAAc,EACnB,oCAAsC4C,EAAkB,CAAE,IAAA5C,EAAK,KAAM,OAAQ,MAAA2E,EAAO,QAAA4D,EAAS,OAAAzG,EAAQ,CAC9G,CACA,MAAM0G,GAAsBjD,EAC1B,WACA+C,GACA,CAAC,CAAE,MAAA3D,EAAO,QAAA4D,EAAS,OAAAzG,CAAM,KAAQ,CAAE,MAAA6C,EAAO,QAAA4D,EAAS,OAAAzG,IACnD,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAAS2G,GAAgBzI,EAAK,CAAE,MAAA2E,EAAO,YAAAwD,CAAW,EAAI,CACpD,OAAAxF,EAAO3C,EAAK,iBAAiB,EACtB,yCAA2C4C,EAAkB,CAClE,QAAS+B,EACT,MAAOwD,CACX,CAAG,CACH,CAC+B5C,EAC7B,cACAkD,GACChQ,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,WACvB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAASiQ,GAAW1I,EAAK,CAAE,MAAA2E,EAAO,YAAAwD,EAAa,SAAAQ,CAAQ,EAAI,CACzD,OAAAhG,EAAO3C,EAAK,YAAY,EACjB,gCAAkC4C,EAAkB,CACzD,IAAA5C,EACA,MAAA2E,EACA,YAAAwD,EACA,UAAWQ,CACf,CAAG,CACH,CAC0BpD,EACxB,SACAmD,GACCjQ,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,YACnB,SAAUA,EAAM,QACpB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAASmQ,GAAO5I,EAAK,CAAE,MAAA2E,EAAO,YAAAwD,EAAa,MAAAU,CAAK,EAAI,CAClD,OAAAlG,EAAO3C,EAAK,QAAQ,EACb,8BAAgC4C,EAAkB,CACvD,IAAA5C,EACA,MAAA2E,EACA,YAAAwD,EACA,SAAUU,CACd,CAAG,CACH,CACsBtD,EACpB,KACAqD,GACCnQ,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,YACnB,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EACA,SAASqQ,GAAgBjB,EAAUC,EAAU,CACtC,OAAO,KACV,OAAO,GAAK,CACV,MAAO,CACL,MAAO,SAAeiB,EAAQC,EAAQ,CACpC,IAAI9G,EAAIC,GACPA,GAAMD,EAAK,OAAO,GAAG,WAAW6G,CAAM,IAAM,MAAgB5G,EAAG,KAAKD,EAAI8G,CAAM,CACjF,CACR,EACM,UAAW,CAAA,CACjB,GAEE,MAAMhJ,EAAM,2BACNtB,EAAQ,OAAO,GAAG,UAAU,OAClC,cAAO,KAAO,CACZ,YAAYqK,EAAQjJ,EAAO,CACzB,IAAIoC,EAAIC,EACR,MAAM8G,EAAgBF,IAAW,GAAK,EAAI,SAASA,EAAO,QAAQ,eAAgB,EAAE,EAAG,EAAE,GACxF5G,GAAMD,EAAK,OAAO,GAAG,WAAW+G,CAAa,IAAM,MAAgB9G,EAAG,KAAKD,EAAIpC,IAAU,GAAK,OAAS,SAASA,EAAO,EAAE,CAAC,CAC7H,CACJ,EACE,OAAO,GAAG,UAAU,KAAKgI,CAAQ,EAC1BjI,GACLG,EAAM4C,EAAkB,CACtB,SAAU,UACV,IAAK,eAAelE,CAAK,GACzB,IAAKmJ,CACX,CAAK,CACL,CACA,CACqBH,GAAiBoB,EAAe,EAKrD,SAASI,GAAclJ,EAAK,CAAE,MAAAmJ,EAAO,YAAAhB,EAAa,MAAAiB,CAAK,EAAI,CACzD,OAAIA,EACK,6BAA6BA,CAAK,aAE3CzG,EAAO3C,EAAK,eAAe,EAC3B2C,EAAOwG,EAAO,iBAAiB,EACxB,2CAA6CvG,EAAkB,CACpE,IAAA5C,EACA,MAAAmJ,EACA,YAAAhB,CACJ,CAAG,EACH,CAC6B5C,EAC3B,YACA2D,GACCzQ,IAAW,CACV,MAAOA,EAAM,MACb,YAAaA,EAAM,YACnB,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,SAAS4Q,GAAuBxB,EAAUC,EAAU,CAElDjI,GADY,+CAEJ+C,EAAkB,CACtB,IAAKiF,CACX,CAAK,EACD,CAAClM,EAAKkF,IAAS,CACbiH,EAASjH,EAAOA,EAAK,MAAQ,MAAM,CACrC,CACJ,CACA,CAC4B6G,GAAiB2B,EAAsB,EAKnE,SAASC,GAAWtJ,EAAK,CAAE,MAAA2E,GAAS,CAClC,OAAAhC,EAAO3C,EAAK,YAAY,EACjB,6BAA+B4C,EAAkB,CACtD,IAAA5C,EACA,MAAA2E,CACJ,CAAG,CACH,CAC0BY,EACxB,SACA+D,GACC7Q,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAAS8Q,GAAWvJ,EAAK,CAAE,MAAA2E,GAAS,CAClC,OAAAhC,EAAO3C,EAAK,YAAY,EACjB,oCAAsC4C,EAAkB,CAC7D,IAAA5C,EACA,MAAA2E,CACJ,CAAG,CACH,CAC0BY,EACxB,SACAgE,GACC9Q,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EACA,SAAS+Q,GAAQxJ,EAAK,CAAE,MAAA2E,GAAS,CAC/B,OAAAhC,EAAO3C,EAAK,SAAS,EACd,0BAA4B4C,EAAkB,CACnD,IAAA5C,EACA,KAAM2E,CACV,CAAG,CACH,CACuBY,EACrB,MACAiE,GACC/Q,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EAKA,SAASgR,GAAoB5B,EAAUC,EAAU,CAC/C,MAAMC,EAAW,oDAAoDF,CAAQ,GAC7EhI,GAAMkI,EAAU,CAAE,MAAO,OAAO,EAAI,CAACpM,EAAKF,IAAa,CACrDqM,EACE,CAACnM,GAAOF,GAAYA,EAAS,MAAQA,EAAS,KAAK,SAAS,OAAS,GAAKA,EAAS,KAAK,SAAS,CAAC,EAAE,KAAK,MAAQA,EAAS,KAAK,SAAS,CAAC,EAAE,KAAK,MAAQ,MAC9J,CACE,CAAC,CACH,CACyBiM,GAAiB+B,EAAmB,EAK7D,SAASC,GAAa1J,EAAK,CAAE,MAAA2E,GAAS,CACpC,OAAAhC,EAAO3C,EAAK,cAAc,EACnB,gCAAkC4C,EAAkB,CACzD,IAAA5C,EACA,KAAM2E,CACV,CAAG,CACH,CAC4BY,EAC1B,WACAmE,GACCjR,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAASkR,GAAY3J,EAAK,CAAE,MAAA2E,GAAS,CACnC,OAAAhC,EAAO3C,EAAK,aAAa,EAClB,kCAAoC4C,EAAkB,CAC3D,IAAA5C,EACA,KAAM2E,CACV,CAAG,CACH,CAC2BY,EACzB,UACAoE,GACClR,IAAW,CACV,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAASmR,GAAW5J,EAAK,CACvB,MAAA2E,EACA,QAAAkF,EACA,KAAAC,EACA,SAAAC,CACF,EAAG,CACD,OAAApH,EAAO3C,EAAK,YAAY,EACjB,4CAA8C4C,EAAkB,CACrE,aAAc5C,EACd,MAAA2E,EACA,QAAAkF,EACA,KAAAC,EACA,SAAAC,CACJ,CAAG,CACH,CAC0BxE,EACxB,SACAqE,GACCnR,IAAW,CACV,MAAOA,EAAM,MACb,MAAOA,EAAM,MAAQ,CAAA,GAAI,KAAK,GAAG,EACjC,QAASA,EAAM,QACf,SAAUA,EAAM,UAAY,MAChC,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,SAASuR,GAAoBnC,EAAUC,EAAU,CAE/C,OAAOjI,GADU,wCAEJ+C,EAAkB,CAC3B,IAAKiF,CACX,CAAK,EACD,CAAClM,EAAKkF,IAAS,CACbiH,EAAS,CAACnM,GAAOkF,GAAQA,EAAK,SAAWA,EAAK,SAAS,WAAa,MAAM,CAC5E,CACJ,CACA,CACyB6G,GAAiBsC,EAAmB,EAC7D,MAAMC,GAAcjI,GAAW,CAC7B,MAAO,UACP,KAAM,+eACR,CAAC,EACD,SAASkI,GAAYlK,EAAK,CACxB,MAAA2E,EACA,IAAAwF,EACA,SAAAC,EAAW,CAAA,EACX,QAAAC,EAAU,CAAA,CACZ,EAAG,CACD,OAAA1H,EAAO3C,EAAK,aAAa,EACzB2C,EAAO,MAAM,QAAQyH,CAAQ,EAAG,kCAAkC,EAClEzH,EAAO,MAAM,QAAQ0H,CAAO,EAAG,iCAAiC,EACzD,mCAAqCzH,EAAkB,CAC5D,IAAA5C,EACA,KAAM2E,EACN,IAAAwF,EACA,SAAUC,EAAS,OAAS,EAAIA,EAAS,KAAK,GAAG,EAAI,OACrD,QAASC,EAAQ,OAAS,EAAIA,EAAQ,KAAK,GAAG,EAAI,MACtD,CAAG,CACH,CACA,MAAMC,GAAqB/E,EACzB,UACA2E,GACCzR,IAAW,CACV,SAAUA,EAAM,SAChB,MAAOA,EAAM,MACb,IAAKA,EAAM,IACX,QAASA,EAAM,OACnB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAAS8R,GAAUvK,EAAK,CAAE,MAAA2E,EAAO,UAAAmB,CAAS,EAAI,CAC5C,OAAAnD,EAAO3C,EAAK,WAAW,EAChB,kBAAoB4C,EAAkB,CAC3C,KAAM+B,EAAQA,EAAQmB,EAAY9F,EAAMA,CAC5C,CAAG,CACH,CACyBuF,EACvB,QACAgF,GACC9R,IAAW,CACV,MAAOA,EAAM,MACb,UAAWA,EAAM,WAAa,GAClC,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAAS+R,GAAOxK,EAAK,CAAE,MAAA2E,EAAO,MAAAkE,EAAO,QAAA4B,EAAS,UAAAC,GAAa,CACzD,OAAA/H,EAAO3C,EAAK,QAAQ,EACb,2BAA6B4C,EAAkB,CACpD,IAAA5C,EACA,MAAA2E,EACA,MAAAkE,EACA,QAAS4B,EAAU,EAAI,EACvB,YAAaC,EAAY,EAAI,CACjC,CAAG,CACH,CACsBnF,EACpB,KACAiF,GACC/R,IAAW,CACV,MAAOA,EAAM,MACb,MAAOA,EAAM,MACb,QAASA,EAAM,QACf,UAAWA,EAAM,SACrB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EACA,SAASkS,GAAgB9C,EAAUC,EAAU,CACtC,OAAO,KAAI,OAAO,GAAK,CAAA,GAC5B,OAAO,GAAG,MAAQ,CAChB,MAAO,CAACiB,EAAQjJ,IAAU,CACxB,IAAIoC,EAAIC,EACR,OAAQA,GAAMD,EAAK,OAAO,GAAG,YAAc,KAAO,OAASA,EAAG6G,CAAM,IAAM,KAAO,OAAS5G,EAAG,KAAKD,EAAIpC,CAAK,CAC7G,CACJ,EACE,OAAO,GAAG,UAAY,CAAA,EACtB,MAAME,EAAM,2BACNtB,EAAQ,OAAO,GAAG,UAAU,OAClC,cAAO,GAAG,UAAU,KAAKoJ,CAAQ,EAC1BjI,GACLG,EAAM4C,EAAkB,CACtB,IAAK,QACL,MAAAlE,EACA,IAAKmJ,CACX,CAAK,CACL,CACA,CACqBH,GAAiBiD,EAAe,EACrD,MAAMC,GAAY5I,GAAW,CAC3B,MAAO,UACP,KAAM,0hGACR,CAAC,EACD,SAAS6I,GAAU7K,EAAK,CAAE,MAAA2E,EAAO,MAAAkE,CAAK,EAAI,CACxC,OAAAlG,EAAO3C,EAAK,WAAW,EAChB,2CAA6C4C,EAAkB,CACpE,IAAA5C,EACA,MAAA2E,EACA,IAAKkE,CACT,CAAG,CACH,CACA,MAAMiC,GAAmBvF,EACvB,QACAsF,GACCpS,IAAW,CACV,MAAOA,EAAM,MACb,MAAOA,EAAM,KACjB,GACE,CACE,YAAa,IACb,aAAc,IACd,eAAgB,cACpB,CACA,EAKA,SAASsS,IAAmB,CAC1B,MAAO,gCAAgC,KAAK,UAAU,SAAS,CACjE,CACA,SAASC,GAAahL,EAAK,CAAE,MAAA2E,EAAO,UAAAmB,CAAS,EAAI,CAC/C,OAAAnD,EAAO3C,EAAK,cAAc,EACnB,YAAc+K,KAAqB,MAAQ,OAAS,qBAAuBnI,EAAkB,CAClG,KAAM+B,EAAQA,EAAQmB,EAAY9F,EAAMA,CAC5C,CAAG,CACH,CAC4BuF,EAC1B,WACAyF,GACCvS,IAAW,CACV,MAAOA,EAAM,MACb,UAAWA,EAAM,WAAa,GAClC,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,EAKA,SAASwS,GAAcjL,EAAK,CAAE,MAAAkL,EAAO,QAAAvE,CAAO,EAAI,CAC9C,OAAAhE,EAAO3C,EAAK,eAAe,EACpB,uCAAyC4C,EAAkB,CAChE,EAAG5C,EACH,MAAAkL,EACA,QAAAvE,CACJ,CAAG,CACH,CAC6BpB,EAC3B,YACA0F,GACCxS,IAAW,CACV,MAAOA,EAAM,MACb,QAASA,EAAM,OACnB,GACE,CACE,YAAa,IACb,aAAc,GAClB,CACA,ECn7BO,MAAM0S,GAA8C,CAAC,CACxD,SAAAtD,EACA,MAAAlD,EACA,YAAAwD,EAAc,GACd,UAAA7P,EAAY,EAChB,IAAM,CACF,KAAM,CAAE,EAAAsC,CAAA,EAAMC,GAAA,EACR,CAACuQ,EAAQC,CAAS,EAAIrQ,EAAAA,SAAS,EAAK,EACpCsQ,EAAevE,EAAAA,OAAyB,IAAI,EAE5CwE,EAAiB,MAAO7H,GAAyB,CACnDA,GAAG,eAAA,EACHA,GAAG,gBAAA,EAEH,GAAI,CACI,UAAU,UACV,MAAM,UAAU,UAAU,UAAU8H,CAAgB,EAGhDF,EAAa,UACbA,EAAa,QAAQ,OAAA,EACrB,SAAS,YAAY,MAAM,GAGnCD,EAAU,EAAI,EACdI,GAAY7Q,EAAE,qBAAqB,CAAC,EAGpC,WAAW,IAAM,CACbyQ,EAAU,EAAK,CACnB,EAAG,GAAI,CACX,OAAS1P,EAAK,CACV,QAAQ,MAAM,uBAAwBA,CAAG,EACzCO,EAAUtB,EAAE,kBAAkB,CAAC,CACnC,CACJ,EAGM8Q,EAAoB,SAAY,CAClC,GAAI,UAAU,MACV,GAAI,CACA,aAAM,UAAU,MAAM,CAClB,MAAA/G,EACA,KAAMwD,EACN,IAAKqD,CAAA,CACR,EACM,EACX,OAAS7P,EAAK,CACV,QAAQ,IAAI,oCAAqCA,CAAG,CACxD,CAEJ,MAAO,EACX,EAUM6P,GAPkBxL,GAChBA,EAAI,WAAW,MAAM,EACdA,EAEJ,GAAG,OAAO,SAAS,MAAM,GAAGA,EAAI,WAAW,GAAG,EAAIA,EAAM,IAAMA,CAAG,IAGpC6H,CAAQ,EAE1C8D,EAAeC,GAAM,WAGzB,CAAC,CAAE,QAAAtH,CAAA,EAAW5L,IACZ6D,EAAAA,IAACD,EAAA,CACG,IAAA5D,EACA,QAAQ,QACR,UAAW,6BAA6BJ,CAAS,GACjD,QAAS,MAAMoL,GAAK,CAGhB,GADiB,OAAO,YAAc,IACxB,CACV,MAAMgI,EAAA,EACN,MACJ,CACApH,EAAQZ,CAAC,CACb,EACA,MAAO9I,EAAE,iBAAiB,EAE1B,SAAA2B,EAAAA,IAAC,IAAA,CAAE,UAAU,oBAAA,CAAqB,CAAA,CAAA,CAEzC,EAED,cACKsP,GAAA,CACG,SAAA,CAAAtP,EAAAA,IAACsP,GAAS,OAAT,CAAgB,GAAIF,CAAA,CAAc,EAEnCtP,EAAAA,KAACwP,GAAS,KAAT,CACG,UAAU,qBACV,MAAO,CACH,SAAU,QACV,aAAc,OACd,QAAS,OACT,UAAW,KAAA,EAIf,SAAA,CAAAtP,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAAC,UAAQ,SAAA3B,EAAE,iBAAiB,EAAE,CAAA,CAClC,EAGAyB,EAAAA,KAAC,MAAA,CAAI,UAAU,OACX,SAAA,CAAAE,MAAC,QAAA,CAAM,UAAU,oCACZ,SAAA3B,EAAE,mBAAmB,EAC1B,EACAyB,EAAAA,KAACpD,GAAA,CAAW,KAAK,KACb,SAAA,CAAAsD,EAAAA,IAACuP,GAAA,CACG,IAAKR,EACL,KAAK,OACL,MAAOE,EACP,SAAQ,GACR,MAAO,CACH,gBAAiB,UACjB,OAAQ,oBACR,SAAU,MAAA,CACd,CAAA,EAEJjP,EAAAA,IAACD,EAAA,CACG,QAAS8O,EAAS,YAAc,oBAChC,KAAK,KACL,QAASG,EACT,SAAUH,EACV,MAAO,CACH,SAAU,OACV,QAAS,SAAA,EAGZ,SAAAA,QACI,IAAA,CAAE,UAAU,eAAe,EAE5B7O,EAAAA,IAAC,IAAA,CAAE,UAAU,iBAAA,CAAkB,CAAA,CAAA,CAEvC,CAAA,CACJ,CAAA,EACJ,SAGC,MAAA,CACG,SAAA,CAAAA,MAAC,QAAA,CAAM,UAAU,oCACZ,SAAA3B,EAAE,mBAAmB,EAC1B,EACAyB,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACX,SAAA,CAAAE,EAAAA,IAACqK,GAAA,CACG,IAAK4E,EACL,QAAQ,WACR,UAAU,YAEV,SAAAjP,EAAAA,IAAC,MAAA,CAAI,UAAU,cACX,SAAAA,EAAAA,IAAC8J,IAAa,KAAM,GAAI,MAAK,EAAA,CAAC,CAAA,CAClC,CAAA,CAAA,EAGJ9J,EAAAA,IAAC+N,GAAA,CACG,IAAKkB,EACL,MAAA7G,EACA,UAAU,YAEV,SAAApI,EAAAA,IAAC0N,GAAA,CAAY,KAAM,GAAI,MAAK,EAAA,CAAC,CAAA,CAAA,EAGjC1N,EAAAA,IAACiM,GAAA,CACG,IAAKgD,EACL,MAAA7G,EACA,QAASwD,EACT,UAAU,YAEV,SAAA5L,EAAAA,IAAC8L,GAAA,CAAa,KAAM,GAAI,MAAK,EAAA,CAAC,CAAA,CAAA,EAGlC9L,EAAAA,IAACuO,GAAA,CACG,IAAKU,EACL,MAAO,GAAG7G,CAAK,IAAIwD,CAAW,GAC9B,UAAU,YAEV,SAAA5L,EAAAA,IAACqO,GAAA,CAAU,KAAM,GAAI,MAAK,EAAA,CAAC,CAAA,CAAA,EAG/BrO,EAAAA,IAAC4J,GAAA,CACG,IAAKqF,EACL,QAAS7G,EACT,KAAMwD,EACN,UAAU,YAEV,SAAA5L,EAAAA,IAACwJ,GAAA,CAAU,KAAM,GAAI,MAAK,EAAA,CAAC,CAAA,CAAA,CAC/B,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,CAAA,CAAA,CACJ,EACJ,CAER,ECzMMgG,GAAsB,iBASrB,SAASC,GAAU,CACtB,KAAAC,EACA,OAAAC,EACA,QAAAxR,EACA,cAAAyR,CACJ,EAAmB,CACf,KAAM,CAAE,EAAAvR,CAAA,EAAMC,GAAA,EACR,CAACuR,EAAcC,CAAe,EAAIrR,EAAAA,SAAsB,IAAI,EAC5D,CAAC0H,EAAS4J,CAAU,EAAItR,EAAAA,SAAiBJ,EAAE,wBAAwB,CAAC,EACpE,CAAC2R,EAAOC,CAAQ,EAAIxR,EAAAA,SAAiB,CAAA,CAAE,EACvC,CAACyR,EAAcC,CAAe,EAAI1R,EAAAA,SAAS,EAAK,EAChD,CAAC2R,EAAiBC,CAAkB,EAAI5R,EAAAA,SAAS,EAAK,EACtD,CAAC6R,EAAmBC,CAAoB,EAAI9R,EAAAA,SAAS,EAAK,EAC1D,CAAC+R,EAAWC,CAAY,EAAIhS,EAAAA,SAAwB,IAAI,EACxD,CAACiS,EAAiBC,CAAkB,EAAIlS,EAAAA,SAAS,EAAK,EACtDmS,EAAmBpG,EAAAA,OAAsB,IAAI,EAC7CqG,EAAqBrG,EAAAA,OAA8B,IAAI,EACvDsG,EAAsBtG,EAAAA,OAAsB,IAAI,EAChDuG,EAAoBvG,EAAAA,OAAe,CAAC,EACpCwG,GAAwBxG,EAAAA,OAAO,EAAK,EACpCyG,EAA0BzG,EAAAA,OAAO,EAAK,EACtC0G,EAAiB1G,EAAAA,OAAO,EAAK,EAE7B2G,EAAe3G,EAAAA,OAAoB,IAAI,EACvC4G,EAAkB5G,EAAAA,OAAe,EAAE,EAGnC6G,GAAUC,GAAA,EAGVC,EAAiB,CACnB,iBAAkB,IAClB,aAAc,IACd,QAAS,GAEb,EAGMC,EAAqB/G,cAAagH,GAA4B,CAChE,MAAMvK,EAAW,KAAK,IAClBqK,EAAe,iBAAmB,KAAK,IAAI,IAAKE,CAAO,EACvDF,EAAe,YAAA,EAEnB,OAAO,KAAK,MAAMrK,CAAQ,CAC9B,EAAG,CAAA,CAAE,EAGLlI,EAAAA,UAAU,IAAM,CACR0Q,GACAgC,EAAA,CAER,EAAG,CAAChC,CAAI,CAAC,EAGT1Q,EAAAA,UAAU,IACC,IAAM,CACL6R,EAAmB,UACRA,EAAmB,QAC1B,aAAaA,EAAmB,OAAO,GAO3CD,EAAiB,SAAW,CAACA,EAAiB,QAAQ,QACtDA,EAAiB,QAAQ,MAAA,CAEjC,EACD,CAAA,CAAE,EAGL,MAAMe,EAAclH,EAAAA,YAAY,IAAM,CAC9BoG,EAAmB,UACRA,EAAmB,QAC1B,aAAaA,EAAmB,OAAO,EAI3CA,EAAmB,QAAU,MAEjCC,EAAoB,QAAU,KAC9BC,EAAkB,QAAU,CAChC,EAAG,CAAA,CAAE,EAECa,GAAqBnH,EAAAA,YAAY,IAAM,CACrCmG,EAAiB,SAAW,CAACA,EAAiB,QAAQ,QACtDA,EAAiB,QAAQ,MAAA,EAE7BA,EAAiB,QAAU,IAC/B,EAAG,CAAA,CAAE,EAGCiB,EAAmBpH,EAAAA,YAAY,IAAM,CAEvCkH,EAAA,EAEApB,EAAqB,EAAK,EAC1BI,EAAmB,EAAK,EAEpBQ,EAAa,SACbrB,EAAgBqB,EAAa,OAAO,EAEpCC,EAAgB,SAChBrB,EAAWqB,EAAgB,OAAO,EAGtCQ,GAAA,EACAZ,GAAsB,QAAU,GAChCC,EAAwB,QAAU,GAClCC,EAAe,QAAU,EAC7B,EAAG,CAACU,GAAoBD,CAAW,CAAC,EAE9BG,GAAwBrH,EAAAA,YAAY,IAAM,CAC5C,GAAIuG,GAAsB,QACtB,OAEJA,GAAsB,QAAU,GAGhC,MAAMe,GADOZ,EAAa,SAAWtB,IAChB,QAAU,EACzBmC,EACFZ,EAAgB,SAAWjL,GAAW9H,EAAE,wBAAwB,EAEhEF,GACA,OAAO,cACH,IAAI,YAAY,qBAAsB,CAClC,OAAQ,CACJ,QAAAA,EACA,OAAA4T,EACA,QAASC,EACT,UAAW,KAAK,IAAA,CAAI,CACxB,CACH,CAAA,CAGb,EAAG,CAAC7L,EAAS0J,EAAcxR,EAAGF,CAAO,CAAC,EAEhC8T,GAA2BxH,EAAAA,YAAY,IAAM,CAC3CwG,EAAwB,UAG5BA,EAAwB,QAAU,GAClC/B,GAAY7Q,EAAE,mCAAmC,CAAC,EACtD,EAAG,CAACA,CAAC,CAAC,EAEA6T,GAAuBzH,EAAAA,YAAY,IAAM,CAC3CkH,EAAA,EACAC,GAAA,EACArB,EAAqB,EAAK,EAC1BI,EAAmB,EAAK,EACxBF,EAAa,IAAI,EACjBK,EAAoB,QAAU,KAC9BC,EAAkB,QAAU,EAC5Be,GAAA,EACAG,GAAA,EACAf,EAAe,QAAU,GAGzBiB,GAAa,CACT,OAAQ,UACR,SAAUhU,CAAA,CACb,EAEDwR,EAAA,CACJ,EAAG,CACCiC,GACAE,GACAnC,EACAsC,GACAN,EACAxT,CAAA,CACH,EAEKiU,EAAuB3H,EAAAA,YACxB7K,GAA0B,CAEvBuS,GAAa,CACT,OAAQ,UACR,SAAUhU,EACV,MAAOyB,CAAA,CACV,EAEGA,GACAD,EAAUC,CAAY,EAE1BiS,EAAA,CACJ,EACA,CAACA,EAAkB1T,CAAO,CAAA,EAIxBkU,EAAqB5H,EAAAA,YAAY,SAAY,CAC/C,GAAK+F,EAGL,IAAIM,EAAoB,SACJ,KAAK,IAAA,EAAQA,EAAoB,QACnCS,EAAe,QAEzB,GAAI,CAIA,MAAMjN,EAAO,MAHI,MAAM,MACnB,iBAAiBkM,CAAS,SAAA,GAEF,KAAA,EAE5B,GAAIlM,EAAK,SAAWA,EAAK,KAAM,CAC3B,MAAMgO,GAAShO,EAAK,KAAK,OAEzB,GAAIgO,KAAWC,GAAc,QAAS,CAElCZ,EAAA,EACAhB,EAAmB,EAAK,EACxBhR,EACItB,EAAE,0CAA0C,CAAA,EAEhDwT,EAAA,EACA,MACJ,SAAWS,KAAWC,GAAc,UAAW,CAC3CL,GAAA,EACA,MACJ,SACII,KAAWC,GAAc,WACzBD,KAAWC,GAAc,OAC3B,CACEH,EACIE,KAAWC,GAAc,UACnBlU,EAAE,mCAAmC,EACrCA,EAAE,gCAAgC,CAAA,EAE5C,MACJ,CACJ,CACJ,OAASmU,EAAO,CACZ,QAAQ,MAAM,iCAAkCA,CAAK,EACrDJ,EACI/T,EAAE,2CAA2C,CAAA,EAEjD,MACJ,CAKR,GAAI,CAEA,MAAMiG,EAAO,MADI,MAAM,MAAM,iBAAiBkM,CAAS,SAAS,GACpC,KAAA,EAE5B,GAAIlM,EAAK,SAAWA,EAAK,KAAM,CAC3B,MAAMgO,EAAShO,EAAK,KAAK,OAEzB,GAAIgO,IAAWC,GAAc,UAAW,CACpCL,GAAA,EACA,MACJ,SACII,IAAWC,GAAc,WACzBD,IAAWC,GAAc,OAC3B,CACEH,EACIE,IAAWC,GAAc,UACnBlU,EAAE,mCAAmC,EACrCA,EAAE,gCAAgC,CAAA,EAE5C,MACJ,CAEJ,CACJ,OAASmU,EAAO,CACZ,QAAQ,MAAM,iCAAkCA,CAAK,CAEzD,EACJ,EAAG,CACCJ,EACAF,GACA1B,EACAqB,EACAF,EACAtT,CAAA,CACH,EAEKqT,EAAa,SAAY,CAC3BvB,EAAgB,EAAI,EACpB,GAAI,CAEA,MAAM7L,EAAO,MADI,MAAM,MAAM,YAAY,GACb,KAAA,EAExBA,EAAK,QACL2L,EAAS3L,EAAK,IAAI,EAElB3E,EAAU2E,EAAK,OAASjG,EAAE,6BAA6B,CAAC,CAEhE,OAASe,EAAK,CACVO,EAAUtB,EAAE,kBAAkB,CAAC,EAC/B,QAAQ,MAAM,wBAAyBe,CAAG,CAC9C,QAAA,CACI+Q,EAAgB,EAAK,CACzB,CACJ,EAEMsC,EAAoBC,GAAe,CACrC5C,EAAgB4C,CAAI,CACxB,EAEMC,EAAc,IAAM,CAEtBhB,EAAA,EAEIf,EAAiB,SAAW,CAACA,EAAiB,QAAQ,SACtDA,EAAiB,QAAQ,MAAA,EACzBA,EAAiB,QAAU,MAG/Bd,EAAgB,IAAI,EACpBC,EAAW1R,EAAE,wBAAwB,CAAC,EACtCkS,EAAqB,EAAK,EAC1BE,EAAa,IAAI,EACjBE,EAAmB,EAAK,EACxBG,EAAoB,QAAU,KAC9BK,EAAa,QAAU,KACvBC,EAAgB,QAAU,GAC1BzB,EAAA,CACJ,EAGMiD,EAAyBnI,EAAAA,YAAY,IAAM,CAC7C,GAAI,CAAC+F,GAAaU,EAAe,QAAS,OAE1CA,EAAe,QAAU,GAEzBP,EAAmB,EAAI,EAEvBG,EAAoB,QAAU,KAAK,IAAA,EACnCC,EAAkB,QAAU,EAG5B,MAAM8B,EAAmB,IAAM,CAK3B,MAAM3L,EAAWsK,EAAmBT,EAAkB,OAAO,EAC7DA,EAAkB,SAAW,EAE7BF,EAAmB,QAAU,WAAW,IAAM,CAC1CwB,EAAA,EAAqB,QAAQ,IAAM,CAE3BxB,EAAmB,SACnBgC,EAAA,CAER,CAAC,CACL,EAAG3L,CAAQ,CACf,EAGAmL,EAAA,EAAqB,QAAQ,IAAM,CAG/BQ,EAAA,CACJ,CAAC,CACL,EAAG,CAACrC,EAAWgB,EAAoBa,CAAkB,CAAC,EAGtDrT,EAAAA,UAAU,IAAM,CACZ,MAAM8T,EAAY,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACtDC,EAAiBD,EAAU,IAAI,iBAAiB,EAChDE,EAAmBF,EAAU,IAAI,mBAAmB,EACpDG,GAAeH,EAAU,IAAI,eAAe,EAC5CI,EAAeJ,EAAU,IAAI,YAAY,EAGzCK,GAAW,IAAM,CACnB,MAAM1P,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EACxCA,EAAI,aAAa,OAAO,iBAAiB,EACzCA,EAAI,aAAa,OAAO,mBAAmB,EAC3CA,EAAI,aAAa,OAAO,eAAe,EACvCA,EAAI,aAAa,OAAO,YAAY,EACpCA,EAAI,aAAa,OAAO,eAAe,EACvC,OAAO,QAAQ,aAAa,CAAA,EAAI,GAAIA,EAAI,UAAU,CACtD,EAEA,GAAIsP,IAAmB,KAAOG,EAE1BzC,EAAa,SAASyC,CAAY,CAAC,EACnCC,GAAA,EAEA,WAAW,IAAM,CACbP,EAAA,CACJ,EAAG,GAAG,UACCI,IAAqB,IAE5BG,GAAA,EACAxT,EAAUtB,EAAE,mCAAmC,CAAC,EAGhD8T,GAAa,CACT,OAAQ,SACR,SAAUhU,CAAA,CACb,UACM8U,KAAiB,IAAK,CAE7B,MAAMrT,EAAekT,EAAU,IAAI,eAAe,EAClDK,GAAA,EACAxT,EACIC,EACM,mBAAmBA,CAAY,EAC/BvB,EAAE,gCAAgC,CAAA,EAI5C8T,GAAa,CACT,OAAQ,UACR,SAAUhU,EACV,MAAOyB,GAAgB,eAAA,CAC1B,CACL,CACJ,EAAG,CAACgT,EAAwBvU,CAAC,CAAC,EAE9B,MAAM+U,EAAiB,SAAY,CAC/B,GAAI,CAACvD,EAAc,OAEnBQ,EAAmB,EAAI,EAGvB,IAAIgD,EAA+B,KAEnC,GAAI,CAAChC,KAGDgC,EAAgB,OAAO,KACnB,cACA,SACA,sBAAA,EAGA,CAACA,GAAe,CAEhB1T,EAAUtB,EAAE,6BAA6B,CAAC,EAC1CgS,EAAmB,EAAK,EACxB,MACJ,CAIAgD,IACAA,EAAc,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMhBhV,EAAE,+BAA+B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAsDjCA,EAAE,iCAAiC,CAAC;AAAA,yBACrCA,EAAE,qCAAqC,CAAC;AAAA;AAAA;AAAA;AAAA,SAIxD,EAEGuS,EAAiB,QAAUyC,GAI/BlC,EAAa,QAAUtB,EACvBuB,EAAgB,QAAUjL,EAC1B6K,GAAsB,QAAU,GAChCC,EAAwB,QAAU,GAClCC,EAAe,QAAU,GAGzBiB,GAAa,CACT,OAAQ,QACR,SAAUhU,CAAA,CACb,EAED,GAAI,CAiBA,MAAMmV,EAAe,MAfI,MAAM,MAAM,iBAAkB,CACnD,OAAQ,OACR,QAAS,CACL,eAAgB,kBAAA,EAEpB,KAAM,KAAK,UAAU,CACjB,QAAAnV,EACA,cAAAyR,EACA,OAAQC,EAAa,GACrB,OAAQA,EAAa,OACrB,QAAA1J,CAAA,CAEH,CAAA,CACJ,GAE2C,KAAA,EAE5C,GAAI,CAACmN,EAAa,QACd,MAAM,IAAI,MACNA,EAAa,SACTA,EAAa,OACbjV,EAAE,+BAA+B,CAAA,EA6B7C,MAAMkV,EAAc,MAxBI,MAAM,MAAM,6BAA8B,CAC9D,OAAQ,OACR,QAAS,CACL,eAAgB,kBAAA,EAEpB,KAAM,KAAK,UAAU,CACjB,OAAQ1D,EAAa,OACrB,SAAU,MACV,YAAaxR,EAAE,6BAA8B,CACzC,WAAYwR,EAAa,KACzB,QAAA1J,CAAA,CACH,EACD,KAAMqN,GAAY,SAClB,SAAU,CACN,WAAYF,EAAa,KAAK,GAC9B,QAAAnV,EACA,cAAAyR,EACA,OAAQC,EAAa,GACrB,WAAYA,EAAa,OACzB,QAAA1J,CAAA,CACJ,CACH,CAAA,CACJ,GAEyC,KAAA,EAE1C,GAAI,CAACoN,EAAY,QACb,MAAM,IAAI,MACNA,EAAY,SACRA,EAAY,OACZlV,EAAE,+BAA+B,CAAA,EAI7C,MAAMmS,GAAY+C,EAAY,KAAK,UAGnC9C,EAAaD,EAAS,EAGtB,IAAIiD,EAA4B,KAChC,GAAIF,EAAY,KAAK,YAEjBE,EAAaF,EAAY,KAAK,oBACvBA,EAAY,KAAK,YAExBE,EAAaF,EAAY,KAAK,gBAG9B,OAAM,IAAI,MACNA,EAAY,SACRA,EAAY,OACZlV,EAAE,+BAA+B,CAAA,EAK7C,GAAIoV,EACA,GAAIpC,GAAS,CAET,aAAa,QACT7B,GACA,KAAK,UAAU,CACX,QAAArR,EACA,OAAQ0R,EAAa,GACrB,QAAA1J,EACA,UAAAqK,GACA,UAAW,OAAO,SAAS,IAAA,CAC9B,CAAA,EAGL,OAAO,SAAS,KAAOiD,EACvB,MACJ,MAAWJ,GAAiB,CAACA,EAAc,SAEvCA,EAAc,SAAS,KAAOI,GAKtCpD,EAAmB,EAAK,EACxBE,EAAqB,EAAI,CAC7B,OAASnR,EAAK,CAEN,CAACiS,IAAWgC,GAAiB,CAACA,EAAc,QAC5CA,EAAc,MAAA,EAElBzC,EAAiB,QAAU,KAE3B,IAAIhR,EAAe,GAGfR,aAAe,MACfQ,EAAeR,EAAI,QAEnB,OAAOA,GAAQ,UACfA,IAAQ,MACR,UAAWA,EAGXQ,EAAgBR,EAA0B,MAE1CQ,EAAevB,EAAE,+BAA+B,EAIpDsB,EAAUC,CAAY,EACtB,QAAQ,MAAM,2BAA4BR,CAAG,EAC7CiR,EAAmB,EAAK,CAC5B,CACJ,EAGArR,OAAAA,EAAAA,UAAU,IAAM,CACZ,MAAM0U,EAAiBjL,GAAwB,CAC3C,GAAIA,EAAM,SAAW,OAAO,SAAS,OACjC,OAGJ,KAAM,CAAE,KAAAhI,EAAM,QAAA0F,GAAS,UAAAwN,CAAA,EAAclL,EAAM,KAE3C,GAAIkL,GACY,KAAK,IAAA,EAAQA,EACf,IAAe,CACrB,QAAQ,KAAK,6BAA8BlT,CAAI,EAC/C,MACJ,CAGAA,IAAS,qBACTkR,EAAA,EACAhB,EAAmB,EAAK,EACxBJ,EAAqB,EAAK,EAC1B5Q,EAAUtB,EAAE,mCAAmC,CAAC,EAGhD8T,GAAa,CACT,OAAQ,SACR,SAAUhU,CAAA,CACb,EAED0T,EAAA,GACOpR,IAAS,iBAChBkR,EAAA,EACAhB,EAAmB,EAAK,EACxBJ,EAAqB,EAAK,EAC1B5Q,EAAUwG,IAAW9H,EAAE,gCAAgC,CAAC,EAGxD8T,GAAa,CACT,OAAQ,UACR,SAAUhU,EACV,MAAOgI,IAAW,eAAA,CACrB,EAED0L,EAAA,GACOpR,IAAS,mBAChBmS,EAAA,CAER,EAEA,cAAO,iBAAiB,UAAWc,CAAa,EACzC,IAAM,OAAO,oBAAoB,UAAWA,CAAa,CACpE,EAAG,CAAC/B,EAAaE,EAAkBxT,EAAGuU,CAAsB,CAAC,EAGzD9S,EAAAA,KAAA8T,WAAA,CAEI,SAAA,CAAA9T,OAAC+T,GAAM,KAAMvD,EAAmB,OAAQqC,EAAa,SAAQ,GACzD,SAAA,CAAA3S,EAAAA,IAAC6T,EAAM,OAAN,CAAa,YAAW,GACrB,SAAA7T,MAAC6T,EAAM,MAAN,CAAY,GAAG,KACX,SAAAxV,EAAE,6BAA6B,EACpC,EACJ,EACAyB,EAAAA,KAAC+T,EAAM,KAAN,CAAW,UAAU,OAClB,SAAA,CAAA7T,MAAC,KAAA,CAAG,UAAU,OACT,SAAA3B,EAAE,8BAA8B,EACrC,QACC,IAAA,CAAE,UAAU,OACR,SAAAA,EAAE,mCAAmC,CAAA,CAC1C,CAAA,EACJ,EACAyB,EAAAA,KAAC+T,EAAM,OAAN,CACG,SAAA,CAAA7T,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,uBACV,QAAS8R,EAER,WAAE,kCAAkC,CAAA,CAAA,EAEzC7R,EAAAA,IAACD,EAAA,CACG,QAAQ,UACR,QAAS6S,EACT,SAAUlC,EAET,WACG5Q,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC8T,GAAA,CACG,GAAG,OACH,UAAU,SACV,KAAK,KACL,KAAK,SACL,cAAY,OACZ,UAAU,MAAA,CAAA,EAEbzV,EAAE,gCAAgC,CAAA,CAAA,CACvC,EAEAA,EAAE,iCAAiC,CAAA,CAAA,CAE3C,CAAA,CACJ,CAAA,EACJ,EAGAyB,EAAAA,KAAC+T,EAAA,CACG,KAAMnE,GAAQ,CAACY,EACf,OAAQqC,EACR,SAAQ,GAER,SAAA,CAAA3S,EAAAA,IAAC6T,EAAM,OAAN,CAAa,YAAW,GACrB,SAAA7T,MAAC6T,EAAM,MAAN,CAAY,GAAG,KAAM,SAAAxV,EAAE,eAAe,EAAE,EAC7C,EACAyB,EAAAA,KAAC+T,EAAM,KAAN,CAEI,SAAA,CAAA3D,EACGpQ,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACX,SAAA,CAAAE,EAAAA,IAAC8T,GAAA,CAAQ,UAAU,SAAS,QAAQ,UAAU,QAC7C,MAAA,CAAI,UAAU,kBACV,SAAAzV,EAAE,iBAAiB,CAAA,CACxB,CAAA,CAAA,CACJ,EAEA2B,EAAAA,IAAC+T,GAAA,CAAI,UAAU,WACV,SAAA/D,EAAM,IAAI0C,GAAQ,CACf,MAAMsB,EACFhU,EAAAA,IAACiU,GAAA,CAAQ,GAAI,gBAAgBvB,EAAK,EAAE,GAC/B,SAAAA,EAAK,iBACFA,EAAK,YACb,EAGJ,OACI1S,EAAAA,IAACkU,GAAA,CAAkB,GAAI,EACnB,SAAAlU,EAAAA,IAACmU,GAAA,CACG,UAAU,MACV,QAASH,EACT,MAAO,CACH,KAAM,IACN,KAAM,GAAA,EAGV,SAAAlU,EAAAA,KAAC,MAAA,CACG,UAAW,mCAAmC+P,GAAc,KAAO6C,EAAK,GAAK,oBAAsB,EAAE,GACrG,QAAS,IACLD,EAAiBC,CAAI,EAEzB,MAAO,CACH,OAAQ,UACR,WAAY,eAAA,EAEhB,aAAcvL,GAAK,CACfA,EAAE,cAAc,MAAM,UAClB,aACR,EACA,aAAcA,GAAK,CACfA,EAAE,cAAc,MAAM,UAClB,UACR,EAEA,SAAA,CAAAnH,EAAAA,IAAC,MAAA,CACG,UAAU,OACV,MAAO,CACH,SAAU,MAAA,EAGb,SAAA0S,EAAK,KAAA,CAAA,EAEV5S,EAAAA,KAAC,MAAA,CAAI,UAAU,YAAY,SAAA,CAAA,IACrB4S,EAAK,MAAA,CAAA,CACX,CAAA,CAAA,CAAA,CACJ,CAAA,CACJ,EAvCMA,EAAK,EAwCf,CAER,CAAC,CAAA,CACL,EAIJ5S,EAAAA,KAACsU,GAAK,MAAL,CACG,SAAA,CAAApU,MAACoU,GAAK,MAAL,CAAW,UAAU,mBACjB,SAAA/V,EAAE,sBAAsB,EAC7B,EACA2B,EAAAA,IAACoU,GAAK,QAAL,CACG,KAAK,OACL,YAAa/V,EAAE,wBAAwB,EACvC,MAAO8H,EACP,SAAUgB,GAAK4I,EAAW5I,EAAE,OAAO,KAAK,EACxC,UAAW,GAAA,CAAA,EAEfnH,MAACoU,GAAK,KAAL,CAAU,UAAU,aAChB,SAAA/V,EAAE,qBAAqB,CAAA,CAC5B,CAAA,CAAA,CACJ,CAAA,EACJ,EACA2B,EAAAA,IAAC6T,EAAM,OAAN,CACI,SAAAhE,EACG7P,EAAAA,IAACD,EAAA,CACG,QAAQ,UACR,QAASqT,EACT,SAAUhD,EAET,WACGtQ,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC8T,GAAA,CACG,GAAG,OACH,UAAU,SACV,KAAK,KACL,KAAK,SACL,cAAY,OACZ,UAAU,MAAA,CAAA,EAEbzV,EAAE,oBAAoB,CAAA,CAAA,CAC3B,EAEA,GAAGA,EAAE,sBAAsB,CAAC,KAAKwR,EAAa,MAAM,EAAA,CAAA,EAI5D7P,MAACD,EAAA,CAAO,QAAQ,YAAY,SAAQ,GAC/B,SAAA1B,EAAE,oBAAoB,CAAA,CAC3B,CAAA,CAER,CAAA,CAAA,CAAA,CACJ,EACJ,CAER,CCj5BO,SAASgW,GAAuB,CACnC,QAAAC,CACJ,EAAgC,CAI5B,GAAI,EAFsBA,EAAQ,UAAU,OAAS,YAGjD,OAAO,KAGX,MAAMC,EAAaD,EAAQ,UAAU,YAAc,EAEnD,OACItU,EAAAA,IAACwU,GAAA,CAAM,GAAG,UAAU,KAAI,GAAC,KAAK,OAAO,UAAU,OAC3C,SAAA1U,EAAAA,KAAC,OAAA,CAAK,UAAU,UAAU,SAAA,CAAA,IAAEyU,CAAA,CAAA,CAAW,CAAA,CAC3C,CAER,CCZO,SAASE,GAAqB,CACjC,MAAAC,EACA,QAAAhW,EACA,MAAA8T,EACA,cAAApU,EACA,gBAAAuW,CACJ,EAA8B,CAC1B,KAAM,CAAE,EAAAtW,CAAA,EAAMC,GAAA,EAEd,OAAII,EAEIsB,EAAAA,IAAC,MAAA,CACG,UAAU,mEACV,MAAO,CAAE,YAAa,OAAQ,UAAW,OAAA,EAEzC,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,iBAAiB,KAAK,SACjC,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAU,kBACX,SAAA3B,EAAE,mBAAmB,CAAA,CAC1B,EACJ,QACC,IAAA,CAAE,UAAU,OAAQ,SAAAA,EAAE,qBAAqB,CAAA,CAAE,CAAA,CAAA,CAClD,CAAA,CAAA,EAKRmU,GAAS,CAACkC,EAEN1U,EAAAA,IAAC,MAAA,CACG,UAAU,qEACV,MAAO,CAAE,YAAa,OAAQ,UAAW,OAAA,EAEzC,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACX,SAAA,CAAAE,EAAAA,IAAC,KAAA,CAAI,SAAA3B,EAAE,4BAA4B,CAAA,CAAE,EACrC2B,EAAAA,IAAC,IAAA,CAAG,SAAAwS,GAASnU,EAAE,wBAAwB,CAAA,CAAE,CAAA,CAAA,CAC7C,CAAA,CAAA,EAMR2B,EAAAA,IAAC4U,GAAA,CACG,QAASF,EAAM,GACf,SAAUA,EAAM,SAChB,MAAOA,EAAM,MACb,OAAQA,EAAM,OACd,cAAeA,EAAM,cACrB,OAAQA,EAAM,eAAe,MAC7B,cAAAtW,EACA,gBAAAuW,EACA,aAAcD,EAAM,aACpB,eAAgBA,EAAM,eACtB,MAAOA,EAAM,KAAA,CAAA,CAGzB,CCtDO,MAAMG,GAA4C,CAAC,CACtD,KAAAnF,EACA,MAAAtH,EAAQ,OACR,QAAAjC,EACA,YAAA2O,EAAc,KACd,WAAAC,EAAa,KACb,QAAAC,EAAU,SACV,UAAAC,EACA,SAAAC,CACJ,WAESrB,EAAA,CAAM,KAAAnE,EAAY,OAAQwF,EAAU,SAAQ,GACzC,SAAA,CAAAlV,EAAAA,IAAC6T,EAAM,OAAN,CAAa,YAAW,GACrB,eAACA,EAAM,MAAN,CAAa,SAAAzL,CAAA,CAAM,CAAA,CACxB,EACApI,EAAAA,IAAC6T,EAAM,KAAN,CACG,eAAC,IAAA,CAAE,UAAU,OAAQ,SAAA1N,CAAA,CAAQ,CAAA,CACjC,EACArG,EAAAA,KAAC+T,EAAM,OAAN,CACG,SAAA,CAAA7T,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,uBACV,QAASmV,EAER,SAAAH,CAAA,CAAA,EAEL/U,EAAAA,IAACD,EAAA,CACG,QAAAiV,EACA,QAAS,IAAM,CACXC,EAAA,EACAC,EAAA,CACJ,EAEC,SAAAJ,CAAA,CAAA,CACL,CAAA,CACJ,CAAA,EACJ,EClCD,SAASK,GAAY,CAAE,KAAAzF,EAAM,OAAAC,EAAQ,QAAAxR,GAA6B,CACrE,KAAM,CAAE,EAAAE,CAAA,EAAMC,GAAA,EACR,CAAC8W,EAASC,CAAU,EAAI5W,EAAAA,SAAyB,CAAA,CAAE,EACnD,CAAC6W,EAAgBC,CAAiB,EAAI9W,EAAAA,SAAS,EAAE,EACjD,CAACmN,EAAa4J,CAAc,EAAI/W,EAAAA,SAAS,EAAE,EAC3C,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EACtC,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B,CAACiX,EAASC,CAAU,EAAIlX,EAAAA,SAAS,EAAK,EACtC,CAACmX,EAAgBC,CAAiB,EAAIpX,EAAAA,SAAS,EAAK,EAG1DO,EAAAA,UAAU,IAAM,CACR0Q,GAAQ0F,EAAQ,SAAW,GAC3BU,EAAA,CAER,EAAG,CAACpG,EAAM0F,EAAQ,MAAM,CAAC,EAGzBpW,EAAAA,UAAU,IAAM,CACP0Q,IACD6F,EAAkB,EAAE,EACpBC,EAAe,EAAE,EACjBC,EAAS,EAAE,EACXE,EAAW,EAAK,EAExB,EAAG,CAACjG,CAAI,CAAC,EAET,MAAMoG,EAAoB,SAAY,CAClC,GAAI,CACAD,EAAkB,EAAI,EACtB,MAAM3W,EAAW,MAAMC,GAAI,IAAI,sBAAsB,EACjDD,EAAS,MAAM,MACfmW,EAAWnW,EAAS,KAAK,IAAI,CAErC,OAASE,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACIyW,EAAkB,EAAK,CAC3B,CACJ,EAEME,EAAe,MAAO5O,GAAuB,CAG/C,GAFAA,EAAE,eAAA,EAEE,CAACmO,EAAe,OAAQ,CACxBG,EAASpX,EAAE,wBAAwB,CAAC,EACpC,MACJ,CAEA,GAAI,CACAM,EAAW,EAAI,EACf8W,EAAS,EAAE,EAEX,MAAMtW,GAAI,KAAK,eAAgB,CAC3B,QAAAhB,EACA,OAAQmX,EACR,YAAa1J,EAAY,KAAA,GAAU,MAAA,CACtC,EAED+J,EAAW,EAAI,EAEf,WAAW,IAAM,CACbhG,EAAA,CACJ,EAAG,IAAI,CACX,OAASvQ,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACIT,EAAW,EAAK,CACpB,CACJ,EAEMqX,EAAY,CAACtX,GAAW4W,EAAe,KAAA,EAE7C,OACIxV,EAAAA,KAAC+T,EAAA,CAAM,KAAAnE,EAAY,OAAAC,EAAgB,SAAQ,GACvC,SAAA,CAAA3P,EAAAA,IAAC6T,EAAM,OAAN,CAAa,YAAW,GACrB,SAAA7T,MAAC6T,EAAM,MAAN,CAAY,GAAG,KAAM,SAAAxV,EAAE,iBAAiB,EAAE,EAC/C,EAEAyB,EAAAA,KAACsU,GAAA,CAAK,SAAU2B,EACZ,SAAA,CAAAjW,EAAAA,KAAC+T,EAAM,KAAN,CAAW,UAAU,OACjB,SAAA,CAAArB,SACIyD,GAAA,CAAM,QAAQ,SAAS,UAAU,OAC7B,SAAAzD,EACL,EAGHkD,SACIO,GAAA,CAAM,QAAQ,UAAU,UAAU,OAC9B,SAAA5X,EAAE,mBAAmB,CAAA,CAC1B,EAGH,CAACqX,GACE5V,EAAAA,KAACjC,GAAA,CAAM,IAAK,EAER,SAAA,CAAAiC,OAAC,MAAA,CACG,SAAA,CAAAE,MAAC,KAAA,CAAG,UAAU,OACT,SAAA3B,EAAE,kBAAkB,EACzB,EACCuX,EACG5V,EAAAA,IAAC,MAAA,CAAI,UAAU,aACV,SAAA3B,EAAE,gBAAgB,CAAA,CACvB,QAECR,GAAA,CAAM,IAAK,EACP,SAAAuX,EAAQ,IAAIc,GACTlW,EAAAA,IAACoU,GAAK,MAAL,CAEG,KAAK,QACL,KAAK,eACL,GAAI,UAAU8B,EAAO,KAAK,GAC1B,MAAOA,EAAO,MACd,MAAOA,EAAO,MACd,QACIZ,IACAY,EAAO,MAEX,SAAU/O,GACNoO,EACIpO,EAAE,OAAO,KAAA,CACb,EAbC+O,EAAO,KAAA,CAgBnB,EACL,QAIH,MAAA,CAAI,UAAU,wBACV,SAAA7X,EAAE,yBAAyB,CAAA,CAChC,CAAA,EACJ,SAGC,MAAA,CACG,SAAA,CAAA2B,MAAC,KAAA,CAAG,UAAU,OACT,SAAA3B,EAAE,uBAAuB,EAC9B,EACA2B,EAAAA,IAACoU,GAAK,QAAL,CACG,GAAG,WACH,KAAM,EACN,MAAOxI,EACP,SAAUzE,GACNqO,EAAerO,EAAE,OAAO,KAAK,EAEjC,YAAY,GACZ,UAAW,IACX,UAAU,MAAA,CAAA,EAEdnH,MAACoU,GAAK,KAAL,CAAU,UAAU,aAChB,SAAA/V,EAAE,2BAA2B,CAAA,CAClC,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EAER,EAEC,CAACqX,GACE5V,EAAAA,KAAC+T,EAAM,OAAN,CACG,SAAA,CAAA7T,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,uBACV,QAAS4P,EACT,SAAUjR,EAET,WAAE,eAAe,CAAA,CAAA,EAEtBsB,EAAAA,IAACD,EAAA,CACG,QAAQ,UACR,KAAK,SACL,SAAU,CAACiW,EAEV,SACK3X,EADLK,EACO,iBACA,kBADgB,CACE,CAAA,CAC9B,CAAA,CACJ,CAAA,CAAA,CAER,CAAA,EACJ,CAER,CClKO,SAASyX,GAAU,CACtB,MAAAzB,EACA,QAAAhW,EACA,MAAA8T,EACA,cAAApU,EACA,cAAAgY,CACJ,EAAmB,CACf,KAAM,CAAE,EAAA/X,CAAA,EAAMC,GAAA,EACR+X,EAAWC,GAAA,EACX,CAACC,EAAQC,CAAS,EAAI/X,EAAAA,SAAS,EAAK,EACpC,CAACgY,EAAiBC,CAAkB,EAAIjY,EAAAA,SAAS,EAAK,EACtD,CAACkY,EAAcC,CAAe,EAAInY,EAAAA,SAAS,EAAK,EAChD,CAACoY,EAAUC,CAAW,EAAIrY,EAAAA,SAAS,EAAK,EACxC,CAACsY,EAAmBC,CAAoB,EAAIvY,EAAAA,SAAS,EAAK,EAC1D,CAACwY,EAAeC,CAAgB,EAAIzY,EAAAA,SAAS,EAAK,EAClD,CAAC6M,EAAU6L,CAAW,EAAI1Y,EAAAA,SAAS,EAAE,EAGrC,CAAE,QAAA2Y,EAAS,UAAAC,EAAW,aAAAC,CAAA,EAAiBC,GACzC7C,EACAtW,CAAA,EAGJY,EAAAA,UAAU,IAAM,CACZmY,EAAY,OAAO,SAAS,IAAI,CACpC,EAAG,CAAA,CAAE,EAEL,MAAMK,EAAa,SAAY,CAC3B,GAAI,CAAC9C,GAAS6B,EAAQ,OAGtB,GAAI,CAACnY,EAAe,CAChBmB,GACI,CAAE,OAAQ,OAAQ,SAAUmV,EAAM,EAAA,EAClC,OAAO,SAAS,SAAW,OAAO,SAAS,MAAA,EAE/C,MACJ,CAEA,MAAM+C,EAAS/C,EAAM,cAAgB,SAAW,OAG1CgD,EAAsBhD,EAAM,cAC5BiD,EAAqBjD,EAAM,MAG3BkD,GAAiB,CAAClD,EAAM,cACxBmD,EAAgBD,IACflD,EAAM,OAAS,GAAK,EACrB,KAAK,KAAKA,EAAM,OAAS,GAAK,EAAG,CAAC,EAExC0B,IAAgB,CACZ,MAAOyB,EACP,cAAeD,EAAA,CAClB,EAED,GAAI,CACApB,EAAU,EAAI,EACd,MAAMtX,GAAW,MAAMC,GAAI,KACvB,eAAeuV,EAAM,EAAE,QACvB,CAAE,OAAA+C,CAAA,CAAO,EAGTvY,GAAS,KAAK,SAEdkX,IAAgB,CACZ,MAAOlX,GAAS,KAAK,KAAK,MAC1B,cAAeA,GAAS,KAAK,KAAK,aAAA,CACrC,EAGD4Y,GAAU,CACN,OAAQ5Y,GAAS,KAAK,KAAK,cACrB,OACA,SACN,SAAUwV,EAAM,GAChB,QAAS,GACT,YAAaxV,GAAS,KAAK,KAAK,KAAA,CACnC,IAGDkX,IAAgB,CACZ,MAAOuB,EACP,cAAeD,CAAA,CAClB,EACD/X,EAAUtB,EAAE,qBAAqB,CAAC,EAGlCyZ,GAAU,CACN,OAAQJ,EAAsB,SAAW,OACzC,SAAUhD,EAAM,GAChB,QAAS,GACT,MAAO,iBAAA,CACV,EAET,OAAStV,GAAK,CAEVgX,IAAgB,CACZ,MAAOuB,EACP,cAAeD,CAAA,CAClB,EACD,MAAM9X,GAAeP,GAAgBD,EAAG,EACxC,QAAQ,MAAM,yBAA0BQ,EAAY,EACpDD,EAAUC,EAAY,EAGtBkY,GAAU,CACN,OAAQJ,EAAsB,SAAW,OACzC,SAAUhD,EAAM,GAChB,QAAS,GACT,MAAO9U,EAAA,CACV,CACL,QAAA,CACI4W,EAAU,EAAK,CACnB,CACJ,EAEAxX,EAAAA,UAAU,IAAM,CAERZ,GACAsW,GAAO,IACP7U,GAAwB,CAAE,OAAQ,OAAQ,SAAU6U,EAAM,EAAA,CAAI,IAEzDA,EAAM,eAAoB8C,EAAA,EAEvC,EAAG,CAACpZ,EAAesW,GAAO,GAAIA,GAAO,aAAa,CAAC,EAEnD,MAAMqD,GAAkB,SAAY,CAChC,GAAI,GAACrD,GAAS,CAACtW,GAAiBuY,GAEhC,GAAI,CACAC,EAAgB,EAAI,EACpB,MAAM1X,EAAW,MAAMC,GAAI,KACvB,eAAeuV,EAAM,EAAE,YAAA,EAG3B,GAAIxV,EAAS,KAAK,QAAS,CAEvB,MAAMiH,EACFjH,EAAS,KAAK,SAAW,YACnBb,EAAE,mCAAmC,EACrCA,EAAE,qCAAqC,EACjD6Q,GAAY/I,CAAO,EAGnBiQ,IAAgB,CACZ,cAAelX,EAAS,KAAK,aAAA,CAChC,CACL,MACIS,EAAUT,EAAS,KAAK,SAAWb,EAAE,kBAAkB,CAAC,CAEhE,OAASe,EAAK,CACV,QAAQ,MACJ,yCACAC,GAAgBD,CAAG,CAAA,EAEvBO,EAAUtB,EAAE,kBAAkB,CAAC,CACnC,QAAA,CACIuY,EAAgB,EAAK,CACzB,CACJ,EAEMoB,EAAe,IAAM,CAEvB,GAAI,CAAC5Z,EAAe,CAChBmB,GACI,CAAE,OAAQ,SAAU,SAAUmV,GAAO,EAAA,EACrC,OAAO,SAAS,SAAW,OAAO,SAAS,MAAA,EAE/C,MACJ,CACAgC,EAAmB,EAAI,CAC3B,EAEA1X,EAAAA,UAAU,IAAM,CAERZ,GACAsW,GAAO,IACP7U,GAAwB,CAAE,OAAQ,SAAU,SAAU6U,EAAM,EAAA,CAAI,GAEhEgC,EAAmB,EAAI,CAE/B,EAAG,CAACtY,EAAesW,GAAO,EAAE,CAAC,EAE7B,MAAMuD,EAAe,IAAM,CACvBjB,EAAqB,EAAI,CAC7B,EAEMkB,EAAyB,GAC3BxD,GAAO,QACFA,EAAM,OAA0C,kBAGnDyD,EAAa,IAAM,CACrB,GAAKzD,EAKL,IAAI,CAACtW,EAAe,CAChB,MAAMga,EAAY,mBACd,OAAO,SAAS,SAAW,OAAO,SAAS,MAAA,EAE/C,OAAO,SAAS,KAAOC,GACnB,yBAAyBD,CAAS,EAAA,EAEtC,MACJ,CAGA,GAAI1D,GAASA,EAAM,SAAW,YAAa,CACvC/U,EAAUtB,EAAE,oCAAoC,CAAC,EACjD,MACJ,CAEA,GAAI,CAAC6Z,EAAwB,CACzBvY,EAAUtB,EAAE,mCAAmC,CAAC,EAChD,MACJ,CAEA,GAAI,OAAOqW,EAAM,OAAO,EAAE,IAAM,OAAOtW,CAAa,EAAG,CACnDuB,EAAUtB,EAAE,qCAAqC,CAAC,EAClD,MACJ,CAEA6Y,EAAiB,EAAI,EACzB,EAEMoB,GAAgB,SAAY,CAC9B,GAAI,GAAC5D,GAAS,CAACtW,GAAiByY,GAEhC,GAAI,CACAC,EAAY,EAAI,EAChB,MAAM5X,EAAW,MAAMC,GAAI,OAAO,eAAeuV,EAAM,EAAE,EAAE,EAEvDxV,EAAS,KAAK,SACdgQ,GAAY7Q,EAAE,+BAA+B,CAAC,EAE9C,WAAW,IAAM,CACb,OAAO,SAAS,KAAOga,GAAQ,GAAG,CACtC,EAAG,IAAI,GAEP1Y,EAAUT,EAAS,KAAK,SAAWb,EAAE,kBAAkB,CAAC,CAEhE,OAASe,EAAK,CACV,QAAQ,MAAM,0BAA2BC,GAAgBD,CAAG,CAAC,EAC7DO,EAAUtB,EAAE,kBAAkB,CAAC,CACnC,QAAA,CACIyY,EAAY,EAAK,CACrB,CACJ,EAEA,OAAIpY,EAEIoB,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,UAAU,yBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,yBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,qBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,CAC3B,EACL,EAIJwS,GAAS,CAACkC,EAEN1U,EAAAA,IAACiW,IAAM,QAAQ,UACX,eAAC,QAAA,CAAO,SAAA5X,EAAE,6BAA6B,CAAA,CAAE,CAAA,CAC7C,EAKJyB,EAAAA,KAAA8T,WAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,KAAA,CAAG,UAAU,UAAW,SAAA0U,EAAM,MAAM,QAGpC,MAAA,CAAI,UAAU,OACX,SAAA5U,EAAAA,KAAC,MAAA,CAAI,UAAU,qHAEX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,6FACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACX,SAAA,CAAAE,MAAC,MAAA,CAAI,UAAU,qBACV,SAAA0U,EAAM,OAAO,SACV1U,EAAAA,IAAC,IAAA,CACG,KAAMuY,GACF7D,EAAM,OAAO,QAAA,EAEjB,UAAU,uBAEV,SAAA1U,EAAAA,IAACwY,GAAA,CACG,SAAU9D,EAAM,OAAO,SACvB,YACIA,EAAM,OAAO,YAEjB,WAAYA,EAAM,OAAO,WACzB,sBAAqB,GACrB,KAAK,QAAA,CAAA,CACT,CAAA,EAGJ1U,EAAAA,IAACwY,GAAA,CACG,SAAU9D,EAAM,OAAO,SACvB,YAAaA,EAAM,OAAO,YAC1B,WAAYA,EAAM,OAAO,WACzB,sBAAqB,GACrB,KAAK,QAAA,CAAA,EAGjB,EACA5U,EAAAA,KAAC,MAAA,CAAI,UAAU,cACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACV,SAAA,CAAA4U,EAAM,OAAO,SACV1U,EAAAA,IAAC,IAAA,CACG,KAAMuY,GACF7D,EAAM,OAAO,QAAA,EAEjB,UAAU,iCACV,MAAO,CAAE,OAAQ,SAAA,EAEhB,WAAM,OAAO,WAAA,CAAA,EAGlBA,EAAM,OAAO,YAEjB1U,EAAAA,IAACyY,GAAA,CACG,WAAY/D,EAAM,OAAO,UAAA,CAAA,CAC7B,EACJ,QACC,QAAA,CAAM,UAAU,aACZ,SAAAA,EAAM,OAAO,iBACV,QACArW,EACI,oBACA,CACI,MAAOqW,EAAM,OACR,cAAA,EAET,CACI,MAAOA,EAAM,OACR,cAAA,CACT,CACJ,CACR,CAAA,CAAA,CACJ,CAAA,EACJ,EAECA,EAAM,OAAO,IACV,OAAOtW,GAAiB,CAAC,IACrB,OAAOsW,EAAM,OAAO,EAAE,GACtB1U,EAAAA,IAAC,MAAA,CAAI,UAAU,qBACX,SAAAA,EAAAA,IAAC0Y,IAAa,OAAQhE,EAAM,OAAO,EAAA,CAAI,CAAA,CAC3C,CAAA,EAEZ,QAGC,MAAA,CAAI,UAAU,gBACX,SAAA5U,EAAAA,KAAC,MAAA,CAAI,UAAU,+CACV,SAAA,CAAA4U,EAAM,SAAW,aACd5U,EAAAA,KAACC,EAAA,CACG,QAAQ,QACR,QAASyX,EACT,SAAUjB,EACV,UAAU,4BAEV,SAAA,CAAAvW,EAAAA,IAAC,IAAA,CACG,UAAW,WACP0U,EAAM,cACA,yBACA,mBACV,EAAA,CAAA,EAEHA,EAAM,QAAU,QACjBA,EAAM,MAAQ,EACRA,EAAM,MAAM,eAAA,EACZrW,EAAE,gBAAgB,CAAA,CAAA,CAAA,EAI/BqW,GACGA,EAAM,SAAW,aACjBwD,GACA,CAAC7B,GACGvW,EAAAA,KAACC,EAAA,CACG,QAAQ,QACR,UAAU,4BACV,QAASoY,EAET,SAAA,CAAAnY,EAAAA,IAAC,IAAA,CAAE,UAAU,iBAAA,CAAkB,EAC9B3B,EAAE,kBAAkB,CAAA,CAAA,CAAA,EAGjC2B,EAAAA,IAAC9B,GAAA,CACG,QAASwW,EAAM,GACf,cAAAtW,EACA,UAAU,2BAAA,CAAA,EAEd4B,EAAAA,IAAC4O,GAAA,CACG,SAAAtD,EACA,MAAOoJ,EAAM,MACb,YAAa,GAAGA,EAAM,KAAK,MAAMA,EAAM,OAAO,WAAW,GACzD,UAAU,2BAAA,CAAA,SAGbpF,GAAA,CACG,SAAA,CAAAtP,EAAAA,IAACsP,GAAS,OAAT,CACG,QAAQ,QACR,UAAU,2DAEV,SAAAtP,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAAA,CAA4B,CAAA,CAAA,EAG7CF,EAAAA,KAACwP,GAAS,KAAT,CAEG,SAAA,CAAAtP,MAACsP,GAAS,KAAT,CAAc,QAAS0I,EACnB,SAAA3Z,EAAE,kBAAkB,EACzB,EAGC+Y,GAAW1C,GACR1U,EAAAA,IAACsP,GAAS,KAAT,CACG,KAAM+I,GACF,UAAU3D,EAAM,EAAE,OAAA,EAGrB,WAAE,gBAAgB,CAAA,CAAA,EAK1B4C,GACGtX,EAAAA,IAACsP,GAAS,KAAT,CACG,QAASyI,GACT,SAAUpB,EAET,SAAAA,EACKtY,EAAE,gBAAgB,EAClBqW,EAAM,cACJrW,EAAE,uBAAuB,EACzBA,EAAE,qBAAqB,CAAA,CAAA,EAKtCgZ,GACGrX,EAAAA,IAACsP,GAAS,KAAT,CACG,QAAS2I,EACT,SAAUpB,EAET,SACKxY,EADLwY,EACO,iBACA,kBADgB,CACE,CAAA,CAC9B,CAAA,CAER,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,CACJ,EAGCnC,EAAM,aACH5U,OAAC,MAAA,CAAI,UAAU,4BACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACX,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,cACX,SAAA3B,EACG,iBACA,CAAE,MAAOqW,EAAM,KAAA,EACf,CAAE,MAAOA,EAAM,KAAA,CAAM,EAE7B,EACA1U,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAkB,SAAA,IAAC,EACnCA,EAAAA,IAAC,OAAA,CAAK,UAAU,cACX,WAAE,sBAAuB,CACtB,KAAM0U,EAAM,UAAA,CACf,CAAA,CACL,CAAA,EACJ,EACA1U,EAAAA,IAAC,MAAA,CACG,UAAU,sBACV,MAAO,CAAE,WAAY,UAAA,EAEpB,SAAA0U,EAAM,YAAY,QAAQ,OAAQ;AAAA,CAAI,CAAA,CAAA,EAI1CA,EAAM,MAAQA,EAAM,KAAK,OAAS,GAC/B1U,EAAAA,IAAC,MAAA,CAAI,UAAU,kBACV,SAAA0U,EAAM,KAAK,IAAI,CAACiE,EAAKxW,IAClBrC,EAAAA,KAAC0U,GAAA,CAEG,GAAG,UACH,UAAU,mCACV,MAAO,CAAE,SAAU,SAAA,EACtB,SAAA,CAAA,IACKmE,CAAA,CAAA,EALGxW,CAAA,CAOZ,CAAA,CACL,CAAA,EAER,EAIHuS,GACG1U,EAAAA,IAACmV,GAAA,CACG,KAAMsB,EACN,OAAQ,IAAMC,EAAmB,EAAK,EACtC,QAAShC,EAAM,EAAA,CAAA,EAKtBA,GACG1U,EAAAA,IAAC6U,GAAA,CACG,KAAMkC,EACN,MAAO1Y,EAAE,kBAAkB,EAC3B,QAASA,EAAE,yBAA0B,CACjC,MAAOqW,EAAM,KAAA,CAChB,EACD,YAAarW,EAAE,kBAAkB,EACjC,WAAYA,EAAE,kBAAkB,EAChC,QAAQ,SACR,UAAWia,GACX,SAAU,IAAMtB,EAAqB,EAAK,CAAA,CAAA,EAKjDtC,GACG1U,EAAAA,IAACyP,GAAA,CACG,KAAMwH,EACN,OAAQ,IAAMC,EAAiB,EAAK,EACpC,QAASxC,EAAM,GACf,cAAeA,EAAM,OAAO,EAAA,CAAA,CAChC,EAER,CAER,CCvjBO,SAASkE,GAAe,CAC3B,QAAAza,EACA,cAAAC,EACA,aAAAya,CACJ,EAAwB,CACpB,KAAM,CAACnE,EAAOoE,CAAQ,EAAIra,EAAAA,SAAuBoa,GAAgB,IAAI,EAC/D,CAACna,EAASC,CAAU,EAAIF,EAAAA,SAAS,CAACoa,CAAY,EAC9C,CAACrG,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B,CAACsa,EAAgBC,CAAiB,EAAIva,EAAAA,SAAwB,IAChEL,EAAgB,KAAO,CAAA,EAErB6a,EAAwBzO,EAAAA,OAAsB,IAAI,EAExDxL,EAAAA,UAAU,IAAM,CACP0V,GACDwE,EAAA,CAER,EAAG,CAAC/a,CAAO,CAAC,EAEZa,EAAAA,UAAU,IAAM,CACZ,IAAIma,EAAS,GACb,OAAK/a,GAIL4a,EAAkB,IAAI,EAEtB7Z,GAAI,IACA,uBAAuBhB,CAAO,EAAA,EAE7B,KAAKe,GAAY,CACd,MAAMka,EAAQla,EAAS,KAAK,KACtBma,EAAWD,GAAO,eAAiB,EACnCE,EAAWF,GAAO,eAAiB,EACrCD,GACAH,EACIK,EAAW,IAAM,CAACC,GAAYD,EAAWC,EAAW,IAC9CD,EACA,CAAA,CAGlB,CAAC,EACA,MAAM,IAAM,CACLF,KAA0B,CAAC,CACnC,CAAC,EAEE,IAAM,CACTA,EAAS,EACb,IA1BIH,EAAkB,CAAC,EACZ,OA0Bf,EAAG,CAAC5a,EAAeD,CAAO,CAAC,EAE3B,MAAM+a,EAAY,SAAY,CAC1B,GAAI,CACAva,EAAW,EAAI,EACf8W,EAAS,EAAE,EAEX,MAAMvW,EAAW,MAAMC,GAAI,IAAW,eAAehB,CAAO,EAAE,EAC9D2a,EAAS5Z,EAAS,IAAI,CAC1B,OAASE,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACIT,EAAW,EAAK,CACpB,CACJ,EAEM4a,EAAqBC,GAAkC,CACrD9E,GACAoE,EAAS,CAAE,GAAGpE,EAAO,GAAG8E,EAAe,CAE/C,EAEAxa,OAAAA,EAAAA,UAAU,IAAM,CACR,CAAC0V,GAAO,IAAMuE,EAAsB,UAAYvE,EAAM,KAE1DuE,EAAsB,QAAUvE,EAAM,GACtC+E,GAAW,eAAgB,CACvB,aAAc,QACd,SAAU/E,EAAM,GAChB,MAAOA,EAAM,MACb,UAAWA,EAAM,QAAQ,EAAA,CAC5B,EACL,EAAG,CAACA,CAAK,CAAC,SAGL,MAAA,CAEG,SAAA,CAAA1U,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAACyU,GAAA,CACG,MAAAC,EACA,QAAShW,GAAWqa,IAAmB,KACvC,MAAAvG,EACA,cAAApU,EACA,gBAAiB2a,GAAkB,CAAA,CAAA,EAE3C,EAGA/Y,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAACmW,GAAA,CACG,MAAAzB,EACA,QAAAhW,EACA,MAAA8T,EACA,cAAApU,EACA,cAAemb,CAAA,CAAA,CACnB,CACJ,CAAA,EACJ,CAER,CCjGO,SAASG,GAAY,CACxB,QAAAvb,EACA,SAAAwb,EACA,YAAAC,EACA,YAAAC,EACA,SAAAC,EACA,SAAA5E,EACA,UAAAnZ,EAAY,GACZ,UAAAge,EAAY,EAChB,EAAqB,CACjB,KAAM,CAAE,EAAA1b,CAAA,EAAMC,GAAA,EACR,CAAE,KAAM0b,CAAA,EAAgBC,GAAA,EACxB,CAACC,EAAcC,CAAe,EAAI1b,EAAAA,SAAS,EAAK,EAChD,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B,CAAC2b,EAAWC,CAAY,EAAI5b,EAAAA,SAAS,EAAK,EAC1C6b,EAAc9P,EAAAA,OAA4B,IAAI,EAE9C,CACF,SAAA+P,EACA,aAAAxE,EACA,MAAAyE,EACA,MAAAC,EACA,UAAW,CAAE,OAAAC,EAAQ,QAAAC,CAAA,CAAQ,EAC7BC,GAAyB,CACzB,KAAM,UAAA,CACT,EAEKC,EAAUJ,EAAM,UAAW,EAAE,EAEnCzb,EAAAA,UAAU,IAAM,CACR+a,GAAaO,EAAY,SACzBA,EAAY,QAAQ,MAAA,CAE5B,EAAG,CAACP,CAAS,CAAC,EAEd/a,EAAAA,UAAU,IAAM,CAERgb,GACAna,GAAwB,CAAE,OAAQ,UAAW,SAAU1B,CAAA,CAAS,GAEhEmc,EAAY,SAAS,MAAA,CAE7B,EAAG,CAACN,EAAa7b,CAAO,CAAC,EAGzBa,EAAAA,UAAU,IAAM,CACZ,MAAM8b,EAAWR,EAAY,QACzBQ,IACAA,EAAS,MAAM,OAAS,OACxBA,EAAS,MAAM,OACX,KAAK,IAAI,GAAI,KAAK,IAAI,IAAKA,EAAS,YAAY,CAAC,EAAI,KAEjE,EAAG,CAACD,CAAO,CAAC,EAEZ,MAAME,EAAe,MAAOzW,GAA0B,CAElD,GAAI,CAAC0V,EAAa,CACdza,GACI,CAAE,OAAQ,UAAW,SAAUpB,CAAA,EAC/B,OAAO,SAAS,SAAW,OAAO,SAAS,MAAA,EAE/C,MACJ,CAEA,GAAI,CACAgc,EAAgB,EAAI,EACpB1E,EAAS,EAAE,EAEX,MAAMuF,EAAgC,CAClC,QAAA7c,EACA,QAASmG,EAAK,QAAQ,KAAA,EACtB,GAAIqV,GAAY,CAAE,SAAAA,CAAA,EAClB,GAAIC,GAAe,CAAE,YAAAA,CAAA,CAAY,EAG/B1a,EAAW,MAAMC,GAAI,KAAK,gBAAiB6b,CAAO,EAEpD9b,EAAS,KAAK,UACdsb,EAAA,EACAH,EAAa,EAAK,EAClBP,IAAW5a,EAAS,KAAK,IAAI,EAErC,OAASE,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACI+a,EAAgB,EAAK,CACzB,CACJ,EAEMc,GAAe,IAAM,CACvBT,EAAA,EACA/E,EAAS,EAAE,EACX4E,EAAa,EAAK,EAClBnF,IAAA,CACJ,EAEMgG,EAAc,IAAM,CACtBb,EAAa,EAAI,CACrB,EAEMc,EAAa,IAAM,CAChBN,EAAQ,QACTR,EAAa,EAAK,CAE1B,EAEMe,EAAc,EAAQzB,EACtB0B,EAAcjB,GAAaS,EAAQ,KAAA,GAAUO,EAC7CE,GAAqBzB,GAAexb,EAAE,uBAAuB,EAEnE,OACIyB,EAAAA,KAAC,MAAA,CAAI,UAAW,gBAAgB/D,CAAS,GACrC,SAAA,CAAA+D,EAAAA,KAACsU,GAAA,CACG,SAAU2B,EAAagF,CAAY,EACnC,UAAU,oBAEV,SAAA,CAAAjb,EAAAA,KAACsU,GAAK,MAAL,CAAW,UAAU,OAClB,SAAA,CAAApU,EAAAA,IAACoU,GAAK,QAAL,CACG,IAAKkG,EACL,GAAG,WACH,YAAagB,GACb,KAAM,EACN,UAAW,CAAC,CAACZ,EAAO,QACnB,GAAGH,EAAS,UAAW,CACpB,SAAUlc,EAAE,gCAAgC,EAC5C,UAAW,CACP,MAAO,EACP,QAASA,EAAE,gCAAgC,CAAA,EAE/C,UAAW,CACP,MAAO,IACP,QAASA,EAAE,+BAA+B,CAAA,CAC9C,CACH,EACD,SAAU6b,EACV,QAASgB,EACT,OAAQC,CAAA,CAAA,EAEZnb,EAAAA,IAACoU,GAAK,QAAQ,SAAb,CAAsB,KAAK,UACvB,SAAAsG,EAAO,SAAS,OAAA,CACrB,CAAA,EACJ,EAECW,GACGrb,EAAAA,IAAC,MAAA,CACG,UAAU,qDACV,MAAO,CACH,UAAWqb,EACL,uBACA,MAAA,EAGV,SAAAvb,EAAAA,KAAC,MAAA,CAAI,UAAU,eACV,SAAA,CAAAoV,GACGlV,EAAAA,IAACD,EAAA,CACG,QAAQ,oBACR,QAASkb,GACT,SAAUf,EAET,WAAE,kBAAkB,CAAA,CAAA,EAG7Bla,EAAAA,IAACD,EAAA,CACG,KAAK,SACL,QAAQ,UACR,SACI,CAAC4a,GAAWT,GAAgB,CAACW,EAAQ,KAAA,EAGxC,WACG/a,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC8T,GAAA,CACG,GAAG,OACH,UAAU,SACV,KAAK,KACL,KAAK,SACL,cAAY,OACZ,UAAU,MAAA,CAAA,EAGRzV,EADLsb,EACO,sBACA,oBADqB,CACD,CAAA,CAChC,EAEAtb,EADAsb,EACE,mBAEA,uBAFkB,CAEK,CAAA,CAEjC,CAAA,CACJ,CAAA,CAAA,EAIPnH,GACG1S,EAAAA,KAACmW,GAAA,CACG,QAAQ,SACR,UAAU,iBACV,MAAO,CAAE,SAAU,MAAA,EAEnB,SAAA,CAAAjW,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAA,CAAkC,EAC9CwS,CAAA,CAAA,CAAA,CACL,CAAA,CAAA,QAIP,QAAA,CAAO,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAAA,CAoBN,CAAA,EACN,CAER,CC/OO,SAAS+I,GAAgB,CAC5B,QAAAjH,EACA,SAAAwF,EACA,SAAA5E,CACJ,EAAyB,CACrB,KAAM,CAAE,EAAA7W,CAAA,EAAMC,GAAA,EACR,CAAC4b,EAAcC,CAAe,EAAI1b,EAAAA,SAAS,EAAK,EAChD,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B6b,EAAc9P,EAAAA,OAA4B,IAAI,EAE9C,CACF,SAAA+P,EACA,aAAAxE,EACA,MAAA0E,EACA,UAAW,CAAE,OAAAC,EAAQ,QAAAC,EAAS,QAAAa,CAAA,CAAQ,EACtCZ,GAA6B,CAC7B,KAAM,WACN,cAAe,CACX,QAAStG,EAAQ,OAAA,CACrB,CACH,EAEKuG,EAAUJ,EAAM,UAAW,EAAE,EAEnCzb,EAAAA,UAAU,IAAM,CACZ,GAAIsb,EAAY,QAAS,CACrBA,EAAY,QAAQ,MAAA,EAEpB,MAAMmB,EAASnB,EAAY,QAAQ,MAAM,OACzCA,EAAY,QAAQ,kBAAkBmB,EAAQA,CAAM,CACxD,CACJ,EAAG,CAAA,CAAE,EAGLzc,EAAAA,UAAU,IAAM,CACZ,MAAM8b,EAAWR,EAAY,QACzBQ,IACAA,EAAS,MAAM,OAAS,OACxBA,EAAS,MAAM,OACX,KAAK,IAAI,GAAI,KAAK,IAAI,IAAKA,EAAS,YAAY,CAAC,EAAI,KAEjE,EAAG,CAACD,CAAO,CAAC,EAEZ,MAAME,EAAe,MAAOzW,GAA8B,CACtD,GAAI,CACA6V,EAAgB,EAAI,EACpB1E,EAAS,EAAE,EAEX,MAAMuF,EAAgC,CAClC,QAAS1W,EAAK,QAAQ,KAAA,CAAK,EAGzBpF,EAAW,MAAMC,GAAI,IACvB,iBAAiBmV,EAAQ,EAAE,GAC3B0G,CAAA,EAGA9b,EAAS,KAAK,SACd4a,IAAW5a,EAAS,KAAK,IAAI,CAErC,OAASE,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACI+a,EAAgB,EAAK,CACzB,CACJ,EAEMc,EAAe,IAAM,CACvBxF,EAAS,EAAE,EACXP,IAAA,CACJ,EAEMwG,EAAaF,GAAWX,EAAQ,KAAA,IAAWvG,EAAQ,QAEzD,OACIxU,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACX,SAAA,CAAAA,EAAAA,KAACsU,GAAA,CACG,SAAU2B,EAAagF,CAAY,EACnC,UAAU,oBAEV,SAAA,CAAAjb,EAAAA,KAACsU,GAAK,MAAL,CAAW,UAAU,OAClB,SAAA,CAAApU,EAAAA,IAACoU,GAAK,QAAL,CACG,IAAKkG,EACL,GAAG,WACH,YAAajc,EAAE,4BAA4B,EAC3C,UAAW,CAAC,CAACqc,EAAO,QACpB,KAAM,EACL,GAAGH,EAAS,UAAW,CACpB,SAAU,8BACV,UAAW,CACP,MAAO,EACP,QAAS,2BAAA,EAEb,UAAW,CACP,MAAO,IACP,QACI,2CAAA,CACR,CACH,EACD,SAAUL,CAAA,CAAA,EAEdla,EAAAA,IAACoU,GAAK,QAAQ,SAAb,CAAsB,KAAK,UACvB,SAAAsG,EAAO,SAAS,OAAA,CACrB,CAAA,EACJ,EAEClI,GACG1S,EAAAA,KAACmW,GAAA,CACG,QAAQ,SACR,UAAU,iBACV,MAAO,CAAE,SAAU,MAAA,EAEnB,SAAA,CAAAjW,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAA,CAAkC,EAC9CwS,CAAA,CAAA,CAAA,EAIT1S,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACX,SAAA,CAAAE,EAAAA,IAACD,EAAA,CACG,QAAQ,oBACR,QAASkb,EACT,SAAUf,EACb,SAAA,QAAA,CAAA,EAGDla,EAAAA,IAACD,EAAA,CACG,KAAK,SACL,SAAU,CAAC4a,GAAWT,GAAgB,CAACW,EAAQ,KAAA,EAE9C,WACG/a,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC8T,GAAA,CACG,GAAG,OACH,UAAU,SACV,KAAK,KACL,KAAK,SACL,cAAY,OACZ,UAAU,MAAA,CAAA,EACZ,WAAA,CAAA,CAEN,EACA4H,EACA5b,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,IAAA,CAAE,UAAU,qBAAA,CAAsB,EAAI,MAAA,CAAA,CAE3C,EAEA,MAAA,CAAA,CAER,CAAA,CACJ,CAAA,CAAA,CAAA,QAGH,QAAA,CAAO,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAAA,CASN,CAAA,EACN,CAER,CCxJO,SAAS2b,GAAY,CACxB,QAAArH,EACA,QAAAnW,EACA,cAAAC,EACA,gBAAAwd,EACA,aAAAC,EACA,SAAAC,EACA,SAAAC,EACA,QAAAC,EACA,kBAAAC,EACA,cAAAC,EACA,MAAAC,EAAQ,EACR,kBAAAC,CACJ,EAAqB,CACjB,KAAM,CAAE,EAAA/d,CAAA,EAAMC,GAAA,EACR,CAAE,KAAM0b,CAAA,EAAgBC,GAAA,EACxB,CAACoC,EAAWC,CAAY,EAAI7d,EAAAA,SAAS,EAAK,EAC1C,CAAC8d,EAAYC,CAAa,EAAI/d,EAAAA,SAAS,EAAK,EAC5C,CAACge,EAAUC,CAAW,EAAIje,EAAAA,SAAS,EAAK,EACxC,CAACke,EAAYC,CAAa,EAAIne,EAAAA,SAAS,EAAK,EAC5C,CAACoe,EAAoBC,CAAqB,EAAIre,EAAAA,SAAS,EAAK,EAC5D,CAACse,EAAYC,EAAa,EAAIve,EAAAA,SAAS,EAAK,EAC5C,CAACwe,EAAWC,CAAY,EAAIze,EAAAA,SAAS,EAAK,EAG1C,CAAC0e,EAAgBC,CAAiB,EAAI3e,EAAAA,SAAS6V,CAAO,EAEtD,CAAC+I,GAAOC,CAAQ,EAAI7e,EAAAA,SAAS6V,EAAQ,OAAS,CAAC,EAC/C,CAACiJ,EAAUC,CAAW,EAAI/e,EAAAA,SAAS6V,EAAQ,UAAY,CAAC,EACxD,CAACmJ,GAAeC,CAAgB,EAAIjf,EAAAA,SACtC6V,EAAQ,eAAiB,EAAA,EAEvB,CAACqJ,GAAkBC,EAAmB,EAAInf,EAAAA,SAC5C6V,EAAQ,kBAAoB,EAAA,EAE1B,CAACuJ,GAAaC,CAAc,EAAIrf,EAAAA,SAAS,EAAK,EAC9C,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAE/B2Y,EAAU,OAAOhZ,CAAa,IAAM,OAAO+e,EAAe,MAAM,EAEhE9F,EACFuE,IAAoB,SACpB,OAAOxd,CAAa,IAAM,OAAO+e,EAAe,MAAM,GACtD,OAAO/e,CAAa,IAAM,OAAOyd,CAAY,EAE3CkC,EAAU3f,GAAiB+e,EAAe,SAAW,SAG3Dne,EAAAA,UAAU,IAAM,CACZoe,EAAkB9I,CAAO,EACzBgJ,EAAShJ,EAAQ,OAAS,CAAC,EAC3BkJ,EAAYlJ,EAAQ,UAAY,CAAC,EACjCoJ,EAAiBpJ,EAAQ,eAAiB,EAAK,EAC/CsJ,GAAoBtJ,EAAQ,kBAAoB,EAAK,CACzD,EAAG,CAACA,CAAO,CAAC,EAEZ,MAAMkD,EAAa,SAAY,CAE3B,GAAI,CAACpZ,EAAe,CAChBmB,GAAA,EACA,MACJ,CAEA,GAAIkd,EAAU,OAGd,MAAMuB,EAAgBP,GAChBQ,GAAmBN,GACnBO,GAAgBb,GAChBc,GAAmBZ,EAGnBa,GAAa,CAACX,GACdY,GAAgBD,GAAa,GAAQT,GACrCW,GAAWF,GACXF,GAAgB,EAChB,KAAK,IAAIA,GAAgB,EAAG,CAAC,EAC7BK,GACFH,IAAcH,GACR,KAAK,IAAIE,GAAmB,EAAG,CAAC,EAChCA,GAEVT,EAAiBU,EAAU,EAC3BR,GAAoBS,EAAa,EACjCf,EAASgB,EAAQ,EACjBd,EAAYe,EAAW,EAEvB,GAAI,CACA7B,EAAY,EAAI,EAChBjH,EAAS,EAAE,EAEX,MAAMgC,GAASuG,EAAgB,SAAW,OAEpC9e,GAAW,MAAMC,GAAI,KACvB,iBAAiBge,EAAe,EAAE,QAClC,CAAE,OAAA1F,EAAA,CAAO,EAGb,GAAIvY,GAAS,KAAK,QAAS,CACvB,KAAM,CACF,MAAOsf,GACP,SAAUC,GACV,cAAeC,GACf,iBAAkBC,EAAA,EAClBzf,GAAS,KAAK,KAClBoe,EAASkB,IAAe,CAAC,EACzBhB,EAAYiB,IAAkB,CAAC,EAC/Bf,EAAiBgB,IAAiB,EAAK,EACvCd,GAAoBe,IAAoB,EAAK,CACjD,MAEIjB,EAAiBM,CAAa,EAC9BJ,GAAoBK,EAAgB,EACpCX,EAASY,EAAa,EACtBV,EAAYW,EAAgB,CAEpC,OAAS/e,GAAK,CAEVse,EAAiBM,CAAa,EAC9BJ,GAAoBK,EAAgB,EACpCX,EAASY,EAAa,EACtBV,EAAYW,EAAgB,EAC5B1I,EAASpW,GAAgBD,EAAG,CAAC,CACjC,QAAA,CACIsd,EAAY,EAAK,CACrB,CACJ,EAEMkC,EAAgB,SAAY,CAE9B,GAAI,CAACxgB,EAAe,CAChBmB,GAAA,EACA,MACJ,CAEA,GAAIse,GAAa,OAGjB,MAAMG,EAAgBP,GAChBQ,GAAmBN,GACnBO,GAAgBb,GAChBc,GAAmBZ,EAGnBc,GAAgB,CAACV,GACjBS,GAAaC,GAAgB,GAAQZ,GACrCc,GAAcF,GACdF,GAAmB,EACnB,KAAK,IAAIA,GAAmB,EAAG,CAAC,EAChCG,GACFD,IAAiBL,EACX,KAAK,IAAIE,GAAgB,EAAG,CAAC,EAC7BA,GAEVR,EAAiBU,EAAU,EAC3BR,GAAoBS,EAAa,EACjCf,EAASgB,EAAQ,EACjBd,EAAYe,EAAW,EAEvB,GAAI,CACAT,EAAe,EAAI,EACnBrI,EAAS,EAAE,EAEX,MAAMgC,GAASwG,GAAmB,YAAc,UAE1C/e,GAAW,MAAMC,GAAI,KACvB,iBAAiBge,EAAe,EAAE,WAClC,CAAE,OAAA1F,EAAA,CAAO,EAGb,GAAIvY,GAAS,KAAK,QAAS,CACvB,KAAM,CACF,MAAOsf,GACP,SAAUC,GACV,cAAeC,GACf,iBAAkBC,EAAA,EAClBzf,GAAS,KAAK,KAClBoe,EAASkB,IAAe,CAAC,EACzBhB,EAAYiB,IAAkB,CAAC,EAC/Bf,EAAiBgB,IAAiB,EAAK,EACvCd,GAAoBe,IAAoB,EAAK,CACjD,MAEIjB,EAAiBM,CAAa,EAC9BJ,GAAoBK,EAAgB,EACpCX,EAASY,EAAa,EACtBV,EAAYW,EAAgB,CAEpC,OAAS/e,GAAK,CAEVse,EAAiBM,CAAa,EAC9BJ,GAAoBK,EAAgB,EACpCX,EAASY,EAAa,EACtBV,EAAYW,EAAgB,EAC5B1I,EAASpW,GAAgBD,EAAG,CAAC,CACjC,QAAA,CACI0e,EAAe,EAAK,CACxB,CACJ,EAGMe,EAAkB,SAAY,CAChC,GAAI,EAAAhC,GAAsBV,IAAU,GAEpC,GAAI,CAKA,GAJAW,EAAsB,EAAI,EAC1BrH,EAAS,EAAE,EAIP0H,EAAe,SAAWA,EAAe,UAAY,CAAA,GAAI,OAC3D,CACE,MAAMje,EAAW,MAAMC,GAAI,IACvB,iBAAiBge,EAAe,EAAE,UAAA,EAGtC,GAAIje,EAAS,KAAM,CACf,MAAM4f,GAAa5f,EAAS,KAE5B+c,IAAoBkB,EAAe,GAAI2B,EAAU,CACrD,CACJ,CACJ,OAAS1f,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACI0d,EAAsB,EAAK,CAC/B,CACJ,EAEMiC,EAAa,SAAY,CAC3B,GAAI,GAAChB,GAAWhB,GAEhB,GAAI,CACAC,GAAc,EAAI,EAClBvH,EAAS,EAAE,GAEM,MAAMtW,GAAI,KACvB,iBAAiBge,EAAe,EAAE,OAAA,GAGzB,KAAK,OAGtB,OAAS/d,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACI4d,GAAc,EAAK,CACvB,CACJ,EAEM/E,GAAe,SAAY,CAC7B,GAAI,GAACZ,GAAasF,IAEb,QAAQte,EAAE,0BAA0B,CAAC,EAI1C,GAAI,CACAue,EAAc,EAAI,EAClBnH,EAAS,EAAE,EAEX,MAAMtW,GAAI,OAAO,iBAAiBge,EAAe,EAAE,EAAE,EAIjDpB,IAAWoB,EAAe,EAAE,CAMpC,OAAS/d,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,EAC7Bwd,EAAc,EAAK,CACvB,CACJ,EAEMoC,EAAoBC,GAA4B,CAClD3C,EAAa,EAAK,EAClBc,EAAkB6B,CAAc,EAChCnD,IAAWmD,CAAc,CAC7B,EAEMC,GAAqBC,GAAwB,CAC/C3C,EAAc,EAAK,EAGnB,MAAM4C,GAAuB,CACzB,GAAGD,EACH,OACInF,GAAa,aACbA,GAAa,UACb,YACJ,iBAAkBA,GAAa,WAE/B,cAAemD,EAAe,MAAA,EAK5BxD,GAAWwC,IAAU,EAAIgB,EAAe,GAAKf,EAG7CiD,GAAgBlD,IAAU,EAAI,OAAYgB,EAAe,GAE/DnB,IAAUoD,GAAsBzF,GAAU0F,EAAa,CAC3D,EAEMC,EAAcC,GAETC,GAAcD,CAAU,EAGnC,OAAIpC,EAAe,SAAW,UAEtBnd,EAAAA,IAAC,MAAA,CACG,UAAU,4BACV,MAAO,CACH,WACImc,EAAQ,EAAI,GAAG,KAAK,IAAIA,EAAQ,GAAI,EAAE,CAAC,KAAO,IAClD,YAAa,OACb,WAAYA,EAAQ,EAAI,oBAAsB,MAAA,EAGlD,SAAAnc,EAAAA,IAAC,MAAA,CAAI,UAAU,6BACX,gBAAC,QAAA,CACG,SAAA,CAAAA,EAAAA,IAAC,IAAA,CAAE,UAAU,kBAAA,CAAmB,EAC/B3B,EAAE,2BAA2B,CAAA,CAAA,CAClC,CAAA,CACJ,CAAA,CAAA,EAMR2B,EAAAA,IAAC,MAAA,CAAI,GAAI,WAAWmd,EAAe,EAAE,GAAI,UAAU,oBAC/C,SAAArd,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CACG,aAAc,IAAMod,EAAa,EAAI,EACrC,aAAc,IAAMA,EAAa,EAAK,EAEtC,SAAA,CAAApd,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,uCACX,SAAAA,EAAAA,IAACwY,GAAA,CACG,YAAa2E,EAAe,OAC5B,WAAYA,EAAe,iBAC3B,KAAM,GACN,UAAU,gBAAA,CAAA,EAElB,SACC,MAAA,CACG,SAAA,CAAAnd,EAAAA,IAAC,QAAA,CAAM,UAAU,eACZ,SAAAmd,EAAe,OACpB,EACCE,GAAQ,GACLrd,EAAAA,IAAC,QAAA,CAAM,UAAU,8BACZ,SAAAqd,GACL,EAEJrd,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAkB,SAAA,IAAC,QAClC,QAAA,CAAM,UAAU,aACZ,SAAAsf,EAAWnC,EAAe,SAAS,EACxC,EACAnd,EAAAA,IAACqU,GAAA,CAAuB,QAAS8I,CAAA,CAAgB,EAChDA,EAAe,UACZrd,OAAC,QAAA,CAAM,UAAU,6BACb,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,qBAAA,CAAsB,EAClC3B,EAAE,mBAAmB,CAAA,CAAA,CAC1B,CAAA,CAAA,CAER,CAAA,EACJ,EAEAyB,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACI,SAAAqc,EACGrc,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAACub,GAAA,CACG,QAAS4B,EACT,SAAU6B,EACV,SAAU,IAAM1C,EAAa,EAAK,CAAA,CAAA,CACtC,CACJ,EAEAxc,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,MAAA,CACG,UAAU,uBACV,MAAO,CACH,WAAY,UAAA,EAId,SAEMmd,EAAe,QAAU,GACzBA,EAAe,cAGfrd,EAAAA,KAAA8T,EAAAA,SAAA,CAAE,SAAA,CAAA,IAEE5T,EAAAA,IAAC,OAAA,CAAK,UAAU,eAER,WAAe,cAEvB,EAAQ,IACPmd,EAAe,OAAA,CAAA,CACpB,EAEAA,EAAe,OAEpB,CAAA,EAGPrd,EAAAA,KAAC,MAAA,CAAI,UAAU,oDACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACX,SAAA,CAAAA,EAAAA,KAACC,EAAA,CACG,QAAQ,OACR,UAAU,0DACV,QAASyX,EACT,SAAUiF,EAEV,SAAA,CAAAzc,EAAAA,IAAC,IAAA,CACG,UAAW,MAAMyd,GAAgB,yBAA2B,mBAAmB,OAAA,CAAA,EAElFJ,GAAQ,EACHA,GACAhf,EAAE,gBAAgB,CAAA,CAAA,CAAA,EAG5ByB,EAAAA,KAACC,EAAA,CACG,QAAQ,OACR,UAAU,qDACV,QAAS6e,EACT,SAAUf,GAEV,SAAA,CAAA7d,EAAAA,IAAC,IAAA,CACG,UAAW,MAAM2d,GAAmB,2BAA6B,qBAAqB,IAAIJ,EAAW,EAAI,OAAS,EAAE,EAAA,CAAA,EAEvHA,EAAW,EAAIA,EAAW,EAAA,CAAA,CAAA,EAE9BpB,EAAQ,GACLnc,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,0DACV,QAAS,IAAM,CAEX,GAAI,CAAC3B,EAAe,CAChBmB,GAAA,EACA,MACJ,CACAid,EACI,CAACD,CAAA,CAET,EAEC,WAAE,kBAAkB,CAAA,CAAA,CACzB,EAER,GAEEnF,GAAWC,GAAa0G,IACtBd,GACInd,OAAC,MAAA,CAAI,UAAU,eACV,SAAA,CAAAsX,GACGpX,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,qDACV,QAAS,IACLuc,EACI,EAAA,EAIP,SAAAje,EACG,iBAAA,CACJ,CAAA,EAGPgZ,GACGrX,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,qDACV,QACIkY,GAEJ,SACI0E,EAGH,SACKte,EADLse,EAES,sBAGA,mBAHA,CAIJ,CAAA,EAIboB,GACG/d,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,UAAU,qDACV,QAASgf,EACT,SACIhC,EAGH,SACK1e,EADL0e,EAES,sBAGA,iBAHA,CAIJ,CAAA,CACV,CAAA,CAER,CAAA,CAAA,CAEZ,CAAA,CAAA,CACJ,CAAA,CAER,EAECvK,GACG1S,EAAAA,KAAC,MAAA,CACG,UAAU,oCACV,MAAO,CAAE,SAAU,MAAA,EAEnB,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAA,CAAkC,EAC9CwS,CAAA,CAAA,CAAA,EAIR+J,SACI,MAAA,CAAI,UAAU,OACX,SAAAzc,EAAAA,KAAC,MAAA,CAAI,UAAU,SACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,qBACX,SAAAA,EAAAA,IAAC,MAAA,CACG,UAAU,6EACV,MAAO,CACH,MAAO,OACP,OAAQ,OACR,WAAY,QAAS5B,GAAe,SAAA,GAAc,IAAI,WAAW,CAAC,EAAI,EAAK,GAAG,aAAA,EAGlF,SAAA4B,EAAAA,IAAC,OAAA,CACG,UAAU,yBACV,MAAO,CAAE,SAAU,MAAA,EACtB,SAAA,GAAA,CAAA,CAED,CAAA,EAER,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,cACX,SAAAA,EAAAA,IAAC0Z,GAAA,CACG,QAAAvb,EACA,SAAUgf,EAAe,GACzB,YAAaA,EAAe,OAC5B,YACIA,EAAe,QAAU,EACnB,aAAaA,EAAe,MAAM,MAClC,YAAYA,EAAe,MAAM,MAE3C,SAAU+B,GACV,SAAU,IACN1C,EAAc,EAAK,EAEvB,UAAU,YAAA,CAAA,CACd,CACJ,CAAA,CAAA,CACJ,CAAA,CACJ,CAAA,CAAA,CAER,CAAA,CAAA,CAAA,EAIHL,IAAU,IAAMgB,EAAe,UAAY,IAAI,OAAS,GACrDrd,EAAAA,KAAC,MAAA,CACG,UAAU,yBACV,aAAcqH,GAAKA,EAAE,gBAAA,EACrB,aAAcA,GAAKA,EAAE,gBAAA,EAEnB,SAAA,EAAAgW,EAAe,UAAY,CAAA,GAAI,IAAIsC,GACjCzf,EAAAA,IAAC2b,GAAA,CAEG,QAAS8D,EACT,QAAAthB,EACA,cAAAC,EACA,gBAAAwd,EACA,aAAAC,EACA,SAAAC,EACA,SAAAC,EACA,QAAAC,EACA,kBAAAC,EACA,cAAAC,EACA,MAAO,EACP,kBAAmBiB,EAAe,EAAA,EAZ7BsC,EAAa,EAAA,CAczB,EAGAtC,EAAe,SACXA,EAAe,UAAY,CAAA,GAAI,QAChCnd,EAAAA,IAACD,EAAA,CACG,QAAQ,OACR,KAAK,KACL,UAAU,wCACV,QAAS8e,EACT,SAAUhC,EAET,WACG/c,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,OAAA,CACG,UAAU,wCACV,KAAK,SACL,cAAY,MAAA,CAAA,EAEf3B,EAAE,mBAAmB,CAAA,CAAA,CAC1B,EAEAyB,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,IAAA,CAAE,UAAU,yBAAA,CAA0B,EACtC3B,EAAE,0BAA2B,CAC1B,MACI8e,EAAe,SACdA,EAAe,UAAY,CAAA,GACvB,MAAA,CACZ,CAAA,CAAA,CACL,CAAA,CAAA,CAER,CAAA,CAAA,CAER,CAAA,CAER,CAAA,CACJ,CAER,CCtoBO,SAASuC,GAAc,CAC1B,QAAAvhB,EACA,cAAAC,EACA,gBAAAwd,EACA,aAAAC,EACA,YAAA8D,EAAc,EAClB,EAAuB,CACnB,KAAM,CAAE,EAAAthB,CAAA,EAAMC,GAAA,EACR,CAAE,KAAM0b,CAAA,EAAgBC,GAAA,EACxB,CAAC2F,EAAUC,CAAW,EAAIphB,EAAAA,SAAoB,CAAA,CAAE,EAChD,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAI,EACrC,CAACqhB,EAAaC,CAAc,EAAIthB,EAAAA,SAAS,EAAK,EAC9C,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B,CAACuhB,EAAOC,CAAQ,EAAIxhB,EAAAA,SAAS,CAAC,EAC9B,CAACyhB,EAAMC,CAAO,EAAI1hB,EAAAA,SAAS,CAAC,EAC5B,CAAC2hB,EAASC,CAAU,EAAI5hB,EAAAA,SAAS,EAAK,EACtC,CAAC6hB,EAAQC,CAAS,EAAI9hB,EAAAA,SACxB,OAAA,EAEE,CAAC+hB,EAAYC,CAAa,EAAIhiB,EAAAA,SAAS,EAAK,EAG5CiiB,GAAiB,IAA4B,CAC/C,CAAE,MAAO,QAAS,MAAOriB,EAAE,kBAAkB,CAAA,EAC7C,CAAE,MAAO,SAAU,MAAOA,EAAE,mBAAmB,CAAA,EAC/C,CACI,MAAO,SACP,MAAOA,EAAE,mBAAmB,CAAA,CAChC,EAGEsiB,EAAelW,EAAAA,YACjB,MACImW,EAAU,EACVC,EAAS,GACTC,EAAaR,EACbS,IACC,CACD,GAAI,CACKF,EAGDd,EAAe,EAAI,EAFnBphB,EAAW,EAAI,EAInB8W,EAAS,EAAE,EAEX,MAAMuL,GAAc,IAAM,CACtB,OAAQF,EAAA,CACJ,IAAK,QACD,MAAO,CAAE,OAAQ,QAAS,UAAW,MAAA,EACzC,IAAK,SACD,MAAO,CAAE,OAAQ,YAAa,UAAW,MAAA,EAC7C,IAAK,SACD,MAAO,CAAE,OAAQ,YAAa,UAAW,KAAA,EAC7C,QACI,MAAO,CAAE,OAAQ,YAAa,UAAW,MAAA,CAAO,CAE5D,GAAA,EAIMG,EADY,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAC5B,IAAI,YAAY,EAC1CC,EAAaH,GAAgBE,EAG7BE,EACFP,IAAY,GAAK,CAACC,GAAUK,EAE1BhiB,EAAW,MAAMC,GAAI,IACvB,eAAehB,CAAO,YACtB,CACI,OAAQ,CACJ,KAAMyiB,EACN,SAAU,GACV,GAAGI,EACH,GAAIG,GAA2B,CAAE,WAAAD,CAAA,CAAW,CAChD,CACJ,EAGJ,GAAIhiB,EAAS,KAAM,CACf,KAAM,CACF,SAAUkiB,GACV,MAAOC,EACP,QAASC,GACT,KAAMC,CAAA,EACNriB,EAAS,KAGT2gB,EADAgB,EACYW,GAAQ,CAEhB,MAAM3f,GAAO,OAAO,SAAS,KACvBkf,GAAelf,GAAK,WAAW,WAAW,EAC1CA,GAAK,QAAQ,YAAa,EAAE,EAC5B,KAEN,OAAIkf,IAE2BK,GAAY,KACnCne,IAAKA,GAAE,KAAO8d,EAAA,EAQP,CAAC,GAHaS,EAAK,OACtBve,IAAKA,GAAE,KAAO8d,EAAA,EAEO,GAAGK,EAAW,EAKxC,CAAC,GAAGI,EAAM,GAAGJ,EAAW,CACnC,EAEYA,EAFX,EAKLnB,EAASoB,CAAQ,EACjBlB,EAAQoB,CAAO,EACflB,EAAWiB,EAAU,CACzB,CACJ,OAASliB,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACIT,EAAW,EAAK,EAChBohB,EAAe,EAAK,CACxB,CACJ,EACA,CAAC5hB,EAASmiB,CAAM,CAAA,EAIpBthB,EAAAA,UAAU,IAAM,CAEZ,MAAM6C,EAAO,OAAO,SAAS,KACvBkf,EAAelf,EAAK,WAAW,WAAW,EAC1CA,EAAK,QAAQ,YAAa,EAAE,EAC5B,OAGFkf,EACAJ,EAAa,EAAG,GAAOL,EAAQS,CAAY,EAE3CJ,EAAa,EAAG,GAAOL,CAAM,EAGjC,MAAMmB,EAAmB,IAAM,CAC3B,MAAMC,EAAU,OAAO,SAAS,KAChC,GAAIA,EAAQ,WAAW,WAAW,EAAG,CACjC,MAAMC,EAAkBD,EAAQ,QAAQ,YAAa,EAAE,EAE/B9B,EAAS,KAC7B3c,GAAKA,EAAE,KAAO0e,CAAA,EAOdC,EAAgBD,CAAe,EAH/BhB,EAAa,EAAG,GAAOL,EAAQqB,CAAe,CAKtD,CACJ,EAGA,cAAO,iBAAiB,aAAcF,CAAgB,EAC/C,IAAM,OAAO,oBAAoB,aAAcA,CAAgB,CAC1E,EAAG,CAACd,EAAcL,CAAM,CAAC,EAGzBthB,EAAAA,UAAU,IAAM,CACZ,MAAM6iB,EAA2BpZ,GAAiB,CAC1BA,EAMJ,QAAQ,UAAYtK,GAGpCwiB,EAAa,EAAG,GAAOL,CAAM,CACjC,EAEA,cAAO,iBACH,qBACAuB,CAAA,EAEG,IACH,OAAO,oBACH,qBACAA,CAAA,CAEZ,EAAG,CAAC1jB,EAASwiB,EAAcL,CAAM,CAAC,EAGlCthB,EAAAA,UAAU,IAAM,CACZ,MAAM6C,EAAO,OAAO,SAAS,KAC7B,GAAIA,EAAK,WAAW,WAAW,EAAG,CAC9B,MAAMkf,EAAelf,EAAK,QAAQ,YAAa,EAAE,EAE3B+d,EAAS,KAAK3c,GAAKA,EAAE,KAAO8d,CAAY,GAG1D,WAAW,IAAM,CACba,EAAgBb,CAAY,CAChC,EAAG,GAAG,CAEd,CACJ,EAAG,CAACnB,CAAQ,CAAC,EAGb,MAAMgC,EAAmBE,GAAsB,CAC3C,MAAMC,EAAU,SAAS,eAAe,WAAWD,CAAS,EAAE,EAC1DC,IACAA,EAAQ,eAAe,CAAE,SAAU,SAAU,MAAO,SAAU,EAE9DA,EAAQ,MAAM,gBAAkB,UAChC,WAAW,IAAM,CACbA,EAAQ,MAAM,gBAAkB,EACpC,EAAG,GAAI,EAEf,EAGMC,EAAsBvX,EAAAA,YACxB,CAACqX,EAAmBG,IAA2C,CAC3DpC,EAAY2B,GACRA,EAAK,IAAIlN,GAAW,CAChB,GAAIA,EAAQ,KAAOwN,EACf,OAAOG,EAAQ3N,CAAO,EAG1B,GAAIA,EAAQ,UAAYA,EAAQ,SAAS,OAAS,EAAG,CACjD,MAAM4N,EAAkB5N,EAAQ,SAAS,OACrC6N,EAAM,KAAOL,EAAYG,EAAQE,CAAK,EAAIA,CAAA,EAE9C,MAAO,CACH,GAAG7N,EACH,SAAU4N,CAAA,CAElB,CACA,OAAO5N,CACX,CAAC,CAAA,CAET,EACA,CAAA,CAAC,EAIC8N,EAAoB3X,EAAAA,YACtB,CAACkP,EAAkB0I,EAAmBhD,IAA2B,CAC7D,MAAMD,EAAuB,CACzB,GAAGiD,EACH,OACIrI,GAAa,aACbA,GAAa,UACb,YACJ,iBAAkBA,GAAa,UAAA,EAGnCgI,EAAoBrI,EAAUrF,GAAW,CACrC,MAAM9M,EAAW8M,EAAQ,UAAY,CAAA,EACrC,IAAIgO,EAEJ,GAAIjD,IAAkB,KAElBiD,EAAc,CAAClD,EAAsB,GAAG5X,CAAQ,UACzC6X,EAAe,CAEtB,MAAMkD,EAAc/a,EAAS,UACzB2a,GAASA,EAAM,KAAO9C,CAAA,EAEtBkD,IAAgB,GAChBD,EAAc,CACV,GAAG9a,EAAS,MAAM,EAAG+a,EAAc,CAAC,EACpCnD,EACA,GAAG5X,EAAS,MAAM+a,EAAc,CAAC,CAAA,EAIrCD,EAAc,CAAC,GAAG9a,EAAU4X,CAAoB,CAExD,MAEIkD,EAAc,CAAC,GAAG9a,EAAU4X,CAAoB,EAGpD,MAAO,CACH,GAAG9K,EACH,SAAUgO,EACV,SAAUhO,EAAQ,SAAW,GAAK,CAAA,CAE1C,CAAC,CACL,EACA,CAAC0F,EAAagI,CAAmB,CAAA,EAI/BQ,GAAyB/X,EAAAA,YAC3B,CAACkP,EAAkB8I,IAAoB,CACnCT,EAAoBrI,EAAUrF,GAAW,CACrC,MAAM4N,GAAmB5N,EAAQ,UAAY,CAAA,GAAI,OAC7C6N,GAASA,EAAM,KAAOM,CAAA,EAE1B,MAAO,CACH,GAAGnO,EACH,SAAU4N,EACV,QAAS,KAAK,KAAK5N,EAAQ,SAAW,GAAK,EAAG,CAAC,CAAA,CAEvD,CAAC,CACL,EACA,CAAC0N,CAAmB,CAAA,EAIlBU,EAA2BjY,EAAAA,YAC7B,CAACkP,EAAkBmF,IAA0B,CACzCkD,EAAoBrI,EAAUrF,GAAW,CAErC,MAAMqO,EAAc,IAAI,KACnBrO,EAAQ,UAAY,CAAA,GAAI,IAAI6N,GAASA,EAAM,EAAE,CAAA,EAE5CS,EAAkB9D,EAAW,OAC/B+D,GAAS,CAACF,EAAY,IAAIE,EAAM,EAAE,CAAA,EAGtC,MAAO,CACH,GAAGvO,EACH,SAAU,CAAC,GAAIA,EAAQ,UAAY,CAAA,EAAK,GAAGsO,CAAe,CAAA,CAElE,CAAC,CACL,EACA,CAACZ,CAAmB,CAAA,EAGlBc,EAAmBrY,EAAAA,YACrB,CAAC0U,EAAqBxF,EAAmB0F,IAA2B,CAChE,GAAI1F,EAEAyI,EAAkBzI,EAAUwF,EAAYE,CAAa,MAClD,CAEH,MAAMD,EAAuB,CACzB,GAAGD,EACH,OACInF,GAAa,aACbA,GAAa,UACb,YACJ,iBAAkBA,GAAa,UAAA,EAEnC6F,EAAY2B,GAAQ,CAACpC,EAAsB,GAAGoC,CAAI,CAAC,EACnDvB,EAASuB,GAAQA,EAAO,CAAC,CAC7B,CACJ,EACA,CAACxH,EAAaoI,CAAiB,CAAA,EAG7BW,EAAsBtY,EAAAA,YACvBwU,GAA4B,CACzB+C,EAAoB/C,EAAe,GAAI9B,IAAmB,CACtD,GAAGA,EACH,QAAS8B,EAAe,QACxB,UAAWA,EAAe,SAAA,EAC5B,CACN,EACA,CAAC+C,CAAmB,CAAA,EAGlBgB,GAAsBvY,cAAaqX,GAA+B,CACpE,MAAMmB,EACF,OAAOnB,GAAc,SAAWA,EAAYA,EAAU,SAAA,EAGpDoB,EAA4BtD,GACvBA,EACF,IAAItL,GAAW,CAEZ,GAAIA,EAAQ,KAAO2O,EACf,OAAO,KAIX,GAAI3O,EAAQ,UAAYA,EAAQ,SAAS,OAAS,EAAG,CAIjD,MAAM6O,EAHkBD,EACpB5O,EAAQ,QAAA,EAE6B,UAC5B6N,IAAU,IAAA,EAGvB,MAAO,CACH,GAAG7N,EACH,SAAU6O,EACV,QAASA,EAAiB,MAAA,CAElC,CAEA,OAAO7O,CACX,CAAC,EACA,OAAOA,GAAWA,IAAY,IAAI,EAG3CuL,EAAY2B,GAAQ,CAChB,MAAM4B,EAAkBF,EAAyB1B,CAAI,EAGrD,OADoBA,EAAK,KAAKlN,GAAWA,EAAQ,KAAO2O,CAAU,GAE9DhD,EAASoD,GAAaA,EAAY,CAAC,EAEhCD,CACX,CAAC,CACL,EAAG,CAAA,CAAE,EAECE,EAAiB,IAAM,CACrBlD,GAAW,CAACN,GACZa,EAAaT,EAAO,EAAG,EAAI,CAEnC,EAEMqD,GAAoBC,GAA6C,CAC/DA,IAAclD,IACdC,EAAUiD,CAAS,EACnBrD,EAAQ,CAAC,EAEjB,EAEA,GAAIzhB,EACA,OACIoB,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACX,SAAA,CAAAE,EAAAA,IAAC,OAAI,UAAU,iCACX,SAAAA,MAAC,MAAA,CAAI,UAAU,+BACX,SAAAA,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAEhC,CAAA,CACJ,QAEC,MAAA,CAAI,UAAU,OACX,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,SACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAAC,MAAA,CACG,UAAU,6BACV,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAA,CAAO,CAAA,EAE/C,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,+BACX,SAAAA,EAAAA,IAAC,MAAA,CACG,UAAU,qBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,CAC3B,CACL,CAAA,CAAA,CACJ,CAAA,CACJ,EAGC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC6J,EAAG/H,UAClB,MAAA,CAAY,UAAU,wBACnB,SAAAhC,EAAAA,KAAC,MAAA,CAAI,UAAU,SACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAAC,MAAA,CACG,UAAU,6BACV,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAA,CAAO,CAAA,EAE/C,EACAF,EAAAA,KAAC,MAAA,CAAI,UAAU,cACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oBACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,CAC3B,EACL,EACAA,EAAAA,IAAC,MAAA,CACG,UAAU,0BACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,yBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BF,EAAAA,KAAC,MAAA,CAAI,UAAU,eACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,CAC3B,CAAA,CACL,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EA1CM8B,CA2CV,CACH,CAAA,EACL,EAIR,GAAI0Q,EACA,OACI1S,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACX,SAAA,CAAAA,EAAAA,KAACmW,GAAA,CAAM,QAAQ,UAAU,UAAU,4BAC/B,SAAA,CAAAjW,EAAAA,IAAC,IAAA,CAAE,UAAU,iCAAA,CAAkC,SAC9C,MAAA,CACG,SAAA,CAAAA,EAAAA,IAAC,SAAA,CAAQ,SAAA3B,EAAE,sBAAsB,CAAA,CAAE,EACnC2B,EAAAA,IAAC,MAAA,CAAI,UAAU,QAAS,SAAAwS,CAAA,CAAM,CAAA,CAAA,CAClC,CAAA,EACJ,EACAxS,EAAAA,IAAC,MAAA,CAAI,UAAU,mBACX,SAAAF,EAAAA,KAACC,EAAA,CACG,QAAQ,kBACR,QAAS,IAAM4gB,EAAA,EAEf,SAAA,CAAA3gB,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAAA,CAA6B,EACzC3B,EAAE,qBAAqB,CAAA,CAAA,CAAA,CAC5B,CACJ,CAAA,EACJ,EAKR,MAAMolB,GAA0B,IAC5B3jB,EAAAA,KAAC,MAAA,CACG,UAAU,oEACV,MAAO,CAAE,OAAQ,SAAA,EACjB,QAAS,IAAM2gB,EAAc,CAACD,CAAU,EAExC,SAAA,CAAA1gB,EAAAA,KAAC,MAAA,CAAI,UAAU,4BACX,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,sCAAA,CAAuC,EACpDA,EAAAA,IAAC,OAAA,CAAK,UAAU,cACX,WAAE,mBAAoB,CACnB,MAAOggB,EAAM,eAAA,EACb,OAAQA,IAAU,EAAI,IAAM,EAAA,CAC/B,CAAA,CACL,CAAA,EACJ,EACAhgB,EAAAA,IAAC,IAAA,CACG,UAAW,iBAAiBwgB,EAAa,KAAO,MAAM,aAAA,CAAA,CACzD,CAAA,CAAA,EAIHkD,GAAwB,IAC1B5jB,EAAAA,KAAA8T,EAAAA,SAAA,CAEI,SAAA,CAAA9T,EAAAA,KAAC,MAAA,CAAI,UAAU,yDACV,SAAA,CAAA,CAAC6f,GACE3f,EAAAA,IAAC,KAAA,CAAG,UAAU,mBACT,WAAE,mBAAoB,CACnB,MAAOggB,EAAM,eAAA,EACb,OAAQA,IAAU,EAAI,IAAM,EAAA,CAC/B,EACL,EAEJhgB,EAAAA,IAAC2jB,GAAA,CACI,SAAAjD,GAAA,EAAiB,IAAIkD,GAClB5jB,EAAAA,IAACD,EAAA,CACG,KAAK,KAEL,QACIugB,IAAWsD,EAAO,MACZ,YACA,oBAEV,QAAS,IAAML,GAAiBK,EAAO,KAAK,EAE3C,SAAAA,EAAO,KAAA,EARHA,EAAO,KAAA,CAUnB,CAAA,CACL,CAAA,EACJ,EAEA5jB,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,SACX,SAAAA,MAAC,MAAA,CAAI,UAAU,cACX,SAAAA,EAAAA,IAAC0Z,GAAA,CACG,QAAAvb,EACA,SAAU2kB,EACV,YAEUzkB,EADND,EACQ,wBACA,4BADuB,CACK,CAAA,CAE5C,CACJ,EACJ,EACJ,EAGA4B,EAAAA,IAAC,OAAI,UAAU,gBACV,WAAS,OAAS,EACf4f,EAAS,IAAItL,GACTtU,EAAAA,IAAC2b,GAAA,CAEG,QAAArH,EACA,QAAAnW,EACA,cAAAC,EACA,gBAAAwd,EACA,aAAAC,EACA,SAAUkH,EACV,SAAUC,GACV,QAASF,EACT,kBAAmBJ,EACnB,cAAeF,GACf,MAAO,CAAA,EAXFlO,EAAQ,EAAA,CAapB,EAGDxU,EAAAA,KAAC,MAAA,CAAI,UAAU,mBACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,OACX,SAAAA,EAAAA,IAAC,IAAA,CACG,UAAU,oCACV,MAAO,CAAE,SAAU,MAAA,CAAO,CAAA,EAElC,QACC,KAAA,CAAG,UAAU,kBACT,SAAA3B,EAAE,uBAAuB,EAC9B,EACA2B,EAAAA,IAAC,IAAA,CAAE,UAAU,kBACR,SACK3B,EADLD,EACO,qBACA,4BADoB,CACQ,CACxC,EACC,CAACA,GACE4B,EAAAA,IAACD,EAAA,CACG,QAAQ,kBACR,KAAK,KACL,QAAS,IAAM,CACXR,GACI,CACI,OAAQ,UACR,SAAUpB,CAAA,EAEd,OAAO,SAAS,SACZ,OAAO,SAAS,MAAA,CAE5B,EACA,UAAU,oBAET,WAAE,yBAAyB,CAAA,CAAA,CAChC,CAAA,CAER,EAER,EAGCiiB,GAAWR,EAAS,OAAS,GAC1B5f,EAAAA,IAAC,MAAA,CAAI,UAAU,mBACX,SAAAA,EAAAA,IAACD,EAAA,CACG,QAAQ,oBACR,QAASujB,EACT,SAAUxD,EACV,UAAU,oBACV,MAAO,CAAE,SAAU,OAAA,EAElB,WACGhgB,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC8T,GAAA,CACG,GAAG,OACH,UAAU,SACV,KAAK,KACL,KAAK,SACL,cAAY,OACZ,UAAU,MAAA,CAAA,EAEbzV,EAAE,4BAA4B,CAAA,CAAA,CACnC,EAEAyB,EAAAA,KAAA8T,EAAAA,SAAA,CACI,SAAA,CAAA5T,EAAAA,IAAC,IAAA,CAAE,UAAU,uBAAA,CAAwB,EACpC3B,EAAE,qBAAqB,CAAA,CAAA,CAC5B,CAAA,CAAA,EAGZ,EAIH,CAAC+hB,GAAWR,EAAS,OAAS,IAC3B5f,EAAAA,IAAC,MAAA,CAAI,UAAU,mCACX,SAAAF,EAAAA,KAAC,QAAA,CAAM,UAAU,aACb,SAAA,CAAAE,EAAAA,IAAC,IAAA,CAAE,UAAU,yBAAA,CAA0B,EACtC3B,EAAE,uBAAuB,CAAA,CAAA,CAC9B,CAAA,CACJ,CAAA,EAER,EAGJ,OAAIshB,EAEI7f,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACV,SAAA,CAAA2jB,GAAA,EACAjD,GACGxgB,EAAAA,IAAC,MAAA,CAAI,UAAU,OAAQ,aAAsB,CAAE,CAAA,EAEvD,EAIDA,EAAAA,IAAC,MAAA,CAAI,UAAU,sBAAuB,cAAwB,CACzE,CCzsBO,SAAS6jB,GAAsB1lB,EAAyB,CAC3D,MAAO,UAAU,mBAAmBA,CAAO,CAAC,iBAChD,CAEA,SAAS2lB,GACLpP,EACsC,CACtC,GAAKA,EAEL,MAAO,CACH,GAAIA,EAAM,GACV,MAAOA,EAAM,MACb,KAAMmP,GAAsBnP,EAAM,EAAE,CAAA,CAE5C,CAEO,SAASqP,GAA6B,CACzC,aAAAC,EACA,WAAAC,CACJ,EAAuE,CACnE,GAAID,IAAiB,UAAW,OAAO,KAEvC,MAAME,EAAQ,CACV,SAAUJ,GAAiBG,GAAY,QAAQ,EAC/C,KAAMH,GAAiBG,GAAY,IAAI,CAAA,EAG3C,OAAOC,EAAM,UAAYA,EAAM,KAAOA,EAAQ,IAClD,CCSO,SAASC,GAAc,CAAE,QAAAhmB,EAAS,aAAA6lB,GAAoC,CACzE,KAAM,CAAE,EAAA3lB,CAAA,EAAMC,GAAA,EACR8lB,EAAe,EAAQJ,EACvBK,EAAe7Z,EAAAA,OAAuB,IAAI,EAC1C,CAAC8Z,EAAkBC,CAAmB,EAAI9lB,EAAAA,SAC5C,CAAA,CAAC,EAEC,CAAC+lB,EAAoBC,CAAqB,EAAIhmB,EAAAA,SAElD,CAAA,CAAE,EACE,CAACimB,EAAgBC,CAAiB,EAAIlmB,EAAAA,SAGzC,CAAA,CAAE,EACC,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAI,EACrC,CAAC+T,EAAOiD,CAAQ,EAAIhX,EAAAA,SAAS,EAAE,EAC/B,CAACmmB,EAAYC,CAAa,EAAIpmB,EAAAA,SAAS,EAAK,EAC5C,CAACqmB,EAAcC,CAAe,EAAItmB,EAAAA,SAAS,EAAE,EAGnDO,EAAAA,UAAU,IAAM,CACZ,MAAMgmB,EAAYX,EAAa,QAC/B,GAAI,CAACW,EAAW,OAGhB,MAAMC,EAAkB,IAAM,CAC1B,MAAMC,EAASF,EAAU,cACzB,OAAKE,EAGS,OAAO,iBAAiBA,CAAM,EAC/B,UAAY,OAJL,EAKxB,EAGA,GAAID,IAAmB,CACnBJ,EAAc,EAAI,EAClB,MACJ,CAGA,MAAMM,EAAW,IAAI,eAAe,IAAM,CAClCF,MACAJ,EAAc,EAAI,EAClBM,EAAS,WAAA,EAEjB,CAAC,EAED,OAAAA,EAAS,QAAQ,SAAS,IAAI,EAEvB,IAAMA,EAAS,WAAA,CAC1B,EAAG,CAAA,CAAE,EAELnmB,EAAAA,UAAU,IAAM,CACR4lB,GAAczmB,IACd4mB,EAAgB,EAAE,EAClBK,EAAA,EAER,EAAG,CAACR,EAAYzmB,CAAO,CAAC,EAExB,MAAMinB,EAAoB,SAAY,CAClC,GAAI,CACAzmB,EAAW,EAAI,EACf8W,EAAS,EAAE,EAEX,MAAMvW,EAAW,MAAMC,GAAI,IACvB,eAAehB,CAAO,UAAA,EAGtBe,EAAS,KAAK,UACdqlB,EAAoBrlB,EAAS,KAAK,KAAK,UAAU,EACjDulB,EACIL,EAAe,CAAA,EAAKllB,EAAS,KAAK,KAAK,YAAA,EAE3CylB,EAAkBzlB,EAAS,KAAK,KAAK,YAAc,CAAA,CAAE,EAE7D,OAASE,EAAK,CACVqW,EAASpW,GAAgBD,CAAG,CAAC,CACjC,QAAA,CACIT,EAAW,EAAK,CACpB,CACJ,EAEM0mB,EAAe5hB,GAAgB,CACjC,MAAM6hB,EAAU,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACpDC,EAAU,IAAI,IAChBC,GAAqB/hB,CAAG,EACxB,OAAO,SAAS,MAAA,EAEpB,OAAIugB,GAAcuB,EAAQ,aAAa,IAAI,SAAUvB,CAAY,EAC7DsB,EAAQ,IAAI,UAAU,GACtBC,EAAQ,aAAa,IAAI,WAAYD,EAAQ,IAAI,UAAU,GAAK,EAAE,EAElEA,EAAQ,IAAI,MAAM,GAClBC,EAAQ,aAAa,IAAI,OAAQD,EAAQ,IAAI,MAAM,GAAK,EAAE,EAEvD,GAAGC,EAAQ,QAAQ,GAAGA,EAAQ,MAAM,EAC/C,EAEMtB,EAAaF,GAA6B,CAC5C,aAAAC,EACA,WAAYU,CAAA,CACf,EAEKe,EAAuB,CACzBC,EACAhd,EACAid,IAEA7lB,EAAAA,KAAC,IAAA,CACG,KAAM4I,EAAK,KACX,UAAW,qDAAqDid,CAAS,iCAEzE,SAAA,CAAA3lB,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAA0lB,EAAM,EAC1C1lB,EAAAA,IAAC,OAAA,CAAK,UAAU,iCAAkC,WAAK,KAAA,CAAM,CAAA,CAAA,CAAA,EAI/D4lB,EAAmBlR,GACrB5U,EAAAA,KAAC,IAAA,CAEG,KAAMulB,EAAY3Q,EAAM,GAAG,EAC3B,UAAU,6CAGV,SAAA,CAAA5U,EAAAA,KAAC,MAAA,CAAI,UAAU,qDACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,IACI0U,EAAM,eAAe,QACrB2D,GAAQ,0BAA0B,EAEtC,IAAK3D,EAAM,MACX,UAAU,UACV,MAAO,CACH,MAAO,QACP,OAAQ,OACR,UAAW,QACX,YAAa,MAAA,EAEjB,QAASjM,GAAS,CACdA,EAAM,cAAc,QAAU,KAC9BA,EAAM,cAAc,IAAMod,GAAc,OAAO,CACnD,CAAA,CAAA,EAEHnR,EAAM,UACH1U,EAAAA,IAAC,OAAA,CACG,UAAU,mEACV,MAAO,CACH,SAAU,UACV,OAAQ,KAAA,EAGX,SAAA8lB,GAAepR,EAAM,QAAQ,CAAA,CAAA,CAClC,EAER,EAGA5U,EAAAA,KAAC,MAAA,CAAI,UAAU,yDACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CAAI,UAAU,uCACV,SAAA0U,EAAM,MACX,EACA5U,EAAAA,KAAC,MAAA,CACG,UAAU,uCACV,MAAO,CAAE,SAAU,QAAA,EAEnB,SAAA,CAAAE,MAAC,OAAA,CACI,SAAA3B,EACG,iBACA,CAAE,MAAOqW,EAAM,KAAA,EACf,CAAE,MAAOA,EAAM,KAAA,CAAM,EAE7B,EACA1U,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,IAAC,EACxBA,MAAC,QACI,SAAA0U,EAAM,YACD8K,GAAc9K,EAAM,WAAW,EAC/B,EAAA,CACV,CAAA,CAAA,CAAA,CACJ,CAAA,CACJ,CAAA,CAAA,EA5DKA,EAAM,EAAA,EAgEnB,GAAI,CAACkQ,EACD,OAAO5kB,EAAAA,IAAC,MAAA,CAAI,IAAKqkB,CAAA,CAAc,EAGnC,GAAI3lB,EACA,aACK,MAAA,CAAI,IAAK2lB,EACL,SAAA,CAAC,EAAG,EAAG,EAAG,EAAG,CAAC,EAAE,IAAIviB,GACjBhC,EAAAA,KAAC,MAAA,CAAY,UAAU,cACnB,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,UAAU,mBACV,MAAO,CACH,MAAO,QACP,OAAQ,OACR,aAAc,KAAA,CAClB,CAAA,EAEJF,EAAAA,KAAC,MAAA,CAAI,UAAU,cACX,SAAA,CAAAE,EAAAA,IAAC,MAAA,CACG,UAAU,0BACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,yBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,EAE5BA,EAAAA,IAAC,MAAA,CACG,UAAU,oBACV,MAAO,CAAE,OAAQ,MAAA,CAAO,CAAA,CAC3B,CAAA,CACL,CAAA,GAtBM8B,CAuBV,CACH,EACL,EAIR,MAAMikB,EAAczB,EAAiB,OAASE,EAAmB,OAEjE,GAAIhS,GAASuT,IAAgB,EACzB,OACI/lB,EAAAA,IAAC,MAAA,CAAI,IAAKqkB,EACN,eAAC,MAAA,CAAI,UAAU,8BACX,SAAArkB,EAAAA,IAAC,QAAA,CAAO,SAAA3B,EAAE,0BAA0B,CAAA,CAAE,EAC1C,EACJ,EAKR,MAAM2nB,GAAY,CAAC,GAAG1B,EAAkB,GAAGE,CAAkB,EAAE,MAAM,EAAG,EAAE,EAE1E,OACI1kB,EAAAA,KAAC,MAAA,CAAI,IAAKukB,EACL,SAAA,CAAAJ,GACGnkB,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACV,SAAA,CAAAmkB,EAAW,SACRwB,EACI,QACAxB,EAAW,SACX,OAAA,EAGJjkB,EAAAA,IAAC,OAAA,CAAK,UAAU,iCAAA,CAAkC,EAErDikB,EAAW,KACRwB,EACI,QACAxB,EAAW,KACX,KAAA,EAGJjkB,MAAC,OAAA,CAAK,UAAU,iCAAA,CAAkC,CAAA,EAE1D,EAEHgmB,GAAU,MAAM,EAAGlB,CAAY,EAAE,IAAIc,CAAe,EACpDd,EAAekB,GAAU,QACtBhmB,EAAAA,IAAC,SAAA,CACG,KAAK,SACL,UAAU,kCACV,QAAS,IAAM+kB,EAAgBxhB,GAASA,EAAQ,EAAE,EAEjD,WAAE,oBAAoB,CAAA,CAAA,CAC3B,EAER,CAER,CCrUA0iB,GAAO,uBAAyB/pB,GAA+B,CAC3D,MAAMgqB,EACFhqB,EAAM,UAAYiqB,GAAoBjqB,EAAM,QAAQ,EAC9CA,EAAM,SACN,OAEV,OACI8D,EAAAA,IAAComB,IAAa,gBAAiBF,EAC3B,eAACtN,GAAA,CAAgB,GAAG1c,EAAO,SAAAgqB,CAAA,CAAoB,CAAA,CACnD,CAER,CAAC,EAGDD,GAAO,2BAA6B/pB,GAA+B,CAC/D,MAAMgqB,EACFhqB,EAAM,UAAYiqB,GAAoBjqB,EAAM,QAAQ,EAC9CA,EAAM,SACN,OAEV,OACI8D,EAAAA,IAAComB,GAAA,CAAa,gBAAiBF,EAC3B,SAAAlmB,EAAAA,IAAC0f,IAAe,GAAGxjB,EAAO,YAAa,EAAA,CAAO,CAAA,CAClD,CAER,CAAC,EAGD+pB,GAAO,kCAAoC/pB,GAA+B,CACtE,MAAMgqB,EACFhqB,EAAM,UAAYiqB,GAAoBjqB,EAAM,QAAQ,EAC9CA,EAAM,SACN,OAEV,OACI8D,EAAAA,IAAComB,GAAA,CAAa,gBAAiBF,EAC3B,SAAAlmB,EAAAA,IAAC0f,IAAe,GAAGxjB,EAAO,YAAa,EAAA,CAAM,CAAA,CACjD,CAER,CAAC,EAGD+pB,GAAO,2BAA6B/pB,GAA+B,CAC/D,MAAMgqB,EACFhqB,EAAM,UAAYiqB,GAAoBjqB,EAAM,QAAQ,EAC9CA,EAAM,SACN,OAEV,OACI8D,MAAComB,IAAa,gBAAiBF,EAC3B,eAAC/B,GAAA,CAAe,GAAGjoB,EAAO,CAAA,CAC9B,CAER,CAAC,EAGD+pB,GAAO,kCAAoC/pB,GAA+B,CACtE,MAAMgqB,EACFhqB,EAAM,UAAYiqB,GAAoBjqB,EAAM,QAAQ,EAC9CA,EAAM,SACN,OAEV,OACI8D,MAAComB,IAAa,gBAAiBF,EAC3B,eAAC/B,GAAA,CAAe,GAAGjoB,EAAO,CAAA,CAC9B,CAER,CAAC","x_google_ignoreList":[0,1,2,3,5,6,7,8,9]}